From e3781521d70779484ad052291b9c1100e0067251 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 14:28:04 +0200 Subject: [PATCH 01/38] optimize (part2) --- platformio.ini | 20 ++---- platformio_lib.ini | 139 +++++++++++++++++++++++++++++++++++++ platformio_tasmota_env.ini | 60 +--------------- 3 files changed, 144 insertions(+), 75 deletions(-) create mode 100644 platformio_lib.ini diff --git a/platformio.ini b/platformio.ini index a14faae3e..8d422c75e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -59,6 +59,7 @@ build_cache_dir = .cache extra_configs = platformio_tasmota32.ini platformio_tasmota_env.ini platformio_tasmota_env32.ini + platformio_lib.ini platformio_override.ini default_envs = ${build_envs.default_envs} @@ -123,22 +124,9 @@ build_flags = ${esp_defaults.build_flags} -DPSTR_ALIGN=1 ; restrict to minimal mime-types -DMIMETYPE_MINIMAL - -lib_ignore = Servo(esp8266) - ESP8266AVRISP - ESP8266LLMNR - ESP8266NetBIOS - ESP8266SSDP - ESP8266WiFiMesh - Ethernet(esp8266) - GDBStub - TFT_Touch_Shield_V2 - ESP8266WiFiMesh - EspSoftwareSerial - SPISlave - Hash - - +lib_deps = IRremoteESP8266 +lib_ignore = ${lib_EP8266_default.lib_ignore} + [irremoteesp_full] build_flags = -DUSE_IR_REMOTE_FULL -U_IR_ENABLE_DEFAULT_ diff --git a/platformio_lib.ini b/platformio_lib.ini new file mode 100644 index 000000000..0aa58b43e --- /dev/null +++ b/platformio_lib.ini @@ -0,0 +1,139 @@ +; ******************************************************** +; *** PlatformIO Configuration for Library DISABLING *** +; ******************************************************** + + +[lib_EP8266_default] +lib_ignore = + Servo(esp8266) + ESP8266AVRISP + ESP8266LLMNR + ESP8266NetBIOS + ESP8266SSDP + SP8266WiFiMesh + Ethernet(esp8266) + GDBStub + TFT_Touch_Shield_V2 + ESP8266HTTPUpdateServer + ESP8266WiFiMesh + EspSoftwareSerial + SPISlave + Hash + +[lib_EP8266] +lib_ignore = + ${lib_EP8266_default.lib_ignore} + LittleFS(esp8266) + +[lib_all_EP8266] +lib_ignore = + ${lib_EP8266.lib_ignore} + ${lib_Tasmota.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} + ${lib_ir.lib_ignore} + ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_Tasmota] +lib_ignore = + NTP Library + base64 + Unishox Compressor Decompressor highly customized and optimized for ESP8266 and Tasmota + ;ESP KNX IP Library + UdpListener + +[lib_SSL] +lib_ignore = + BearSSL + +[lib_display] +lib_ignore = + LinkedList + Adafruit BusIO + Adafruit GFX Library + Arduino ST7789 Library + Adafruit ILI9341 + ILI9488 + RA8876 + Adafruit LED Backpack Library + Waveshare esp 2.9 inch e-paper display driver + LiquidCrystal_I2C + Adafruit SH1106-gemu-1.0 + Adafruit SSD1306 + SSD3115 + I2Cdevlib-Core + +[lib_i2c_sensor] +lib_ignore = + LinkedList + Adafruit BusIO + I2Cdevlib-Core + Adafruit CCS811 Library + Adafruit MAX31865 library + Adafruit MCP9808 Library + Adafruit SGP30 Sensor + Adafruit TSL2591 + Joba Tsl2561 Library + Joba_Tsl2561 + Adafruit VEML7700 Library + MPU6050 I2C + LinkedList + LOLIN_HP303B + Grove - Multichannel Gas Sensor + Mutichannel_Gas_Sensor + OneWire + VL53L0X + VL53L1X + MLX90640 + FrogmoreScd30 + BME680 + FT5206_Library + HPMA115S0 Arduino Library + +[lib_sensor] +lib_ignore = + NewPing + +[lib_rf] +lib_ignore = + rc-switch + RF24 + C2Programmer + KeeloqLib + +[lib_ir] +lib_ignore = + IRremoteESP8266 + +[lib_light] +lib_ignore = + NeoPixelBus + +[lib_audio] +lib_ignore = + ESP8266Audio + ESP8266SAM + +[lib_serial] +lib_ignore = + LibTeleinfo + TasmotaSerial + TasmotaModbus + +[lib_other] +lib_ignore = + OpenTherm Library + A4988_Stepper + EEPROM 24C128 + +[lib_SPI] +lib_ignore = + cc1101 + EEPROM 24C128 \ No newline at end of file diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index c28667685..e3ead2b55 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -21,65 +21,7 @@ lib_ignore = ${common.lib_ignore} [env:tasmota-minimal] build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -lib_ignore = ${common.lib_ignore} - LittleFS(esp8266) - A4988_Stepper - Adafruit BusIO - Adafruit CCS811 Library - Adafruit GFX Library - Arduino ST7789 Library - Adafruit ILI9341 - ILI9488 - RA8876 - Adafruit LED Backpack Library - Waveshare esp 2.9 inch e-paper display driver - LiquidCrystal_I2C - Adafruit MAX31865 library - Adafruit MCP9808 Library - Adafruit SGP30 Sensor - Adafruit SH1106-gemu-1.0 - Adafruit SSD1306 - Adafruit TSL2591 - Joba Tsl2561 Library - Joba_Tsl2561 - Adafruit VEML7700 Library - SSD3115 - NTP Library - base64 - C2Programmer - ;ESP KNX IP Library - I2Cdevlib-Core - MPU6050 I2C - LibTeleinfo - LinkedList - LOLIN_HP303B - Mutichannel_Gas_Sensor - NewPing - OneWire - OpenTherm Library - rc-switch - RF24 - TasmotaModbus - TasmotaSerial - UdpListener - VL53L0X - VL53L1X - MLX90640 - FrogmoreScd30 - cc1101 - EEPROM 24C128 - BME680 - FrogmoreScd30 - FT5206_Library - HPMA115S0 Arduino Library - Grove - Multichannel Gas Sensor - BearSSL - OneWire - IRremoteESP8266 - ESP8266Audio - ESP8266SAM - KeeloqLib - NeoPixelBus +lib_ignore = ${lib_all_EP8266.lib_ignore} [env:tasmota-lite] build_flags = ${common.build_flags} -DFIRMWARE_LITE From 52f1d217746d48631e96934bf95b26f163d25ca3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:04:31 +0200 Subject: [PATCH 02/38] Lib ignore Optimize (part 3) --- platformio.ini | 1 - platformio_lib.ini | 173 ++++++++++++++++++++++++++++++++++--- platformio_tasmota_env.ini | 33 ++++++- 3 files changed, 192 insertions(+), 15 deletions(-) diff --git a/platformio.ini b/platformio.ini index 8d422c75e..c9c78c297 100644 --- a/platformio.ini +++ b/platformio.ini @@ -124,7 +124,6 @@ build_flags = ${esp_defaults.build_flags} -DPSTR_ALIGN=1 ; restrict to minimal mime-types -DMIMETYPE_MINIMAL -lib_deps = IRremoteESP8266 lib_ignore = ${lib_EP8266_default.lib_ignore} [irremoteesp_full] diff --git a/platformio_lib.ini b/platformio_lib.ini index 0aa58b43e..6284d52c4 100644 --- a/platformio_lib.ini +++ b/platformio_lib.ini @@ -1,7 +1,150 @@ ; ******************************************************** ; *** PlatformIO Configuration for Library DISABLING *** ; ******************************************************** +; +; +; *********************************************************************** +; *** Config Setup for disabling for the different Tasmota variants *** +; *********************************************************************** +[lib_Tasmota] +; Disable not needed libs to build TASMOTA, IR-CUSTOM and all language variants +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} +; ${lib_ESP_ir.lib_ignore} +; ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_minimal] +; Disable not needed libs to build TASMOTA-minimal +lib_ignore = + ${lib_all_EP8266.lib_ignore} + +[lib_lite] +; Disable not needed libs to build TASMOTA-lite +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} + ${lib_ESP_ir.lib_ignore} + ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_knx] +; Disable not needed libs to build TASMOTA-KNX +lib_ignore = + ;${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} +; ${lib_ESP_ir.lib_ignore} +; ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_sensors] +; Disable not needed libs to build TASMOTA-sensors +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} +; ${lib_i2c_sensor.lib_ignore} +; ${lib_sensor.lib_ignore} +; ${lib_rf.lib_ignore} +; ${lib_ESP_ir.lib_ignore} +; ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_display] +; Disable not needed libs to build TASMOTA-display +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} +; ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} +; ${lib_ESP_ir.lib_ignore} +; ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + +[lib_ir] +; Disable not needed libs to build TASMOTA-IR +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} +; ${lib_ESP_ir.lib_ignore} + ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + + +[lib_zbbridge] +; Disable not needed libs to build TASMOTA-ZbBridge +lib_ignore = + ${lib_ESP_knx.lib_ignore} + ${lib_EP8266.lib_ignore} +; ${lib_custom.lib_ignore} + ${lib_SSL.lib_ignore} + ${lib_ESP_display.lib_ignore} + ${lib_i2c_sensor.lib_ignore} + ${lib_sensor.lib_ignore} + ${lib_rf.lib_ignore} + ${lib_ESP_ir.lib_ignore} + ${lib_light.lib_ignore} + ${lib_audio.lib_ignore} + ${lib_serial.lib_ignore} + ${lib_other.lib_ignore} + ${lib_SPI.lib_ignore} + + + + +; ****************************** +; *** Library groups setup *** +; ****************************** [lib_EP8266_default] lib_ignore = @@ -28,35 +171,42 @@ lib_ignore = [lib_all_EP8266] lib_ignore = ${lib_EP8266.lib_ignore} - ${lib_Tasmota.lib_ignore} + ${lib_knx.lib_ignore} + ${lib_custom.lib_ignore} ${lib_SSL.lib_ignore} - ${lib_display.lib_ignore} + ${lib_ESP_display.lib_ignore} ${lib_i2c_sensor.lib_ignore} ${lib_sensor.lib_ignore} ${lib_rf.lib_ignore} - ${lib_ir.lib_ignore} + ${lib_ESP_ir.lib_ignore} ${lib_light.lib_ignore} ${lib_audio.lib_ignore} ${lib_serial.lib_ignore} ${lib_other.lib_ignore} ${lib_SPI.lib_ignore} -[lib_Tasmota] +[lib_custom] lib_ignore = NTP Library base64 Unishox Compressor Decompressor highly customized and optimized for ESP8266 and Tasmota - ;ESP KNX IP Library UdpListener + C2Programmer + TasmotaSerial + TasmotaModbus + +[lib_ESP_knx] +lib_ignore = + ;ESP KNX IP Library [lib_SSL] lib_ignore = BearSSL -[lib_display] +[lib_ESP_display] lib_ignore = LinkedList - Adafruit BusIO + ;Adafruit BusIO Adafruit GFX Library Arduino ST7789 Library Adafruit ILI9341 @@ -68,7 +218,7 @@ lib_ignore = Adafruit SH1106-gemu-1.0 Adafruit SSD1306 SSD3115 - I2Cdevlib-Core + ;I2Cdevlib-Core [lib_i2c_sensor] lib_ignore = @@ -105,10 +255,9 @@ lib_ignore = lib_ignore = rc-switch RF24 - C2Programmer KeeloqLib -[lib_ir] +[lib_ESP_ir] lib_ignore = IRremoteESP8266 @@ -124,8 +273,6 @@ lib_ignore = [lib_serial] lib_ignore = LibTeleinfo - TasmotaSerial - TasmotaModbus [lib_other] lib_ignore = @@ -136,4 +283,4 @@ lib_ignore = [lib_SPI] lib_ignore = cc1101 - EEPROM 24C128 \ No newline at end of file + EEPROM 24C128 diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index e3ead2b55..8ef08ef57 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -18,97 +18,128 @@ lib_extra_dirs = ${common.shared_libdeps_dir} lib_ignore = ${common.lib_ignore} [env:tasmota] +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-minimal] build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -lib_ignore = ${lib_all_EP8266.lib_ignore} +lib_ignore = ${lib_minimal.lib_ignore} [env:tasmota-lite] build_flags = ${common.build_flags} -DFIRMWARE_LITE +lib_ignore = ${lib_lite.lib_ignore} [env:tasmota-knx] build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION +lib_ignore = ${lib_knx.lib_ignore} [env:tasmota-sensors] build_flags = ${common.build_flags} -DFIRMWARE_SENSORS +lib_ignore = ${lib_sensors.lib_ignore} [env:tasmota-display] build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS +lib_ignore = ${lib_display.lib_ignore} [env:tasmota-ir] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR +lib_ignore = ${lib_ir.lib_ignore} [env:tasmota-ircustom] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE +lib_ignore = ${lib_zbbridge.lib_ignore} [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-BR] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_BR +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-CN] build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_CN +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-CZ] build_flags = ${common.build_flags} -DMY_LANGUAGE=cs_CZ +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-DE] build_flags = ${common.build_flags} -DMY_LANGUAGE=de_DE +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-ES] build_flags = ${common.build_flags} -DMY_LANGUAGE=es_ES +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-FR] build_flags = ${common.build_flags} -DMY_LANGUAGE=fr_FR +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-GR] build_flags = ${common.build_flags} -DMY_LANGUAGE=el_GR +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-HE] build_flags = ${common.build_flags} -DMY_LANGUAGE=he_HE +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-HU] build_flags = ${common.build_flags} -DMY_LANGUAGE=hu_HU +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-IT] build_flags = ${common.build_flags} -DMY_LANGUAGE=it_IT +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-KO] build_flags = ${common.build_flags} -DMY_LANGUAGE=ko_KO +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-NL] build_flags = ${common.build_flags} -DMY_LANGUAGE=nl_NL +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-PL] build_flags = ${common.build_flags} -DMY_LANGUAGE=pl_PL +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-PT] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_PT +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-RO] build_flags = ${common.build_flags} -DMY_LANGUAGE=ro_RO +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-RU] build_flags = ${common.build_flags} -DMY_LANGUAGE=ru_RU +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-SE] build_flags = ${common.build_flags} -DMY_LANGUAGE=sv_SE +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-SK] build_flags = ${common.build_flags} -DMY_LANGUAGE=sk_SK +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-TR] build_flags = ${common.build_flags} -DMY_LANGUAGE=tr_TR +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-TW] build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_TW +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-UK] build_flags = ${common.build_flags} -DMY_LANGUAGE=uk_UA +lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-VN] build_flags = ${common.build_flags} -DMY_LANGUAGE=vi_VN +lib_ignore = ${lib_Tasmota.lib_ignore} From 65a921fa4b943896da0afb909fd5573510e313bb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 18:14:35 +0200 Subject: [PATCH 03/38] small changes for libignorre --- platformio.ini | 2 -- platformio_lib.ini | 2 -- platformio_tasmota32.ini | 1 + platformio_tasmota_env.ini | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index c9c78c297..4d33b9a7f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -83,7 +83,6 @@ upload_resetmethod = nodemcu upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} shared_libdeps_dir = lib -lib_ignore = ${esp82xx_defaults.lib_ignore} [scripts_defaults] extra_scripts = pio/strip-floats.py @@ -124,7 +123,6 @@ build_flags = ${esp_defaults.build_flags} -DPSTR_ALIGN=1 ; restrict to minimal mime-types -DMIMETYPE_MINIMAL -lib_ignore = ${lib_EP8266_default.lib_ignore} [irremoteesp_full] build_flags = -DUSE_IR_REMOTE_FULL diff --git a/platformio_lib.ini b/platformio_lib.ini index 6284d52c4..7c4ed544b 100644 --- a/platformio_lib.ini +++ b/platformio_lib.ini @@ -206,7 +206,6 @@ lib_ignore = [lib_ESP_display] lib_ignore = LinkedList - ;Adafruit BusIO Adafruit GFX Library Arduino ST7789 Library Adafruit ILI9341 @@ -218,7 +217,6 @@ lib_ignore = Adafruit SH1106-gemu-1.0 Adafruit SSD1306 SSD3115 - ;I2Cdevlib-Core [lib_i2c_sensor] lib_ignore = diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 2eb453954..35768c686 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -43,6 +43,7 @@ default_envs = ${build_envs.default_envs} [core32] platform = espressif32@2.0.0 platform_packages = tool-esptoolpy@1.20800.0 + platformio/framework-arduinoespressif32 @ 3.10004.201016 [common32] platform = ${core32.platform} diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 8ef08ef57..06c36cc7c 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -15,7 +15,6 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} lib_extra_dirs = ${common.shared_libdeps_dir} -lib_ignore = ${common.lib_ignore} [env:tasmota] lib_ignore = ${lib_Tasmota.lib_ignore} From ac1e6c0efb91721be754814ae1a443e2e07b6980 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 22:29:25 +0200 Subject: [PATCH 04/38] Esp32 lib ignore --- platformio_tasmota32.ini | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 35768c686..33a08ce48 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -81,3 +81,14 @@ lib_extra_dirs = lib_ignore = cc1101 + ESP32 Azure IoT Arduino + ESP32 Async UDP + ESP32 BLE Arduino + SimpleBLE + WiFiClientSecure + NetBIOS + ESP32 + DNSServer + Preferences + BluetoothSerial + From 89f79bb62500711d181bd5b4c747d047f9629a8e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 22:34:36 +0200 Subject: [PATCH 05/38] Update platformio_tasmota32.ini --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 33a08ce48..4d6a31937 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -85,7 +85,7 @@ lib_ignore = ESP32 Async UDP ESP32 BLE Arduino SimpleBLE - WiFiClientSecure + ;WiFiClientSecure NetBIOS ESP32 DNSServer From 7cb86770bbc6f4de8322a59e615c4718b5bab4fc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 22:40:06 +0200 Subject: [PATCH 06/38] Update platformio_tasmota32.ini --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 4d6a31937..3f5b6eb0d 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -88,7 +88,7 @@ lib_ignore = ;WiFiClientSecure NetBIOS ESP32 - DNSServer + ;DNSServer Preferences BluetoothSerial From 5b9e2d25eaec2f4c9a17959053ed2b74d4a340e6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Oct 2020 22:50:06 +0200 Subject: [PATCH 07/38] Resolve warning for esptool --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 4d33b9a7f..6aab83df8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -134,5 +134,6 @@ build_flags = -DUSE_IR_REMOTE_FULL ; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4 platform = espressif8266@2.6.2 platform_packages = framework-arduinoespressif8266@https://github.com/tasmota/Arduino/releases/download/2.7.4.5/esp8266-2.7.4.5.zip + platformio/tool-esptool @ 1.413.0 build_unflags = ${esp_defaults.build_unflags} build_flags = ${esp82xx_defaults.build_flags} From 0ae067444ac0127e313c40d81e18a4d08e899c9e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 13:59:04 +0100 Subject: [PATCH 08/38] split lib --- lib/FT5206_Library/.gitignore | 2 - lib/FT5206_Library/README.md | 2 - .../.github/workflows/pr-or-master-push.yml | 0 {lib => lib_audio}/ESP8266Audio/LICENSE | 0 {lib => lib_audio}/ESP8266Audio/README.md | 0 .../examples/MixerSample/MixerSample.ino | 0 .../ESP8266Audio/examples/MixerSample/viola.h | 0 .../PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino | 0 .../examples/PlayAACFromPROGMEM/homer.aac | Bin .../examples/PlayAACFromPROGMEM/sampleaac.h | 0 .../PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino | 0 .../PlayFLACFromPROGMEMToDAC.ino | 0 .../PlayFLACFromPROGMEMToDAC/sample.h | 0 .../PlayMIDIFromLittleFS.ino | 0 .../PlayMIDIFromLittleFS/data/1mgm.sf2 | Bin .../PlayMIDIFromLittleFS/data/furelise.mid | Bin .../PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino | 0 .../examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 | Bin .../PlayMIDIFromSPIFFS/data/furelise.mid | Bin .../PlayMODFromPROGMEMToDAC.ino | 0 .../examples/PlayMODFromPROGMEMToDAC/enigma.h | 0 .../PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino | 0 .../PlayMP3FromSPIFFS/data/pno-cs.mp3 | Bin .../PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino | 0 .../PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino | 0 .../data/gs-16b-2c-44100hz.opus | Bin .../PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino | 0 .../PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino | 0 .../examples/PlayWAVFromPROGMEM/viola.h | 0 .../StreamMP3FromHTTP/StreamMP3FromHTTP.ino | 0 .../Schema_Spiram.png | Bin .../StreamMP3FromHTTP_SPIRAM.ino | 0 .../TalkingClockI2S/TalkingClockI2S.ino | 0 .../examples/WebRadio/WebRadio.ino | 0 .../ESP8266Audio/examples/WebRadio/web.cpp | 0 .../ESP8266Audio/examples/WebRadio/web.h | 0 {lib => lib_audio}/ESP8266Audio/keywords.txt | 0 {lib => lib_audio}/ESP8266Audio/library.json | 0 .../ESP8266Audio/library.properties | 0 .../ESP8266Audio/src/AudioFileSource.h | 0 .../src/AudioFileSourceBuffer.cpp | 0 .../ESP8266Audio/src/AudioFileSourceBuffer.h | 0 .../ESP8266Audio/src/AudioFileSourceFATFS.h | 0 .../ESP8266Audio/src/AudioFileSourceFS.cpp | 0 .../ESP8266Audio/src/AudioFileSourceFS.h | 0 .../src/AudioFileSourceHTTPStream.cpp | 0 .../src/AudioFileSourceHTTPStream.h | 0 .../src/AudioFileSourceICYStream.cpp | 0 .../src/AudioFileSourceICYStream.h | 0 .../ESP8266Audio/src/AudioFileSourceID3.cpp | 0 .../ESP8266Audio/src/AudioFileSourceID3.h | 0 .../src/AudioFileSourceLittleFS.h | 0 .../src/AudioFileSourcePROGMEM.cpp | 0 .../ESP8266Audio/src/AudioFileSourcePROGMEM.h | 0 .../ESP8266Audio/src/AudioFileSourceSD.cpp | 0 .../ESP8266Audio/src/AudioFileSourceSD.h | 0 .../ESP8266Audio/src/AudioFileSourceSPIFFS.h | 0 .../src/AudioFileSourceSPIRAMBuffer.cpp | 0 .../src/AudioFileSourceSPIRAMBuffer.h | 0 .../ESP8266Audio/src/AudioFileSourceSTDIO.cpp | 0 .../ESP8266Audio/src/AudioFileSourceSTDIO.h | 0 .../ESP8266Audio/src/AudioFileStream.cpp | 0 .../ESP8266Audio/src/AudioFileStream.h | 0 .../ESP8266Audio/src/AudioGenerator.h | 0 .../ESP8266Audio/src/AudioGeneratorAAC.cpp | 0 .../ESP8266Audio/src/AudioGeneratorAAC.h | 0 .../ESP8266Audio/src/AudioGeneratorFLAC.cpp | 0 .../ESP8266Audio/src/AudioGeneratorFLAC.h | 0 .../ESP8266Audio/src/AudioGeneratorMIDI.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMIDI.h | 0 .../ESP8266Audio/src/AudioGeneratorMOD.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMOD.h | 0 .../ESP8266Audio/src/AudioGeneratorMP3.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMP3.h | 0 .../ESP8266Audio/src/AudioGeneratorMP3a.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMP3a.h | 0 .../ESP8266Audio/src/AudioGeneratorOpus.cpp | 0 .../ESP8266Audio/src/AudioGeneratorOpus.h | 0 .../ESP8266Audio/src/AudioGeneratorRTTTL.cpp | 0 .../ESP8266Audio/src/AudioGeneratorRTTTL.h | 0 .../ESP8266Audio/src/AudioGeneratorTalkie.cpp | 0 .../ESP8266Audio/src/AudioGeneratorTalkie.h | 0 .../ESP8266Audio/src/AudioGeneratorWAV.cpp | 0 .../ESP8266Audio/src/AudioGeneratorWAV.h | 0 .../ESP8266Audio/src/AudioLogger.cpp | 0 .../ESP8266Audio/src/AudioLogger.h | 0 .../ESP8266Audio/src/AudioOutput.h | 0 .../ESP8266Audio/src/AudioOutputBuffer.cpp | 0 .../ESP8266Audio/src/AudioOutputBuffer.h | 0 .../src/AudioOutputFilterDecimate.cpp | 0 .../src/AudioOutputFilterDecimate.h | 0 .../ESP8266Audio/src/AudioOutputI2S.cpp | 0 .../ESP8266Audio/src/AudioOutputI2S.h | 0 .../ESP8266Audio/src/AudioOutputI2SNoDAC.cpp | 0 .../ESP8266Audio/src/AudioOutputI2SNoDAC.h | 0 .../ESP8266Audio/src/AudioOutputMixer.cpp | 0 .../ESP8266Audio/src/AudioOutputMixer.h | 0 .../ESP8266Audio/src/AudioOutputNull.h | 0 .../ESP8266Audio/src/AudioOutputSPDIF.cpp | 0 .../ESP8266Audio/src/AudioOutputSPDIF.h | 0 .../ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp | 0 .../ESP8266Audio/src/AudioOutputSPIFFSWAV.h | 0 .../ESP8266Audio/src/AudioOutputSTDIO.cpp | 0 .../ESP8266Audio/src/AudioOutputSTDIO.h | 0 .../ESP8266Audio/src/AudioOutputSerialWAV.cpp | 0 .../ESP8266Audio/src/AudioOutputSerialWAV.h | 0 .../ESP8266Audio/src/AudioStatus.h | 0 .../src/driver/SinglePinI2SDriver.cpp | 0 .../src/driver/SinglePinI2SDriver.h | 0 .../ESP8266Audio/src/libflac/AUTHORS | 0 .../ESP8266Audio/src/libflac/COPYING.FDL | 0 .../ESP8266Audio/src/libflac/COPYING.GPL | 0 .../ESP8266Audio/src/libflac/COPYING.LGPL | 0 .../ESP8266Audio/src/libflac/COPYING.Xiph | 0 .../ESP8266Audio/src/libflac/FLAC/assert.h | 0 .../ESP8266Audio/src/libflac/FLAC/callback.h | 0 .../ESP8266Audio/src/libflac/FLAC/export.h | 0 .../ESP8266Audio/src/libflac/FLAC/format.h | 0 .../ESP8266Audio/src/libflac/FLAC/metadata.h | 0 .../ESP8266Audio/src/libflac/FLAC/ordinals.h | 0 .../src/libflac/FLAC/stream_decoder.h | 0 .../ESP8266Audio/src/libflac/README | 0 .../ESP8266Audio/src/libflac/README.ESP8266 | 0 .../ESP8266Audio/src/libflac/bitmath.c | 0 .../ESP8266Audio/src/libflac/bitreader.c | 0 .../ESP8266Audio/src/libflac/config.h | 0 .../ESP8266Audio/src/libflac/cpu.c | 0 .../ESP8266Audio/src/libflac/crc.c | 0 .../ESP8266Audio/src/libflac/fixed.c | 0 .../ESP8266Audio/src/libflac/float.c | 0 .../ESP8266Audio/src/libflac/format.c | 0 .../ESP8266Audio/src/libflac/lpc.c | 0 .../ESP8266Audio/src/libflac/md5.c | 0 .../ESP8266Audio/src/libflac/memory.c | 0 .../src/libflac/private/bitmath.h | 0 .../src/libflac/private/bitreader.h | 0 .../ESP8266Audio/src/libflac/private/cpu.h | 0 .../ESP8266Audio/src/libflac/private/crc.h | 0 .../ESP8266Audio/src/libflac/private/fixed.h | 0 .../ESP8266Audio/src/libflac/private/float.h | 0 .../ESP8266Audio/src/libflac/private/format.h | 0 .../ESP8266Audio/src/libflac/private/lpc.h | 0 .../ESP8266Audio/src/libflac/private/macros.h | 0 .../ESP8266Audio/src/libflac/private/md5.h | 0 .../ESP8266Audio/src/libflac/private/memory.h | 0 .../src/libflac/private/metadata.h | 0 .../ESP8266Audio/src/libflac/private/window.h | 0 .../ESP8266Audio/src/libflac/protected/all.h | 0 .../src/libflac/protected/stream_decoder.h | 0 .../src/libflac/protected/stream_encoder.h | 0 .../ESP8266Audio/src/libflac/share/alloc.h | 0 .../ESP8266Audio/src/libflac/share/compat.h | 0 .../ESP8266Audio/src/libflac/share/endswap.h | 0 .../ESP8266Audio/src/libflac/share/getopt.h | 0 .../ESP8266Audio/src/libflac/share/macros.h | 0 .../ESP8266Audio/src/libflac/share/private.h | 0 .../ESP8266Audio/src/libflac/share/safe_str.h | 0 .../ESP8266Audio/src/libflac/share/utf8.h | 0 .../ESP8266Audio/src/libflac/stream_decoder.c | 0 .../ESP8266Audio/src/libflac/window.c | 0 .../ESP8266Audio/src/libhelix-aac/aaccommon.h | 0 .../ESP8266Audio/src/libhelix-aac/aacdec.c | 0 .../ESP8266Audio/src/libhelix-aac/aacdec.h | 0 .../ESP8266Audio/src/libhelix-aac/aactabs.c | 0 .../ESP8266Audio/src/libhelix-aac/assembly.h | 0 .../ESP8266Audio/src/libhelix-aac/bitstream.c | 0 .../ESP8266Audio/src/libhelix-aac/bitstream.h | 0 .../ESP8266Audio/src/libhelix-aac/buffers.c | 0 .../ESP8266Audio/src/libhelix-aac/coder.h | 0 .../ESP8266Audio/src/libhelix-aac/dct4.c | 0 .../ESP8266Audio/src/libhelix-aac/decelmnt.c | 0 .../ESP8266Audio/src/libhelix-aac/dequant.c | 0 .../ESP8266Audio/src/libhelix-aac/fft.c | 0 .../ESP8266Audio/src/libhelix-aac/filefmt.c | 0 .../ESP8266Audio/src/libhelix-aac/huffman.c | 0 .../ESP8266Audio/src/libhelix-aac/hufftabs.c | 0 .../ESP8266Audio/src/libhelix-aac/imdct.c | 0 .../ESP8266Audio/src/libhelix-aac/noiseless.c | 0 .../ESP8266Audio/src/libhelix-aac/pns.c | 0 .../ESP8266Audio/src/libhelix-aac/readme.txt | 0 .../ESP8266Audio/src/libhelix-aac/sbr.c | 0 .../ESP8266Audio/src/libhelix-aac/sbr.h | 0 .../ESP8266Audio/src/libhelix-aac/sbrfft.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrfreq.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhfadj.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhfgen.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhuff.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrimdct.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrmath.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrqmf.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrside.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrtabs.c | 0 .../ESP8266Audio/src/libhelix-aac/statname.h | 0 .../ESP8266Audio/src/libhelix-aac/stproc.c | 0 .../ESP8266Audio/src/libhelix-aac/tns.c | 0 .../ESP8266Audio/src/libhelix-aac/trigtabs.c | 0 .../ESP8266Audio/src/libhelix-mp3/LICENSE.txt | 0 .../ESP8266Audio/src/libhelix-mp3/RCSL.txt | 0 .../ESP8266Audio/src/libhelix-mp3/RPSL.txt | 0 .../ESP8266Audio/src/libhelix-mp3/assembly.h | 0 .../ESP8266Audio/src/libhelix-mp3/bitstream.c | 0 .../ESP8266Audio/src/libhelix-mp3/buffers.c | 0 .../ESP8266Audio/src/libhelix-mp3/coder.h | 0 .../ESP8266Audio/src/libhelix-mp3/dct32.c | 0 .../ESP8266Audio/src/libhelix-mp3/dequant.c | 0 .../ESP8266Audio/src/libhelix-mp3/dqchan.c | 0 .../ESP8266Audio/src/libhelix-mp3/huffman.c | 0 .../ESP8266Audio/src/libhelix-mp3/hufftabs.c | 0 .../ESP8266Audio/src/libhelix-mp3/imdct.c | 0 .../ESP8266Audio/src/libhelix-mp3/mp3common.h | 0 .../ESP8266Audio/src/libhelix-mp3/mp3dec.c | 0 .../ESP8266Audio/src/libhelix-mp3/mp3dec.h | 0 .../ESP8266Audio/src/libhelix-mp3/mp3tabs.c | 0 .../src/libhelix-mp3/mpadecobjfixpt.h | 0 .../ESP8266Audio/src/libhelix-mp3/player.h | 0 .../ESP8266Audio/src/libhelix-mp3/polyphase.c | 0 .../ESP8266Audio/src/libhelix-mp3/scalfact.c | 0 .../ESP8266Audio/src/libhelix-mp3/statname.h | 0 .../ESP8266Audio/src/libhelix-mp3/stproc.c | 0 .../ESP8266Audio/src/libhelix-mp3/subband.c | 0 .../ESP8266Audio/src/libhelix-mp3/trigtabs.c | 0 .../ESP8266Audio/src/libmad/CHANGES | 0 .../ESP8266Audio/src/libmad/COPYING | 0 .../ESP8266Audio/src/libmad/COPYRIGHT | 0 .../ESP8266Audio/src/libmad/CREDITS | 0 .../ESP8266Audio/src/libmad/D.dat.h | 0 .../ESP8266Audio/src/libmad/LICENSE | 0 .../ESP8266Audio/src/libmad/README | 0 .../ESP8266Audio/src/libmad/README.ESP8266 | 0 .../ESP8266Audio/src/libmad/TODO | 0 .../ESP8266Audio/src/libmad/VERSION | 0 .../ESP8266Audio/src/libmad/bit.c | 0 .../ESP8266Audio/src/libmad/bit.h | 0 .../ESP8266Audio/src/libmad/config.h | 0 .../ESP8266Audio/src/libmad/decoder.c | 0 .../ESP8266Audio/src/libmad/decoder.h | 0 .../ESP8266Audio/src/libmad/fixed.c | 0 .../ESP8266Audio/src/libmad/fixed.h | 0 .../ESP8266Audio/src/libmad/frame.c | 0 .../ESP8266Audio/src/libmad/frame.h | 0 .../ESP8266Audio/src/libmad/global.h | 0 .../ESP8266Audio/src/libmad/huffman.c | 0 .../ESP8266Audio/src/libmad/huffman.h | 0 .../ESP8266Audio/src/libmad/imdct_s.dat.h | 0 .../ESP8266Audio/src/libmad/layer3.c | 0 .../ESP8266Audio/src/libmad/layer3.h | 0 .../ESP8266Audio/src/libmad/mad.h | 0 .../ESP8266Audio/src/libmad/mad.h.sed | 0 .../ESP8266Audio/src/libmad/qc_table.dat.h | 0 .../ESP8266Audio/src/libmad/rq_table.dat.h | 0 .../ESP8266Audio/src/libmad/sf_table.dat.h | 0 .../ESP8266Audio/src/libmad/stream.c | 0 .../ESP8266Audio/src/libmad/stream.h | 0 .../ESP8266Audio/src/libmad/synth.c | 0 .../ESP8266Audio/src/libmad/synth.h | 0 .../ESP8266Audio/src/libmad/timer.c | 0 .../ESP8266Audio/src/libmad/timer.h | 0 .../ESP8266Audio/src/libmad/version.c | 0 .../ESP8266Audio/src/libmad/version.h | 0 .../ESP8266Audio/src/libogg/AUTHORS | 0 .../ESP8266Audio/src/libogg/CHANGES | 0 .../ESP8266Audio/src/libogg/COPYING | 0 .../ESP8266Audio/src/libogg/README.esp8266.md | 0 .../ESP8266Audio/src/libogg/README.md | 0 .../ESP8266Audio/src/libogg/bitwise.c | 0 .../ESP8266Audio/src/libogg/config.h | 0 .../ESP8266Audio/src/libogg/crctable.h | 0 .../ESP8266Audio/src/libogg/framing.c | 0 .../ESP8266Audio/src/libogg/ogg.pc | 0 .../src/libogg/ogg/config_types.h | 0 .../ESP8266Audio/src/libogg/ogg/ogg.h | 0 .../ESP8266Audio/src/libogg/ogg/os_types.h | 0 .../ESP8266Audio/src/libopus/AUTHORS | 0 .../ESP8266Audio/src/libopus/COPYING | 0 .../ESP8266Audio/src/libopus/ChangeLog | 0 .../ESP8266Audio/src/libopus/INSTALL | 0 .../ESP8266Audio/src/libopus/NEWS | 0 .../ESP8266Audio/src/libopus/README | 0 .../ESP8266Audio/src/libopus/analysis.h | 0 .../src/libopus/celt/_kiss_fft_guts.h | 0 .../ESP8266Audio/src/libopus/celt/arch.h | 0 .../ESP8266Audio/src/libopus/celt/bands.c | 0 .../ESP8266Audio/src/libopus/celt/bands.h | 0 .../ESP8266Audio/src/libopus/celt/celt.c | 0 .../ESP8266Audio/src/libopus/celt/celt.h | 0 .../src/libopus/celt/celt_decoder.c | 0 .../src/libopus/celt/celt_encoder.c | 0 .../ESP8266Audio/src/libopus/celt/celt_lpc.c | 0 .../ESP8266Audio/src/libopus/celt/celt_lpc.h | 0 .../src/libopus/celt/cpu_support.h | 0 .../ESP8266Audio/src/libopus/celt/cwrs.c | 0 .../ESP8266Audio/src/libopus/celt/cwrs.h | 0 .../ESP8266Audio/src/libopus/celt/ecintrin.h | 0 .../ESP8266Audio/src/libopus/celt/entcode.c | 0 .../ESP8266Audio/src/libopus/celt/entcode.h | 0 .../ESP8266Audio/src/libopus/celt/entdec.c | 0 .../ESP8266Audio/src/libopus/celt/entdec.h | 0 .../ESP8266Audio/src/libopus/celt/entenc.c | 0 .../ESP8266Audio/src/libopus/celt/entenc.h | 0 .../src/libopus/celt/fixed_debug.h | 0 .../src/libopus/celt/fixed_generic.h | 0 .../src/libopus/celt/float_cast.h | 0 .../ESP8266Audio/src/libopus/celt/kiss_fft.c | 0 .../ESP8266Audio/src/libopus/celt/kiss_fft.h | 0 .../ESP8266Audio/src/libopus/celt/laplace.c | 0 .../ESP8266Audio/src/libopus/celt/laplace.h | 0 .../ESP8266Audio/src/libopus/celt/mathops.c | 0 .../ESP8266Audio/src/libopus/celt/mathops.h | 0 .../ESP8266Audio/src/libopus/celt/mdct.c | 0 .../ESP8266Audio/src/libopus/celt/mdct.h | 0 .../ESP8266Audio/src/libopus/celt/mfrngcod.h | 0 .../ESP8266Audio/src/libopus/celt/modes.c | 0 .../ESP8266Audio/src/libopus/celt/modes.h | 0 .../src/libopus/celt/os_support.h | 0 .../ESP8266Audio/src/libopus/celt/pitch.c | 0 .../ESP8266Audio/src/libopus/celt/pitch.h | 0 .../src/libopus/celt/quant_bands.c | 0 .../src/libopus/celt/quant_bands.h | 0 .../ESP8266Audio/src/libopus/celt/rate.c | 0 .../ESP8266Audio/src/libopus/celt/rate.h | 0 .../src/libopus/celt/stack_alloc.h | 0 .../src/libopus/celt/static_modes_fixed.h | 0 .../src/libopus/celt/static_modes_float.h | 0 .../ESP8266Audio/src/libopus/celt/vq.c | 0 .../ESP8266Audio/src/libopus/celt/vq.h | 0 .../ESP8266Audio/src/libopus/config.h | 0 .../ESP8266Audio/src/libopus/mapping_matrix.c | 0 .../ESP8266Audio/src/libopus/mapping_matrix.h | 0 .../ESP8266Audio/src/libopus/mlp.h | 0 .../ESP8266Audio/src/libopus/opus.c | 0 .../ESP8266Audio/src/libopus/opus.h | 0 .../ESP8266Audio/src/libopus/opus.pc | 0 .../ESP8266Audio/src/libopus/opus_custom.h | 0 .../ESP8266Audio/src/libopus/opus_decoder.c | 0 .../ESP8266Audio/src/libopus/opus_defines.h | 0 .../ESP8266Audio/src/libopus/opus_encoder.c | 0 .../src/libopus/opus_multistream.c | 0 .../src/libopus/opus_multistream.h | 0 .../src/libopus/opus_multistream_decoder.c | 0 .../src/libopus/opus_multistream_encoder.c | 0 .../ESP8266Audio/src/libopus/opus_private.h | 0 .../src/libopus/opus_projection.h | 0 .../src/libopus/opus_projection_decoder.c | 0 .../src/libopus/opus_projection_encoder.c | 0 .../ESP8266Audio/src/libopus/opus_types.h | 0 .../ESP8266Audio/src/libopus/repacketizer.c | 0 .../ESP8266Audio/src/libopus/silk/A2NLSF.c | 0 .../ESP8266Audio/src/libopus/silk/API.h | 0 .../ESP8266Audio/src/libopus/silk/CNG.c | 0 .../src/libopus/silk/HP_variable_cutoff.c | 0 .../ESP8266Audio/src/libopus/silk/Inlines.h | 0 .../src/libopus/silk/LPC_analysis_filter.c | 0 .../ESP8266Audio/src/libopus/silk/LPC_fit.c | 0 .../src/libopus/silk/LPC_inv_pred_gain.c | 0 .../src/libopus/silk/LP_variable_cutoff.c | 0 .../src/libopus/silk/MacroCount.h | 0 .../src/libopus/silk/MacroDebug.h | 0 .../ESP8266Audio/src/libopus/silk/NLSF2A.c | 0 .../ESP8266Audio/src/libopus/silk/NLSF_VQ.c | 0 .../src/libopus/silk/NLSF_VQ_weights_laroia.c | 0 .../src/libopus/silk/NLSF_decode.c | 0 .../src/libopus/silk/NLSF_del_dec_quant.c | 0 .../src/libopus/silk/NLSF_encode.c | 0 .../src/libopus/silk/NLSF_stabilize.c | 0 .../src/libopus/silk/NLSF_unpack.c | 0 .../ESP8266Audio/src/libopus/silk/NSQ.c | 0 .../ESP8266Audio/src/libopus/silk/NSQ.h | 0 .../src/libopus/silk/NSQ_del_dec.c | 0 .../ESP8266Audio/src/libopus/silk/PLC.c | 0 .../ESP8266Audio/src/libopus/silk/PLC.h | 0 .../src/libopus/silk/SigProc_FIX.h | 0 .../ESP8266Audio/src/libopus/silk/VAD.c | 0 .../src/libopus/silk/VQ_WMat_EC.c | 0 .../src/libopus/silk/ana_filt_bank_1.c | 0 .../src/libopus/silk/biquad_alt.c | 0 .../src/libopus/silk/bwexpander.c | 0 .../src/libopus/silk/bwexpander_32.c | 0 .../src/libopus/silk/check_control_input.c | 0 .../src/libopus/silk/code_signs.c | 0 .../ESP8266Audio/src/libopus/silk/control.h | 0 .../src/libopus/silk/control_SNR.c | 0 .../libopus/silk/control_audio_bandwidth.c | 0 .../src/libopus/silk/control_codec.c | 0 .../ESP8266Audio/src/libopus/silk/debug.c | 0 .../ESP8266Audio/src/libopus/silk/debug.h | 0 .../ESP8266Audio/src/libopus/silk/dec_API.c | 0 .../src/libopus/silk/decode_core.c | 0 .../src/libopus/silk/decode_frame.c | 0 .../src/libopus/silk/decode_indices.c | 0 .../src/libopus/silk/decode_parameters.c | 0 .../src/libopus/silk/decode_pitch.c | 0 .../src/libopus/silk/decode_pulses.c | 0 .../src/libopus/silk/decoder_set_fs.c | 0 .../ESP8266Audio/src/libopus/silk/define.h | 0 .../ESP8266Audio/src/libopus/silk/enc_API.c | 0 .../src/libopus/silk/encode_indices.c | 0 .../src/libopus/silk/encode_pulses.c | 0 .../ESP8266Audio/src/libopus/silk/errors.h | 0 .../silk/fixed/LTP_analysis_filter_FIX.c | 0 .../silk/fixed/LTP_analysis_filter_FIX.lo | 0 .../silk/fixed/LTP_analysis_filter_FIX.o | Bin .../libopus/silk/fixed/LTP_scale_ctrl_FIX.c | 0 .../libopus/silk/fixed/LTP_scale_ctrl_FIX.lo | 0 .../libopus/silk/fixed/LTP_scale_ctrl_FIX.o | Bin .../silk/fixed/apply_sine_window_FIX.c | 0 .../silk/fixed/apply_sine_window_FIX.lo | 0 .../silk/fixed/apply_sine_window_FIX.o | Bin .../src/libopus/silk/fixed/autocorr_FIX.c | 0 .../src/libopus/silk/fixed/autocorr_FIX.lo | 0 .../src/libopus/silk/fixed/autocorr_FIX.o | Bin .../libopus/silk/fixed/burg_modified_FIX.c | 0 .../libopus/silk/fixed/burg_modified_FIX.lo | 0 .../libopus/silk/fixed/burg_modified_FIX.o | Bin .../src/libopus/silk/fixed/corrMatrix_FIX.c | 0 .../src/libopus/silk/fixed/corrMatrix_FIX.lo | 0 .../src/libopus/silk/fixed/corrMatrix_FIX.o | Bin .../src/libopus/silk/fixed/encode_frame_FIX.c | 0 .../libopus/silk/fixed/encode_frame_FIX.lo | 0 .../src/libopus/silk/fixed/encode_frame_FIX.o | Bin .../src/libopus/silk/fixed/find_LPC_FIX.c | 0 .../src/libopus/silk/fixed/find_LPC_FIX.lo | 0 .../src/libopus/silk/fixed/find_LPC_FIX.o | Bin .../src/libopus/silk/fixed/find_LTP_FIX.c | 0 .../src/libopus/silk/fixed/find_LTP_FIX.lo | 0 .../src/libopus/silk/fixed/find_LTP_FIX.o | Bin .../libopus/silk/fixed/find_pitch_lags_FIX.c | 0 .../libopus/silk/fixed/find_pitch_lags_FIX.lo | 0 .../libopus/silk/fixed/find_pitch_lags_FIX.o | Bin .../libopus/silk/fixed/find_pred_coefs_FIX.c | 0 .../libopus/silk/fixed/find_pred_coefs_FIX.lo | 0 .../libopus/silk/fixed/find_pred_coefs_FIX.o | Bin .../src/libopus/silk/fixed/k2a_FIX.c | 0 .../src/libopus/silk/fixed/k2a_FIX.lo | 0 .../src/libopus/silk/fixed/k2a_FIX.o | Bin .../src/libopus/silk/fixed/k2a_Q16_FIX.c | 0 .../src/libopus/silk/fixed/k2a_Q16_FIX.lo | 0 .../src/libopus/silk/fixed/k2a_Q16_FIX.o | Bin .../src/libopus/silk/fixed/main_FIX.h | 0 .../silk/fixed/noise_shape_analysis_FIX.c | 0 .../silk/fixed/noise_shape_analysis_FIX.lo | 0 .../silk/fixed/noise_shape_analysis_FIX.o | Bin .../silk/fixed/pitch_analysis_core_FIX.c | 0 .../silk/fixed/pitch_analysis_core_FIX.lo | 0 .../silk/fixed/pitch_analysis_core_FIX.o | Bin .../libopus/silk/fixed/process_gains_FIX.c | 0 .../libopus/silk/fixed/process_gains_FIX.lo | 0 .../libopus/silk/fixed/process_gains_FIX.o | Bin .../silk/fixed/regularize_correlations_FIX.c | 0 .../silk/fixed/regularize_correlations_FIX.lo | 0 .../silk/fixed/regularize_correlations_FIX.o | Bin .../silk/fixed/residual_energy16_FIX.c | 0 .../silk/fixed/residual_energy16_FIX.lo | 0 .../silk/fixed/residual_energy16_FIX.o | Bin .../libopus/silk/fixed/residual_energy_FIX.c | 0 .../libopus/silk/fixed/residual_energy_FIX.lo | 0 .../libopus/silk/fixed/residual_energy_FIX.o | Bin .../src/libopus/silk/fixed/schur64_FIX.c | 0 .../src/libopus/silk/fixed/schur64_FIX.lo | 0 .../src/libopus/silk/fixed/schur64_FIX.o | Bin .../src/libopus/silk/fixed/schur_FIX.c | 0 .../src/libopus/silk/fixed/schur_FIX.lo | 0 .../src/libopus/silk/fixed/schur_FIX.o | Bin .../src/libopus/silk/fixed/structs_FIX.h | 0 .../src/libopus/silk/fixed/vector_ops_FIX.c | 0 .../src/libopus/silk/fixed/vector_ops_FIX.lo | 0 .../src/libopus/silk/fixed/vector_ops_FIX.o | Bin .../silk/fixed/warped_autocorrelation_FIX.c | 0 .../silk/fixed/warped_autocorrelation_FIX.lo | 0 .../silk/fixed/warped_autocorrelation_FIX.o | Bin .../src/libopus/silk/gain_quant.c | 0 .../src/libopus/silk/init_decoder.c | 0 .../src/libopus/silk/init_encoder.c | 0 .../src/libopus/silk/inner_prod_aligned.c | 0 .../src/libopus/silk/interpolate.c | 0 .../ESP8266Audio/src/libopus/silk/lin2log.c | 0 .../ESP8266Audio/src/libopus/silk/log2lin.c | 0 .../ESP8266Audio/src/libopus/silk/macros.h | 0 .../ESP8266Audio/src/libopus/silk/main.h | 0 .../src/libopus/silk/pitch_est_defines.h | 0 .../src/libopus/silk/pitch_est_tables.c | 0 .../src/libopus/silk/process_NLSFs.c | 0 .../src/libopus/silk/quant_LTP_gains.c | 0 .../ESP8266Audio/src/libopus/silk/resampler.c | 0 .../src/libopus/silk/resampler_down2.c | 0 .../src/libopus/silk/resampler_down2_3.c | 0 .../src/libopus/silk/resampler_private.h | 0 .../src/libopus/silk/resampler_private_AR2.c | 0 .../libopus/silk/resampler_private_IIR_FIR.c | 0 .../libopus/silk/resampler_private_down_FIR.c | 0 .../libopus/silk/resampler_private_up2_HQ.c | 0 .../src/libopus/silk/resampler_rom.c | 0 .../src/libopus/silk/resampler_rom.h | 0 .../src/libopus/silk/resampler_structs.h | 0 .../src/libopus/silk/shell_coder.c | 0 .../ESP8266Audio/src/libopus/silk/sigm_Q15.c | 0 .../ESP8266Audio/src/libopus/silk/sort.c | 0 .../src/libopus/silk/stereo_LR_to_MS.c | 0 .../src/libopus/silk/stereo_MS_to_LR.c | 0 .../src/libopus/silk/stereo_decode_pred.c | 0 .../src/libopus/silk/stereo_encode_pred.c | 0 .../src/libopus/silk/stereo_find_predictor.c | 0 .../src/libopus/silk/stereo_quant_pred.c | 0 .../ESP8266Audio/src/libopus/silk/structs.h | 0 .../src/libopus/silk/sum_sqr_shift.c | 0 .../src/libopus/silk/table_LSF_cos.c | 0 .../ESP8266Audio/src/libopus/silk/tables.h | 0 .../src/libopus/silk/tables_LTP.c | 0 .../src/libopus/silk/tables_NLSF_CB_NB_MB.c | 0 .../src/libopus/silk/tables_NLSF_CB_WB.c | 0 .../src/libopus/silk/tables_gain.c | 0 .../src/libopus/silk/tables_other.c | 0 .../src/libopus/silk/tables_pitch_lag.c | 0 .../libopus/silk/tables_pulses_per_block.c | 0 .../src/libopus/silk/tuning_parameters.h | 0 .../ESP8266Audio/src/libopus/silk/typedef.h | 0 .../ESP8266Audio/src/libopus/tansig_table.h | 0 .../ESP8266Audio/src/libtinysoundfont/LICENSE | 0 .../src/libtinysoundfont/README.ESP8266 | 0 .../src/libtinysoundfont/README.md | 0 .../ESP8266Audio/src/libtinysoundfont/tsf.h | 0 .../ESP8266Audio/src/opusfile/AUTHORS | 0 .../ESP8266Audio/src/opusfile/COPYING | 0 .../src/opusfile/README.esp8266.md | 0 .../ESP8266Audio/src/opusfile/README.md | 0 .../ESP8266Audio/src/opusfile/config.h | 0 .../ESP8266Audio/src/opusfile/info.c | 0 .../ESP8266Audio/src/opusfile/internal.c | 0 .../ESP8266Audio/src/opusfile/internal.h | 0 .../ESP8266Audio/src/opusfile/opusfile.c | 0 .../ESP8266Audio/src/opusfile/opusfile.h | 0 .../ESP8266Audio/src/opusfile/opusfile.pc | 0 .../ESP8266Audio/src/opusfile/stream.c | 0 .../ESP8266Audio/src/spiram-fast.h | 0 .../ESP8266Audio/tests/common.sh | 0 .../ESP8266Audio/tests/host/Arduino.h | 0 .../ESP8266Audio/tests/host/Makefile | 0 .../ESP8266Audio/tests/host/Serial.cpp | 0 .../ESP8266Audio/tests/host/aac.cpp | 0 .../ESP8266Audio/tests/host/midi.cpp | 0 .../ESP8266Audio/tests/host/mp3.cpp | 0 .../ESP8266Audio/tests/host/opus.cpp | 0 .../ESP8266Audio/tests/host/pgmspace.h | 0 .../ESP8266Audio/tests/host/test_8u_16.wav | Bin .../ESP8266Audio/tests/host/wav.cpp | 0 {lib => lib_audio}/ESP8266SAM/README.md | 0 .../ESP8266SAM/examples/Speak/Speak.ino | 0 {lib => lib_audio}/ESP8266SAM/library.json | 0 .../ESP8266SAM/library.properties | 0 .../ESP8266SAM/src/ESP8266SAM.cpp | 0 .../ESP8266SAM/src/ESP8266SAM.h | 0 .../ESP8266SAM/src/ReciterTabs.h | 0 .../ESP8266SAM/src/RenderTabs.h | 0 {lib => lib_audio}/ESP8266SAM/src/SamData.h | 0 {lib => lib_audio}/ESP8266SAM/src/SamTabs.h | 0 {lib => lib_audio}/ESP8266SAM/src/reciter.c | 0 {lib => lib_audio}/ESP8266SAM/src/reciter.h | 0 {lib => lib_audio}/ESP8266SAM/src/render.c | 0 {lib => lib_audio}/ESP8266SAM/src/render.h | 0 {lib => lib_audio}/ESP8266SAM/src/sam.c | 0 {lib => lib_audio}/ESP8266SAM/src/sam.h | 0 {lib => lib_audio}/ESP8266SAM/src/samdebug.c | 0 {lib => lib_audio}/ESP8266SAM/src/samdebug.h | 0 .../C2Programmer-1.0.0/README.md | 0 .../C2Programmer-1.0.0/keywords.txt | 0 .../C2Programmer-1.0.0/library.json | 0 .../C2Programmer-1.0.0/library.properties | 0 .../C2Programmer-1.0.0/src/c2.cpp | 0 .../C2Programmer-1.0.0/src/c2.h | 0 .../C2Programmer-1.0.0/src/ihx.cpp | 0 .../C2Programmer-1.0.0/src/ihx.h | 0 .../.github/CONTRIBUTING.md | 0 .../.github/Contributors.md | 0 .../.github/issue_template.md | 0 .../IRremoteESP8266-2.7.11/.gitignore | 0 .../IRremoteESP8266-2.7.11/.gitmodules | 0 .../IRremoteESP8266-2.7.11/.style.yapf | 0 .../IRremoteESP8266-2.7.11/.travis.yml | 0 .../IRremoteESP8266-2.7.11/CPPLINT.cfg | 0 .../IRremoteESP8266-2.7.11/Doxyfile | 0 .../IRremoteESP8266-2.7.11/LICENSE.txt | 0 .../IRremoteESP8266-2.7.11/README.md | 0 .../IRremoteESP8266-2.7.11/README_fr.md | 0 .../IRremoteESP8266-2.7.11/ReleaseNotes.md | 0 .../SupportedProtocols.md | 0 .../IRremoteESP8266-2.7.11/docs/README.md | 0 .../IRremoteESP8266-2.7.11/docs/README_fr.md | 0 .../IRremoteESP8266-2.7.11/docs/_config.yml | 0 .../docs/doxygen/html/IRac_8cpp.html | 0 .../docs/doxygen/html/IRac_8h.html | 0 .../docs/doxygen/html/IRac_8h_source.html | 0 .../docs/doxygen/html/IRrecv_8cpp.html | 0 .../docs/doxygen/html/IRrecv_8h.html | 0 .../docs/doxygen/html/IRrecv_8h_source.html | 0 .../docs/doxygen/html/IRremoteESP8266_8h.html | 0 .../html/IRremoteESP8266_8h_source.html | 0 .../docs/doxygen/html/IRsend_8cpp.html | 0 .../docs/doxygen/html/IRsend_8h.html | 0 .../docs/doxygen/html/IRsend_8h_source.html | 0 .../docs/doxygen/html/IRtext_8cpp.html | 0 .../docs/doxygen/html/IRtext_8h.html | 0 .../docs/doxygen/html/IRtext_8h_source.html | 0 .../docs/doxygen/html/IRtimer_8cpp.html | 0 .../docs/doxygen/html/IRtimer_8h.html | 0 .../docs/doxygen/html/IRtimer_8h_source.html | 0 .../docs/doxygen/html/IRutils_8cpp.html | 0 .../docs/doxygen/html/IRutils_8h.html | 0 .../docs/doxygen/html/IRutils_8h_source.html | 0 .../docs/doxygen/html/README_8md.html | 0 .../docs/doxygen/html/annotated.html | 0 .../docs/doxygen/html/bc_s.png | Bin .../docs/doxygen/html/bdwn.png | Bin .../html/classIRAirwellAc-members.html | 0 .../docs/doxygen/html/classIRAirwellAc.html | 0 .../html/classIRAirwellAc__coll__graph.map | 0 .../html/classIRAirwellAc__coll__graph.md5 | 0 .../html/classIRAirwellAc__coll__graph.png | Bin .../doxygen/html/classIRAmcorAc-members.html | 0 .../docs/doxygen/html/classIRAmcorAc.html | 0 .../html/classIRAmcorAc__coll__graph.map | 0 .../html/classIRAmcorAc__coll__graph.md5 | 0 .../html/classIRAmcorAc__coll__graph.png | Bin .../doxygen/html/classIRArgoAC-members.html | 0 .../docs/doxygen/html/classIRArgoAC.html | 0 .../html/classIRArgoAC__coll__graph.map | 0 .../html/classIRArgoAC__coll__graph.md5 | 0 .../html/classIRArgoAC__coll__graph.png | Bin .../html/classIRCarrierAc64-members.html | 0 .../docs/doxygen/html/classIRCarrierAc64.html | 0 .../html/classIRCarrierAc64__coll__graph.map | 0 .../html/classIRCarrierAc64__coll__graph.md5 | 0 .../html/classIRCarrierAc64__coll__graph.png | Bin .../doxygen/html/classIRCoolixAC-members.html | 0 .../docs/doxygen/html/classIRCoolixAC.html | 0 .../html/classIRCoolixAC__coll__graph.map | 0 .../html/classIRCoolixAC__coll__graph.md5 | 0 .../html/classIRCoolixAC__coll__graph.png | Bin .../doxygen/html/classIRCoronaAc-members.html | 0 .../docs/doxygen/html/classIRCoronaAc.html | 0 .../html/classIRCoronaAc__coll__graph.map | 0 .../html/classIRCoronaAc__coll__graph.md5 | 0 .../html/classIRCoronaAc__coll__graph.png | Bin .../html/classIRDaikin128-members.html | 0 .../docs/doxygen/html/classIRDaikin128.html | 0 .../html/classIRDaikin128__coll__graph.map | 0 .../html/classIRDaikin128__coll__graph.md5 | 0 .../html/classIRDaikin128__coll__graph.png | Bin .../html/classIRDaikin152-members.html | 0 .../docs/doxygen/html/classIRDaikin152.html | 0 .../html/classIRDaikin152__coll__graph.map | 0 .../html/classIRDaikin152__coll__graph.md5 | 0 .../html/classIRDaikin152__coll__graph.png | Bin .../html/classIRDaikin160-members.html | 0 .../docs/doxygen/html/classIRDaikin160.html | 0 .../html/classIRDaikin160__coll__graph.map | 0 .../html/classIRDaikin160__coll__graph.md5 | 0 .../html/classIRDaikin160__coll__graph.png | Bin .../html/classIRDaikin176-members.html | 0 .../docs/doxygen/html/classIRDaikin176.html | 0 .../html/classIRDaikin176__coll__graph.map | 0 .../html/classIRDaikin176__coll__graph.md5 | 0 .../html/classIRDaikin176__coll__graph.png | Bin .../doxygen/html/classIRDaikin2-members.html | 0 .../docs/doxygen/html/classIRDaikin2.html | 0 .../html/classIRDaikin216-members.html | 0 .../docs/doxygen/html/classIRDaikin216.html | 0 .../html/classIRDaikin216__coll__graph.map | 0 .../html/classIRDaikin216__coll__graph.md5 | 0 .../html/classIRDaikin216__coll__graph.png | Bin .../html/classIRDaikin2__coll__graph.map | 0 .../html/classIRDaikin2__coll__graph.md5 | 0 .../html/classIRDaikin2__coll__graph.png | Bin .../doxygen/html/classIRDaikin64-members.html | 0 .../docs/doxygen/html/classIRDaikin64.html | 0 .../html/classIRDaikin64__coll__graph.map | 0 .../html/classIRDaikin64__coll__graph.md5 | 0 .../html/classIRDaikin64__coll__graph.png | Bin .../html/classIRDaikinESP-members.html | 0 .../docs/doxygen/html/classIRDaikinESP.html | 0 .../html/classIRDaikinESP__coll__graph.map | 0 .../html/classIRDaikinESP__coll__graph.md5 | 0 .../html/classIRDaikinESP__coll__graph.png | Bin .../html/classIRDelonghiAc-members.html | 0 .../docs/doxygen/html/classIRDelonghiAc.html | 0 .../html/classIRDelonghiAc__coll__graph.map | 0 .../html/classIRDelonghiAc__coll__graph.md5 | 0 .../html/classIRDelonghiAc__coll__graph.png | Bin .../html/classIRElectraAc-members.html | 0 .../docs/doxygen/html/classIRElectraAc.html | 0 .../html/classIRElectraAc__coll__graph.map | 0 .../html/classIRElectraAc__coll__graph.md5 | 0 .../html/classIRElectraAc__coll__graph.png | Bin .../html/classIRFujitsuAC-members.html | 0 .../docs/doxygen/html/classIRFujitsuAC.html | 0 .../html/classIRFujitsuAC__coll__graph.map | 0 .../html/classIRFujitsuAC__coll__graph.md5 | 0 .../html/classIRFujitsuAC__coll__graph.png | Bin .../html/classIRGoodweatherAc-members.html | 0 .../doxygen/html/classIRGoodweatherAc.html | 0 .../classIRGoodweatherAc__coll__graph.map | 0 .../classIRGoodweatherAc__coll__graph.md5 | 0 .../classIRGoodweatherAc__coll__graph.png | Bin .../doxygen/html/classIRGreeAC-members.html | 0 .../docs/doxygen/html/classIRGreeAC.html | 0 .../html/classIRGreeAC__coll__graph.map | 0 .../html/classIRGreeAC__coll__graph.md5 | 0 .../html/classIRGreeAC__coll__graph.png | Bin .../doxygen/html/classIRHaierAC-members.html | 0 .../docs/doxygen/html/classIRHaierAC.html | 0 .../html/classIRHaierACYRW02-members.html | 0 .../doxygen/html/classIRHaierACYRW02.html | 0 .../html/classIRHaierACYRW02__coll__graph.map | 0 .../html/classIRHaierACYRW02__coll__graph.md5 | 0 .../html/classIRHaierACYRW02__coll__graph.png | Bin .../html/classIRHaierAC__coll__graph.map | 0 .../html/classIRHaierAC__coll__graph.md5 | 0 .../html/classIRHaierAC__coll__graph.png | Bin .../html/classIRHitachiAc-members.html | 0 .../docs/doxygen/html/classIRHitachiAc.html | 0 .../html/classIRHitachiAc1-members.html | 0 .../docs/doxygen/html/classIRHitachiAc1.html | 0 .../html/classIRHitachiAc1__coll__graph.map | 0 .../html/classIRHitachiAc1__coll__graph.md5 | 0 .../html/classIRHitachiAc1__coll__graph.png | Bin .../html/classIRHitachiAc3-members.html | 0 .../docs/doxygen/html/classIRHitachiAc3.html | 0 .../html/classIRHitachiAc344-members.html | 0 .../doxygen/html/classIRHitachiAc344.html | 0 .../html/classIRHitachiAc344__coll__graph.map | 0 .../html/classIRHitachiAc344__coll__graph.md5 | 0 .../html/classIRHitachiAc344__coll__graph.png | Bin .../classIRHitachiAc344__inherit__graph.map | 0 .../classIRHitachiAc344__inherit__graph.md5 | 0 .../classIRHitachiAc344__inherit__graph.png | Bin .../html/classIRHitachiAc3__coll__graph.map | 0 .../html/classIRHitachiAc3__coll__graph.md5 | 0 .../html/classIRHitachiAc3__coll__graph.png | Bin .../html/classIRHitachiAc424-members.html | 0 .../doxygen/html/classIRHitachiAc424.html | 0 .../html/classIRHitachiAc424__coll__graph.map | 0 .../html/classIRHitachiAc424__coll__graph.md5 | 0 .../html/classIRHitachiAc424__coll__graph.png | Bin .../classIRHitachiAc424__inherit__graph.map | 0 .../classIRHitachiAc424__inherit__graph.md5 | 0 .../classIRHitachiAc424__inherit__graph.png | Bin .../html/classIRHitachiAc__coll__graph.map | 0 .../html/classIRHitachiAc__coll__graph.md5 | 0 .../html/classIRHitachiAc__coll__graph.png | Bin .../html/classIRKelvinatorAC-members.html | 0 .../doxygen/html/classIRKelvinatorAC.html | 0 .../html/classIRKelvinatorAC__coll__graph.map | 0 .../html/classIRKelvinatorAC__coll__graph.md5 | 0 .../html/classIRKelvinatorAC__coll__graph.png | Bin .../doxygen/html/classIRLgAc-members.html | 0 .../docs/doxygen/html/classIRLgAc.html | 0 .../doxygen/html/classIRLgAc__coll__graph.map | 0 .../doxygen/html/classIRLgAc__coll__graph.md5 | 0 .../doxygen/html/classIRLgAc__coll__graph.png | Bin .../doxygen/html/classIRMideaAC-members.html | 0 .../docs/doxygen/html/classIRMideaAC.html | 0 .../html/classIRMideaAC__coll__graph.map | 0 .../html/classIRMideaAC__coll__graph.md5 | 0 .../html/classIRMideaAC__coll__graph.png | Bin .../html/classIRMitsubishi112-members.html | 0 .../doxygen/html/classIRMitsubishi112.html | 0 .../classIRMitsubishi112__coll__graph.map | 0 .../classIRMitsubishi112__coll__graph.md5 | 0 .../classIRMitsubishi112__coll__graph.png | Bin .../html/classIRMitsubishi136-members.html | 0 .../doxygen/html/classIRMitsubishi136.html | 0 .../classIRMitsubishi136__coll__graph.map | 0 .../classIRMitsubishi136__coll__graph.md5 | 0 .../classIRMitsubishi136__coll__graph.png | Bin .../html/classIRMitsubishiAC-members.html | 0 .../doxygen/html/classIRMitsubishiAC.html | 0 .../html/classIRMitsubishiAC__coll__graph.map | 0 .../html/classIRMitsubishiAC__coll__graph.md5 | 0 .../html/classIRMitsubishiAC__coll__graph.png | Bin .../classIRMitsubishiHeavy152Ac-members.html | 0 .../html/classIRMitsubishiHeavy152Ac.html | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.map | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.md5 | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.png | Bin .../classIRMitsubishiHeavy88Ac-members.html | 0 .../html/classIRMitsubishiHeavy88Ac.html | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.map | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.md5 | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.png | Bin .../html/classIRNeoclimaAc-members.html | 0 .../docs/doxygen/html/classIRNeoclimaAc.html | 0 .../html/classIRNeoclimaAc__coll__graph.map | 0 .../html/classIRNeoclimaAc__coll__graph.md5 | 0 .../html/classIRNeoclimaAc__coll__graph.png | Bin .../html/classIRPanasonicAc-members.html | 0 .../docs/doxygen/html/classIRPanasonicAc.html | 0 .../html/classIRPanasonicAc__coll__graph.map | 0 .../html/classIRPanasonicAc__coll__graph.md5 | 0 .../html/classIRPanasonicAc__coll__graph.png | Bin .../html/classIRSamsungAc-members.html | 0 .../docs/doxygen/html/classIRSamsungAc.html | 0 .../html/classIRSamsungAc__coll__graph.map | 0 .../html/classIRSamsungAc__coll__graph.md5 | 0 .../html/classIRSamsungAc__coll__graph.png | Bin .../doxygen/html/classIRSanyoAc-members.html | 0 .../docs/doxygen/html/classIRSanyoAc.html | 0 .../html/classIRSanyoAc__coll__graph.map | 0 .../html/classIRSanyoAc__coll__graph.md5 | 0 .../html/classIRSanyoAc__coll__graph.png | Bin .../doxygen/html/classIRSharpAc-members.html | 0 .../docs/doxygen/html/classIRSharpAc.html | 0 .../html/classIRSharpAc__coll__graph.map | 0 .../html/classIRSharpAc__coll__graph.md5 | 0 .../html/classIRSharpAc__coll__graph.png | Bin .../doxygen/html/classIRTcl112Ac-members.html | 0 .../docs/doxygen/html/classIRTcl112Ac.html | 0 .../html/classIRTcl112Ac__coll__graph.map | 0 .../html/classIRTcl112Ac__coll__graph.md5 | 0 .../html/classIRTcl112Ac__coll__graph.png | Bin .../html/classIRTechnibelAc-members.html | 0 .../docs/doxygen/html/classIRTechnibelAc.html | 0 .../html/classIRTechnibelAc__coll__graph.map | 0 .../html/classIRTechnibelAc__coll__graph.md5 | 0 .../html/classIRTechnibelAc__coll__graph.png | Bin .../doxygen/html/classIRTecoAc-members.html | 0 .../docs/doxygen/html/classIRTecoAc.html | 0 .../html/classIRTecoAc__coll__graph.map | 0 .../html/classIRTecoAc__coll__graph.md5 | 0 .../html/classIRTecoAc__coll__graph.png | Bin .../html/classIRToshibaAC-members.html | 0 .../docs/doxygen/html/classIRToshibaAC.html | 0 .../html/classIRToshibaAC__coll__graph.map | 0 .../html/classIRToshibaAC__coll__graph.md5 | 0 .../html/classIRToshibaAC__coll__graph.png | Bin .../html/classIRTranscoldAc-members.html | 0 .../docs/doxygen/html/classIRTranscoldAc.html | 0 .../html/classIRTranscoldAc__coll__graph.map | 0 .../html/classIRTranscoldAc__coll__graph.md5 | 0 .../html/classIRTranscoldAc__coll__graph.png | Bin .../html/classIRTrotecESP-members.html | 0 .../docs/doxygen/html/classIRTrotecESP.html | 0 .../html/classIRTrotecESP__coll__graph.map | 0 .../html/classIRTrotecESP__coll__graph.md5 | 0 .../html/classIRTrotecESP__coll__graph.png | Bin .../doxygen/html/classIRVestelAc-members.html | 0 .../docs/doxygen/html/classIRVestelAc.html | 0 .../html/classIRVestelAc__coll__graph.map | 0 .../html/classIRVestelAc__coll__graph.md5 | 0 .../html/classIRVestelAc__coll__graph.png | Bin .../doxygen/html/classIRVoltas-members.html | 0 .../docs/doxygen/html/classIRVoltas.html | 0 .../html/classIRVoltas__coll__graph.map | 0 .../html/classIRVoltas__coll__graph.md5 | 0 .../html/classIRVoltas__coll__graph.png | Bin .../html/classIRWhirlpoolAc-members.html | 0 .../docs/doxygen/html/classIRWhirlpoolAc.html | 0 .../html/classIRWhirlpoolAc__coll__graph.map | 0 .../html/classIRWhirlpoolAc__coll__graph.md5 | 0 .../html/classIRWhirlpoolAc__coll__graph.png | Bin .../docs/doxygen/html/classIRac-members.html | 0 .../docs/doxygen/html/classIRac.html | 0 .../doxygen/html/classIRac__coll__graph.map | 0 .../doxygen/html/classIRac__coll__graph.md5 | 0 .../doxygen/html/classIRac__coll__graph.png | Bin .../doxygen/html/classIRrecv-members.html | 0 .../docs/doxygen/html/classIRrecv.html | 0 .../doxygen/html/classIRrecv__coll__graph.map | 0 .../doxygen/html/classIRrecv__coll__graph.md5 | 0 .../doxygen/html/classIRrecv__coll__graph.png | Bin .../doxygen/html/classIRsend-members.html | 0 .../docs/doxygen/html/classIRsend.html | 0 .../doxygen/html/classIRtimer-members.html | 0 .../docs/doxygen/html/classIRtimer.html | 0 .../doxygen/html/classTimerMs-members.html | 0 .../docs/doxygen/html/classTimerMs.html | 0 .../html/classdecode__results-members.html | 0 .../doxygen/html/classdecode__results.html | 0 .../docs/doxygen/html/classes.html | 0 .../docs/doxygen/html/closed.png | Bin .../docs/doxygen/html/de-CH_8h.html | 0 .../docs/doxygen/html/de-CH_8h_source.html | 0 .../docs/doxygen/html/de-DE_8h.html | 0 .../docs/doxygen/html/de-DE_8h_source.html | 0 .../docs/doxygen/html/defaults_8h.html | 0 .../docs/doxygen/html/defaults_8h_source.html | 0 .../docs/doxygen/html/deprecated.html | 0 .../dir_49e56c817e5e54854c35e136979f97ca.html | 0 .../dir_68267d1309a1af8e8297ef4c3efbcdba.html | 0 .../dir_84fe998d1eb06414cc389ad334e77e63.html | 0 .../docs/doxygen/html/doc.png | Bin .../docs/doxygen/html/doxygen.css | 0 .../docs/doxygen/html/doxygen.png | Bin .../docs/doxygen/html/doxygen__index_8md.html | 0 .../docs/doxygen/html/dynsections.js | 0 .../docs/doxygen/html/en-AU_8h.html | 0 .../docs/doxygen/html/en-AU_8h_source.html | 0 .../docs/doxygen/html/en-IE_8h.html | 0 .../docs/doxygen/html/en-IE_8h_source.html | 0 .../docs/doxygen/html/en-UK_8h.html | 0 .../docs/doxygen/html/en-UK_8h_source.html | 0 .../docs/doxygen/html/en-US_8h.html | 0 .../docs/doxygen/html/en-US_8h_source.html | 0 .../docs/doxygen/html/es-ES_8h.html | 0 .../docs/doxygen/html/es-ES_8h_source.html | 0 .../docs/doxygen/html/files.html | 0 .../docs/doxygen/html/folderclosed.png | Bin .../docs/doxygen/html/folderopen.png | Bin .../docs/doxygen/html/fr-FR_8h.html | 0 .../docs/doxygen/html/fr-FR_8h_source.html | 0 .../docs/doxygen/html/functions.html | 0 .../docs/doxygen/html/functions_a.html | 0 .../docs/doxygen/html/functions_b.html | 0 .../docs/doxygen/html/functions_c.html | 0 .../docs/doxygen/html/functions_d.html | 0 .../docs/doxygen/html/functions_e.html | 0 .../docs/doxygen/html/functions_f.html | 0 .../docs/doxygen/html/functions_func.html | 0 .../docs/doxygen/html/functions_func_a.html | 0 .../docs/doxygen/html/functions_func_b.html | 0 .../docs/doxygen/html/functions_func_c.html | 0 .../docs/doxygen/html/functions_func_d.html | 0 .../docs/doxygen/html/functions_func_e.html | 0 .../docs/doxygen/html/functions_func_f.html | 0 .../docs/doxygen/html/functions_func_g.html | 0 .../docs/doxygen/html/functions_func_h.html | 0 .../docs/doxygen/html/functions_func_i.html | 0 .../docs/doxygen/html/functions_func_k.html | 0 .../docs/doxygen/html/functions_func_l.html | 0 .../docs/doxygen/html/functions_func_m.html | 0 .../docs/doxygen/html/functions_func_n.html | 0 .../docs/doxygen/html/functions_func_o.html | 0 .../docs/doxygen/html/functions_func_p.html | 0 .../docs/doxygen/html/functions_func_r.html | 0 .../docs/doxygen/html/functions_func_s.html | 0 .../docs/doxygen/html/functions_func_t.html | 0 .../docs/doxygen/html/functions_func_u.html | 0 .../docs/doxygen/html/functions_func_v.html | 0 .../docs/doxygen/html/functions_func_w.html | 0 .../docs/doxygen/html/functions_func_~.html | 0 .../docs/doxygen/html/functions_g.html | 0 .../docs/doxygen/html/functions_h.html | 0 .../docs/doxygen/html/functions_i.html | 0 .../docs/doxygen/html/functions_k.html | 0 .../docs/doxygen/html/functions_l.html | 0 .../docs/doxygen/html/functions_m.html | 0 .../docs/doxygen/html/functions_n.html | 0 .../docs/doxygen/html/functions_o.html | 0 .../docs/doxygen/html/functions_p.html | 0 .../docs/doxygen/html/functions_q.html | 0 .../docs/doxygen/html/functions_r.html | 0 .../docs/doxygen/html/functions_rela.html | 0 .../docs/doxygen/html/functions_s.html | 0 .../docs/doxygen/html/functions_t.html | 0 .../docs/doxygen/html/functions_u.html | 0 .../docs/doxygen/html/functions_v.html | 0 .../docs/doxygen/html/functions_vars.html | 0 .../docs/doxygen/html/functions_vars_a.html | 0 .../docs/doxygen/html/functions_vars_b.html | 0 .../docs/doxygen/html/functions_vars_c.html | 0 .../docs/doxygen/html/functions_vars_d.html | 0 .../docs/doxygen/html/functions_vars_e.html | 0 .../docs/doxygen/html/functions_vars_f.html | 0 .../docs/doxygen/html/functions_vars_h.html | 0 .../docs/doxygen/html/functions_vars_i.html | 0 .../docs/doxygen/html/functions_vars_l.html | 0 .../docs/doxygen/html/functions_vars_m.html | 0 .../docs/doxygen/html/functions_vars_n.html | 0 .../docs/doxygen/html/functions_vars_o.html | 0 .../docs/doxygen/html/functions_vars_p.html | 0 .../docs/doxygen/html/functions_vars_q.html | 0 .../docs/doxygen/html/functions_vars_r.html | 0 .../docs/doxygen/html/functions_vars_s.html | 0 .../docs/doxygen/html/functions_vars_t.html | 0 .../docs/doxygen/html/functions_vars_u.html | 0 .../docs/doxygen/html/functions_vars_v.html | 0 .../docs/doxygen/html/functions_vars_w.html | 0 .../docs/doxygen/html/functions_vars_x.html | 0 .../docs/doxygen/html/functions_vars_z.html | 0 .../docs/doxygen/html/functions_w.html | 0 .../docs/doxygen/html/functions_x.html | 0 .../docs/doxygen/html/functions_z.html | 0 .../docs/doxygen/html/functions_~.html | 0 .../docs/doxygen/html/globals.html | 0 .../docs/doxygen/html/globals_a.html | 0 .../docs/doxygen/html/globals_c.html | 0 .../docs/doxygen/html/globals_d.html | 0 .../docs/doxygen/html/globals_e.html | 0 .../docs/doxygen/html/globals_enum.html | 0 .../docs/doxygen/html/globals_eval.html | 0 .../docs/doxygen/html/globals_f.html | 0 .../docs/doxygen/html/globals_func.html | 0 .../docs/doxygen/html/globals_g.html | 0 .../docs/doxygen/html/globals_h.html | 0 .../docs/doxygen/html/globals_i.html | 0 .../docs/doxygen/html/globals_j.html | 0 .../docs/doxygen/html/globals_k.html | 0 .../docs/doxygen/html/globals_l.html | 0 .../docs/doxygen/html/globals_m.html | 0 .../docs/doxygen/html/globals_n.html | 0 .../docs/doxygen/html/globals_p.html | 0 .../docs/doxygen/html/globals_r.html | 0 .../docs/doxygen/html/globals_s.html | 0 .../docs/doxygen/html/globals_t.html | 0 .../docs/doxygen/html/globals_type.html | 0 .../docs/doxygen/html/globals_u.html | 0 .../docs/doxygen/html/globals_v.html | 0 .../docs/doxygen/html/globals_vars.html | 0 .../docs/doxygen/html/globals_vars_i.html | 0 .../docs/doxygen/html/globals_vars_k.html | 0 .../docs/doxygen/html/globals_w.html | 0 .../docs/doxygen/html/globals_x.html | 0 .../docs/doxygen/html/globals_y.html | 0 .../docs/doxygen/html/globals_z.html | 0 .../docs/doxygen/html/graph_legend.html | 0 .../docs/doxygen/html/graph_legend.md5 | 0 .../docs/doxygen/html/graph_legend.png | Bin .../docs/doxygen/html/hierarchy.html | 0 .../docs/doxygen/html/i18n_8h.html | 0 .../docs/doxygen/html/i18n_8h_source.html | 0 .../docs/doxygen/html/index.html | 0 .../docs/doxygen/html/inherit_graph_0.map | 0 .../docs/doxygen/html/inherit_graph_0.md5 | 0 .../docs/doxygen/html/inherit_graph_0.png | Bin .../docs/doxygen/html/inherit_graph_1.map | 0 .../docs/doxygen/html/inherit_graph_1.md5 | 0 .../docs/doxygen/html/inherit_graph_1.png | Bin .../docs/doxygen/html/inherit_graph_10.map | 0 .../docs/doxygen/html/inherit_graph_10.md5 | 0 .../docs/doxygen/html/inherit_graph_10.png | Bin .../docs/doxygen/html/inherit_graph_11.map | 0 .../docs/doxygen/html/inherit_graph_11.md5 | 0 .../docs/doxygen/html/inherit_graph_11.png | Bin .../docs/doxygen/html/inherit_graph_12.map | 0 .../docs/doxygen/html/inherit_graph_12.md5 | 0 .../docs/doxygen/html/inherit_graph_12.png | Bin .../docs/doxygen/html/inherit_graph_13.map | 0 .../docs/doxygen/html/inherit_graph_13.md5 | 0 .../docs/doxygen/html/inherit_graph_13.png | Bin .../docs/doxygen/html/inherit_graph_14.map | 0 .../docs/doxygen/html/inherit_graph_14.md5 | 0 .../docs/doxygen/html/inherit_graph_14.png | Bin .../docs/doxygen/html/inherit_graph_15.map | 0 .../docs/doxygen/html/inherit_graph_15.md5 | 0 .../docs/doxygen/html/inherit_graph_15.png | Bin .../docs/doxygen/html/inherit_graph_16.map | 0 .../docs/doxygen/html/inherit_graph_16.md5 | 0 .../docs/doxygen/html/inherit_graph_16.png | Bin .../docs/doxygen/html/inherit_graph_17.map | 0 .../docs/doxygen/html/inherit_graph_17.md5 | 0 .../docs/doxygen/html/inherit_graph_17.png | Bin .../docs/doxygen/html/inherit_graph_18.map | 0 .../docs/doxygen/html/inherit_graph_18.md5 | 0 .../docs/doxygen/html/inherit_graph_18.png | Bin .../docs/doxygen/html/inherit_graph_19.map | 0 .../docs/doxygen/html/inherit_graph_19.md5 | 0 .../docs/doxygen/html/inherit_graph_19.png | Bin .../docs/doxygen/html/inherit_graph_2.map | 0 .../docs/doxygen/html/inherit_graph_2.md5 | 0 .../docs/doxygen/html/inherit_graph_2.png | Bin .../docs/doxygen/html/inherit_graph_20.map | 0 .../docs/doxygen/html/inherit_graph_20.md5 | 0 .../docs/doxygen/html/inherit_graph_20.png | Bin .../docs/doxygen/html/inherit_graph_21.map | 0 .../docs/doxygen/html/inherit_graph_21.md5 | 0 .../docs/doxygen/html/inherit_graph_21.png | Bin .../docs/doxygen/html/inherit_graph_22.map | 0 .../docs/doxygen/html/inherit_graph_22.md5 | 0 .../docs/doxygen/html/inherit_graph_22.png | Bin .../docs/doxygen/html/inherit_graph_23.map | 0 .../docs/doxygen/html/inherit_graph_23.md5 | 0 .../docs/doxygen/html/inherit_graph_23.png | Bin .../docs/doxygen/html/inherit_graph_24.map | 0 .../docs/doxygen/html/inherit_graph_24.md5 | 0 .../docs/doxygen/html/inherit_graph_24.png | Bin .../docs/doxygen/html/inherit_graph_25.map | 0 .../docs/doxygen/html/inherit_graph_25.md5 | 0 .../docs/doxygen/html/inherit_graph_25.png | Bin .../docs/doxygen/html/inherit_graph_26.map | 0 .../docs/doxygen/html/inherit_graph_26.md5 | 0 .../docs/doxygen/html/inherit_graph_26.png | Bin .../docs/doxygen/html/inherit_graph_27.map | 0 .../docs/doxygen/html/inherit_graph_27.md5 | 0 .../docs/doxygen/html/inherit_graph_27.png | Bin .../docs/doxygen/html/inherit_graph_28.map | 0 .../docs/doxygen/html/inherit_graph_28.md5 | 0 .../docs/doxygen/html/inherit_graph_28.png | Bin .../docs/doxygen/html/inherit_graph_29.map | 0 .../docs/doxygen/html/inherit_graph_29.md5 | 0 .../docs/doxygen/html/inherit_graph_29.png | Bin .../docs/doxygen/html/inherit_graph_3.map | 0 .../docs/doxygen/html/inherit_graph_3.md5 | 0 .../docs/doxygen/html/inherit_graph_3.png | Bin .../docs/doxygen/html/inherit_graph_30.map | 0 .../docs/doxygen/html/inherit_graph_30.md5 | 0 .../docs/doxygen/html/inherit_graph_30.png | Bin .../docs/doxygen/html/inherit_graph_31.map | 0 .../docs/doxygen/html/inherit_graph_31.md5 | 0 .../docs/doxygen/html/inherit_graph_31.png | Bin .../docs/doxygen/html/inherit_graph_32.map | 0 .../docs/doxygen/html/inherit_graph_32.md5 | 0 .../docs/doxygen/html/inherit_graph_32.png | Bin .../docs/doxygen/html/inherit_graph_33.map | 0 .../docs/doxygen/html/inherit_graph_33.md5 | 0 .../docs/doxygen/html/inherit_graph_33.png | Bin .../docs/doxygen/html/inherit_graph_34.map | 0 .../docs/doxygen/html/inherit_graph_34.md5 | 0 .../docs/doxygen/html/inherit_graph_34.png | Bin .../docs/doxygen/html/inherit_graph_35.map | 0 .../docs/doxygen/html/inherit_graph_35.md5 | 0 .../docs/doxygen/html/inherit_graph_35.png | Bin .../docs/doxygen/html/inherit_graph_36.map | 0 .../docs/doxygen/html/inherit_graph_36.md5 | 0 .../docs/doxygen/html/inherit_graph_36.png | Bin .../docs/doxygen/html/inherit_graph_37.map | 0 .../docs/doxygen/html/inherit_graph_37.md5 | 0 .../docs/doxygen/html/inherit_graph_37.png | Bin .../docs/doxygen/html/inherit_graph_38.map | 0 .../docs/doxygen/html/inherit_graph_38.md5 | 0 .../docs/doxygen/html/inherit_graph_38.png | Bin .../docs/doxygen/html/inherit_graph_39.map | 0 .../docs/doxygen/html/inherit_graph_39.md5 | 0 .../docs/doxygen/html/inherit_graph_39.png | Bin .../docs/doxygen/html/inherit_graph_4.map | 0 .../docs/doxygen/html/inherit_graph_4.md5 | 0 .../docs/doxygen/html/inherit_graph_4.png | Bin .../docs/doxygen/html/inherit_graph_40.map | 0 .../docs/doxygen/html/inherit_graph_40.md5 | 0 .../docs/doxygen/html/inherit_graph_40.png | Bin .../docs/doxygen/html/inherit_graph_41.map | 0 .../docs/doxygen/html/inherit_graph_41.md5 | 0 .../docs/doxygen/html/inherit_graph_41.png | Bin .../docs/doxygen/html/inherit_graph_42.map | 0 .../docs/doxygen/html/inherit_graph_42.md5 | 0 .../docs/doxygen/html/inherit_graph_42.png | Bin .../docs/doxygen/html/inherit_graph_43.map | 0 .../docs/doxygen/html/inherit_graph_43.md5 | 0 .../docs/doxygen/html/inherit_graph_43.png | Bin .../docs/doxygen/html/inherit_graph_44.map | 0 .../docs/doxygen/html/inherit_graph_44.md5 | 0 .../docs/doxygen/html/inherit_graph_44.png | Bin .../docs/doxygen/html/inherit_graph_45.map | 0 .../docs/doxygen/html/inherit_graph_45.md5 | 0 .../docs/doxygen/html/inherit_graph_45.png | Bin .../docs/doxygen/html/inherit_graph_46.map | 0 .../docs/doxygen/html/inherit_graph_46.md5 | 0 .../docs/doxygen/html/inherit_graph_46.png | Bin .../docs/doxygen/html/inherit_graph_47.map | 0 .../docs/doxygen/html/inherit_graph_47.md5 | 0 .../docs/doxygen/html/inherit_graph_47.png | Bin .../docs/doxygen/html/inherit_graph_48.map | 0 .../docs/doxygen/html/inherit_graph_48.md5 | 0 .../docs/doxygen/html/inherit_graph_48.png | Bin .../docs/doxygen/html/inherit_graph_49.map | 0 .../docs/doxygen/html/inherit_graph_49.md5 | 0 .../docs/doxygen/html/inherit_graph_49.png | Bin .../docs/doxygen/html/inherit_graph_5.map | 0 .../docs/doxygen/html/inherit_graph_5.md5 | 0 .../docs/doxygen/html/inherit_graph_5.png | Bin .../docs/doxygen/html/inherit_graph_50.map | 0 .../docs/doxygen/html/inherit_graph_50.md5 | 0 .../docs/doxygen/html/inherit_graph_50.png | Bin .../docs/doxygen/html/inherit_graph_51.map | 0 .../docs/doxygen/html/inherit_graph_51.md5 | 0 .../docs/doxygen/html/inherit_graph_51.png | Bin .../docs/doxygen/html/inherit_graph_52.map | 0 .../docs/doxygen/html/inherit_graph_52.md5 | 0 .../docs/doxygen/html/inherit_graph_52.png | Bin .../docs/doxygen/html/inherit_graph_53.map | 0 .../docs/doxygen/html/inherit_graph_53.md5 | 0 .../docs/doxygen/html/inherit_graph_53.png | Bin .../docs/doxygen/html/inherit_graph_54.map | 0 .../docs/doxygen/html/inherit_graph_54.md5 | 0 .../docs/doxygen/html/inherit_graph_54.png | Bin .../docs/doxygen/html/inherit_graph_55.map | 0 .../docs/doxygen/html/inherit_graph_55.md5 | 0 .../docs/doxygen/html/inherit_graph_55.png | Bin .../docs/doxygen/html/inherit_graph_56.map | 0 .../docs/doxygen/html/inherit_graph_56.md5 | 0 .../docs/doxygen/html/inherit_graph_56.png | Bin .../docs/doxygen/html/inherit_graph_57.map | 0 .../docs/doxygen/html/inherit_graph_57.md5 | 0 .../docs/doxygen/html/inherit_graph_57.png | Bin .../docs/doxygen/html/inherit_graph_58.map | 0 .../docs/doxygen/html/inherit_graph_58.md5 | 0 .../docs/doxygen/html/inherit_graph_58.png | Bin .../docs/doxygen/html/inherit_graph_59.map | 0 .../docs/doxygen/html/inherit_graph_59.md5 | 0 .../docs/doxygen/html/inherit_graph_59.png | Bin .../docs/doxygen/html/inherit_graph_6.map | 0 .../docs/doxygen/html/inherit_graph_6.md5 | 0 .../docs/doxygen/html/inherit_graph_6.png | Bin .../docs/doxygen/html/inherit_graph_60.map | 0 .../docs/doxygen/html/inherit_graph_60.md5 | 0 .../docs/doxygen/html/inherit_graph_60.png | Bin .../docs/doxygen/html/inherit_graph_61.map | 0 .../docs/doxygen/html/inherit_graph_61.md5 | 0 .../docs/doxygen/html/inherit_graph_61.png | Bin .../docs/doxygen/html/inherit_graph_62.map | 0 .../docs/doxygen/html/inherit_graph_62.md5 | 0 .../docs/doxygen/html/inherit_graph_62.png | Bin .../docs/doxygen/html/inherit_graph_63.map | 0 .../docs/doxygen/html/inherit_graph_63.md5 | 0 .../docs/doxygen/html/inherit_graph_63.png | Bin .../docs/doxygen/html/inherit_graph_64.map | 0 .../docs/doxygen/html/inherit_graph_64.md5 | 0 .../docs/doxygen/html/inherit_graph_64.png | Bin .../docs/doxygen/html/inherit_graph_65.map | 0 .../docs/doxygen/html/inherit_graph_65.md5 | 0 .../docs/doxygen/html/inherit_graph_65.png | Bin .../docs/doxygen/html/inherit_graph_66.map | 0 .../docs/doxygen/html/inherit_graph_66.md5 | 0 .../docs/doxygen/html/inherit_graph_66.png | Bin .../docs/doxygen/html/inherit_graph_67.map | 0 .../docs/doxygen/html/inherit_graph_67.md5 | 0 .../docs/doxygen/html/inherit_graph_67.png | Bin .../docs/doxygen/html/inherit_graph_68.map | 0 .../docs/doxygen/html/inherit_graph_68.md5 | 0 .../docs/doxygen/html/inherit_graph_68.png | Bin .../docs/doxygen/html/inherit_graph_7.map | 0 .../docs/doxygen/html/inherit_graph_7.md5 | 0 .../docs/doxygen/html/inherit_graph_7.png | Bin .../docs/doxygen/html/inherit_graph_8.map | 0 .../docs/doxygen/html/inherit_graph_8.md5 | 0 .../docs/doxygen/html/inherit_graph_8.png | Bin .../docs/doxygen/html/inherit_graph_9.map | 0 .../docs/doxygen/html/inherit_graph_9.md5 | 0 .../docs/doxygen/html/inherit_graph_9.png | Bin .../docs/doxygen/html/inherits.html | 0 .../docs/doxygen/html/ir__Airwell_8cpp.html | 0 .../docs/doxygen/html/ir__Airwell_8h.html | 0 .../doxygen/html/ir__Airwell_8h_source.html | 0 .../docs/doxygen/html/ir__Aiwa_8cpp.html | 0 .../docs/doxygen/html/ir__Amcor_8cpp.html | 0 .../docs/doxygen/html/ir__Amcor_8h.html | 0 .../doxygen/html/ir__Amcor_8h_source.html | 0 .../docs/doxygen/html/ir__Argo_8cpp.html | 0 .../docs/doxygen/html/ir__Argo_8h.html | 0 .../docs/doxygen/html/ir__Argo_8h_source.html | 0 .../docs/doxygen/html/ir__Carrier_8cpp.html | 0 .../docs/doxygen/html/ir__Carrier_8h.html | 0 .../doxygen/html/ir__Carrier_8h_source.html | 0 .../docs/doxygen/html/ir__Coolix_8cpp.html | 0 .../docs/doxygen/html/ir__Coolix_8h.html | 0 .../doxygen/html/ir__Coolix_8h_source.html | 0 .../docs/doxygen/html/ir__Corona_8cpp.html | 0 .../docs/doxygen/html/ir__Corona_8h.html | 0 .../doxygen/html/ir__Corona_8h_source.html | 0 .../docs/doxygen/html/ir__Daikin_8cpp.html | 0 .../docs/doxygen/html/ir__Daikin_8h.html | 0 .../doxygen/html/ir__Daikin_8h_source.html | 0 .../docs/doxygen/html/ir__Delonghi_8cpp.html | 0 .../docs/doxygen/html/ir__Delonghi_8h.html | 0 .../doxygen/html/ir__Delonghi_8h_source.html | 0 .../docs/doxygen/html/ir__Denon_8cpp.html | 0 .../docs/doxygen/html/ir__Dish_8cpp.html | 0 .../docs/doxygen/html/ir__Doshisha_8cpp.html | 0 .../docs/doxygen/html/ir__Electra_8cpp.html | 0 .../docs/doxygen/html/ir__Electra_8h.html | 0 .../doxygen/html/ir__Electra_8h_source.html | 0 .../docs/doxygen/html/ir__Epson_8cpp.html | 0 .../docs/doxygen/html/ir__Fujitsu_8cpp.html | 0 .../docs/doxygen/html/ir__Fujitsu_8h.html | 0 .../doxygen/html/ir__Fujitsu_8h_source.html | 0 .../docs/doxygen/html/ir__GICable_8cpp.html | 0 .../doxygen/html/ir__GlobalCache_8cpp.html | 0 .../doxygen/html/ir__Goodweather_8cpp.html | 0 .../docs/doxygen/html/ir__Goodweather_8h.html | 0 .../html/ir__Goodweather_8h_source.html | 0 .../docs/doxygen/html/ir__Gree_8cpp.html | 0 .../docs/doxygen/html/ir__Gree_8h.html | 0 .../docs/doxygen/html/ir__Gree_8h_source.html | 0 .../docs/doxygen/html/ir__Haier_8cpp.html | 0 .../docs/doxygen/html/ir__Haier_8h.html | 0 .../doxygen/html/ir__Haier_8h_source.html | 0 .../docs/doxygen/html/ir__Hitachi_8cpp.html | 0 .../docs/doxygen/html/ir__Hitachi_8h.html | 0 .../doxygen/html/ir__Hitachi_8h_source.html | 0 .../docs/doxygen/html/ir__Inax_8cpp.html | 0 .../docs/doxygen/html/ir__JVC_8cpp.html | 0 .../doxygen/html/ir__Kelvinator_8cpp.html | 0 .../docs/doxygen/html/ir__Kelvinator_8h.html | 0 .../html/ir__Kelvinator_8h_source.html | 0 .../docs/doxygen/html/ir__LG_8cpp.html | 0 .../docs/doxygen/html/ir__LG_8h.html | 0 .../docs/doxygen/html/ir__LG_8h_source.html | 0 .../docs/doxygen/html/ir__Lasertag_8cpp.html | 0 .../docs/doxygen/html/ir__Lego_8cpp.html | 0 .../docs/doxygen/html/ir__Lutron_8cpp.html | 0 .../docs/doxygen/html/ir__MWM_8cpp.html | 0 .../docs/doxygen/html/ir__Magiquest_8cpp.html | 0 .../docs/doxygen/html/ir__Magiquest_8h.html | 0 .../doxygen/html/ir__Magiquest_8h_source.html | 0 .../docs/doxygen/html/ir__Metz_8cpp.html | 0 .../docs/doxygen/html/ir__Midea_8cpp.html | 0 .../docs/doxygen/html/ir__Midea_8h.html | 0 .../doxygen/html/ir__Midea_8h_source.html | 0 .../html/ir__MitsubishiHeavy_8cpp.html | 0 .../doxygen/html/ir__MitsubishiHeavy_8h.html | 0 .../html/ir__MitsubishiHeavy_8h_source.html | 0 .../doxygen/html/ir__Mitsubishi_8cpp.html | 0 .../docs/doxygen/html/ir__Mitsubishi_8h.html | 0 .../html/ir__Mitsubishi_8h_source.html | 0 .../doxygen/html/ir__Multibrackets_8cpp.html | 0 .../docs/doxygen/html/ir__NEC_8cpp.html | 0 .../docs/doxygen/html/ir__NEC_8h.html | 0 .../docs/doxygen/html/ir__NEC_8h_source.html | 0 .../docs/doxygen/html/ir__Neoclima_8cpp.html | 0 .../docs/doxygen/html/ir__Neoclima_8h.html | 0 .../doxygen/html/ir__Neoclima_8h_source.html | 0 .../docs/doxygen/html/ir__Nikai_8cpp.html | 0 .../docs/doxygen/html/ir__Panasonic_8cpp.html | 0 .../docs/doxygen/html/ir__Panasonic_8h.html | 0 .../doxygen/html/ir__Panasonic_8h_source.html | 0 .../docs/doxygen/html/ir__Pioneer_8cpp.html | 0 .../docs/doxygen/html/ir__Pronto_8cpp.html | 0 .../docs/doxygen/html/ir__RC5__RC6_8cpp.html | 0 .../docs/doxygen/html/ir__RCMM_8cpp.html | 0 .../docs/doxygen/html/ir__Samsung_8cpp.html | 0 .../docs/doxygen/html/ir__Samsung_8h.html | 0 .../doxygen/html/ir__Samsung_8h_source.html | 0 .../docs/doxygen/html/ir__Sanyo_8cpp.html | 0 .../docs/doxygen/html/ir__Sanyo_8h.html | 0 .../doxygen/html/ir__Sanyo_8h_source.html | 0 .../docs/doxygen/html/ir__Sharp_8cpp.html | 0 .../docs/doxygen/html/ir__Sharp_8h.html | 0 .../doxygen/html/ir__Sharp_8h_source.html | 0 .../docs/doxygen/html/ir__Sherwood_8cpp.html | 0 .../docs/doxygen/html/ir__Sony_8cpp.html | 0 .../docs/doxygen/html/ir__Symphony_8cpp.html | 0 .../docs/doxygen/html/ir__Tcl_8cpp.html | 0 .../docs/doxygen/html/ir__Tcl_8h.html | 0 .../docs/doxygen/html/ir__Tcl_8h_source.html | 0 .../docs/doxygen/html/ir__Technibel_8cpp.html | 0 .../docs/doxygen/html/ir__Technibel_8h.html | 0 .../doxygen/html/ir__Technibel_8h_source.html | 0 .../docs/doxygen/html/ir__Teco_8cpp.html | 0 .../docs/doxygen/html/ir__Teco_8h.html | 0 .../docs/doxygen/html/ir__Teco_8h_source.html | 0 .../docs/doxygen/html/ir__Toshiba_8cpp.html | 0 .../docs/doxygen/html/ir__Toshiba_8h.html | 0 .../doxygen/html/ir__Toshiba_8h_source.html | 0 .../docs/doxygen/html/ir__Transcold_8cpp.html | 0 .../docs/doxygen/html/ir__Transcold_8h.html | 0 .../doxygen/html/ir__Transcold_8h_source.html | 0 .../docs/doxygen/html/ir__Trotec_8cpp.html | 0 .../docs/doxygen/html/ir__Trotec_8h.html | 0 .../doxygen/html/ir__Trotec_8h_source.html | 0 .../docs/doxygen/html/ir__Vestel_8cpp.html | 0 .../docs/doxygen/html/ir__Vestel_8h.html | 0 .../doxygen/html/ir__Vestel_8h_source.html | 0 .../docs/doxygen/html/ir__Voltas_8cpp.html | 0 .../docs/doxygen/html/ir__Voltas_8h.html | 0 .../doxygen/html/ir__Voltas_8h_source.html | 0 .../docs/doxygen/html/ir__Whirlpool_8cpp.html | 0 .../docs/doxygen/html/ir__Whirlpool_8h.html | 0 .../doxygen/html/ir__Whirlpool_8h_source.html | 0 .../docs/doxygen/html/ir__Whynter_8cpp.html | 0 .../docs/doxygen/html/ir__Zepeal_8cpp.html | 0 .../docs/doxygen/html/it-IT_8h.html | 0 .../docs/doxygen/html/it-IT_8h_source.html | 0 .../docs/doxygen/html/jquery.js | 0 .../doxygen/html/md_src_locale_README.html | 0 .../docs/doxygen/html/menu.js | 0 .../docs/doxygen/html/menudata.js | 0 .../docs/doxygen/html/namespaceIRAcUtils.html | 0 .../docs/doxygen/html/namespaceirutils.html | 0 .../docs/doxygen/html/namespacemembers.html | 0 .../doxygen/html/namespacemembers_enum.html | 0 .../doxygen/html/namespacemembers_func.html | 0 .../docs/doxygen/html/namespaces.html | 0 .../docs/doxygen/html/namespacestdAc.html | 0 .../docs/doxygen/html/nav_f.png | Bin .../docs/doxygen/html/nav_g.png | Bin .../docs/doxygen/html/nav_h.png | Bin .../docs/doxygen/html/open.png | Bin .../docs/doxygen/html/pages.html | 0 .../docs/doxygen/html/search/all_0.html | 0 .../docs/doxygen/html/search/all_0.js | 0 .../docs/doxygen/html/search/all_1.html | 0 .../docs/doxygen/html/search/all_1.js | 0 .../docs/doxygen/html/search/all_10.html | 0 .../docs/doxygen/html/search/all_10.js | 0 .../docs/doxygen/html/search/all_11.html | 0 .../docs/doxygen/html/search/all_11.js | 0 .../docs/doxygen/html/search/all_12.html | 0 .../docs/doxygen/html/search/all_12.js | 0 .../docs/doxygen/html/search/all_13.html | 0 .../docs/doxygen/html/search/all_13.js | 0 .../docs/doxygen/html/search/all_14.html | 0 .../docs/doxygen/html/search/all_14.js | 0 .../docs/doxygen/html/search/all_15.html | 0 .../docs/doxygen/html/search/all_15.js | 0 .../docs/doxygen/html/search/all_16.html | 0 .../docs/doxygen/html/search/all_16.js | 0 .../docs/doxygen/html/search/all_17.html | 0 .../docs/doxygen/html/search/all_17.js | 0 .../docs/doxygen/html/search/all_18.html | 0 .../docs/doxygen/html/search/all_18.js | 0 .../docs/doxygen/html/search/all_19.html | 0 .../docs/doxygen/html/search/all_19.js | 0 .../docs/doxygen/html/search/all_1a.html | 0 .../docs/doxygen/html/search/all_1a.js | 0 .../docs/doxygen/html/search/all_1b.html | 0 .../docs/doxygen/html/search/all_1b.js | 0 .../docs/doxygen/html/search/all_2.html | 0 .../docs/doxygen/html/search/all_2.js | 0 .../docs/doxygen/html/search/all_3.html | 0 .../docs/doxygen/html/search/all_3.js | 0 .../docs/doxygen/html/search/all_4.html | 0 .../docs/doxygen/html/search/all_4.js | 0 .../docs/doxygen/html/search/all_5.html | 0 .../docs/doxygen/html/search/all_5.js | 0 .../docs/doxygen/html/search/all_6.html | 0 .../docs/doxygen/html/search/all_6.js | 0 .../docs/doxygen/html/search/all_7.html | 0 .../docs/doxygen/html/search/all_7.js | 0 .../docs/doxygen/html/search/all_8.html | 0 .../docs/doxygen/html/search/all_8.js | 0 .../docs/doxygen/html/search/all_9.html | 0 .../docs/doxygen/html/search/all_9.js | 0 .../docs/doxygen/html/search/all_a.html | 0 .../docs/doxygen/html/search/all_a.js | 0 .../docs/doxygen/html/search/all_b.html | 0 .../docs/doxygen/html/search/all_b.js | 0 .../docs/doxygen/html/search/all_c.html | 0 .../docs/doxygen/html/search/all_c.js | 0 .../docs/doxygen/html/search/all_d.html | 0 .../docs/doxygen/html/search/all_d.js | 0 .../docs/doxygen/html/search/all_e.html | 0 .../docs/doxygen/html/search/all_e.js | 0 .../docs/doxygen/html/search/all_f.html | 0 .../docs/doxygen/html/search/all_f.js | 0 .../docs/doxygen/html/search/classes_0.html | 0 .../docs/doxygen/html/search/classes_0.js | 0 .../docs/doxygen/html/search/classes_1.html | 0 .../docs/doxygen/html/search/classes_1.js | 0 .../docs/doxygen/html/search/classes_2.html | 0 .../docs/doxygen/html/search/classes_2.js | 0 .../docs/doxygen/html/search/classes_3.html | 0 .../docs/doxygen/html/search/classes_3.js | 0 .../docs/doxygen/html/search/classes_4.html | 0 .../docs/doxygen/html/search/classes_4.js | 0 .../docs/doxygen/html/search/classes_5.html | 0 .../docs/doxygen/html/search/classes_5.js | 0 .../docs/doxygen/html/search/classes_6.html | 0 .../docs/doxygen/html/search/classes_6.js | 0 .../docs/doxygen/html/search/classes_7.html | 0 .../docs/doxygen/html/search/classes_7.js | 0 .../docs/doxygen/html/search/classes_8.html | 0 .../docs/doxygen/html/search/classes_8.js | 0 .../docs/doxygen/html/search/classes_9.html | 0 .../docs/doxygen/html/search/classes_9.js | 0 .../docs/doxygen/html/search/close.png | Bin .../docs/doxygen/html/search/enums_0.html | 0 .../docs/doxygen/html/search/enums_0.js | 0 .../docs/doxygen/html/search/enums_1.html | 0 .../docs/doxygen/html/search/enums_1.js | 0 .../docs/doxygen/html/search/enums_2.html | 0 .../docs/doxygen/html/search/enums_2.js | 0 .../docs/doxygen/html/search/enums_3.html | 0 .../docs/doxygen/html/search/enums_3.js | 0 .../docs/doxygen/html/search/enums_4.html | 0 .../docs/doxygen/html/search/enums_4.js | 0 .../docs/doxygen/html/search/enums_5.html | 0 .../docs/doxygen/html/search/enums_5.js | 0 .../docs/doxygen/html/search/enums_6.html | 0 .../docs/doxygen/html/search/enums_6.js | 0 .../docs/doxygen/html/search/enums_7.html | 0 .../docs/doxygen/html/search/enums_7.js | 0 .../docs/doxygen/html/search/enums_8.html | 0 .../docs/doxygen/html/search/enums_8.js | 0 .../docs/doxygen/html/search/enums_9.html | 0 .../docs/doxygen/html/search/enums_9.js | 0 .../doxygen/html/search/enumvalues_0.html | 0 .../docs/doxygen/html/search/enumvalues_0.js | 0 .../doxygen/html/search/enumvalues_1.html | 0 .../docs/doxygen/html/search/enumvalues_1.js | 0 .../doxygen/html/search/enumvalues_10.html | 0 .../docs/doxygen/html/search/enumvalues_10.js | 0 .../doxygen/html/search/enumvalues_11.html | 0 .../docs/doxygen/html/search/enumvalues_11.js | 0 .../doxygen/html/search/enumvalues_12.html | 0 .../docs/doxygen/html/search/enumvalues_12.js | 0 .../doxygen/html/search/enumvalues_13.html | 0 .../docs/doxygen/html/search/enumvalues_13.js | 0 .../doxygen/html/search/enumvalues_14.html | 0 .../docs/doxygen/html/search/enumvalues_14.js | 0 .../doxygen/html/search/enumvalues_15.html | 0 .../docs/doxygen/html/search/enumvalues_15.js | 0 .../doxygen/html/search/enumvalues_2.html | 0 .../docs/doxygen/html/search/enumvalues_2.js | 0 .../doxygen/html/search/enumvalues_3.html | 0 .../docs/doxygen/html/search/enumvalues_3.js | 0 .../doxygen/html/search/enumvalues_4.html | 0 .../docs/doxygen/html/search/enumvalues_4.js | 0 .../doxygen/html/search/enumvalues_5.html | 0 .../docs/doxygen/html/search/enumvalues_5.js | 0 .../doxygen/html/search/enumvalues_6.html | 0 .../docs/doxygen/html/search/enumvalues_6.js | 0 .../doxygen/html/search/enumvalues_7.html | 0 .../docs/doxygen/html/search/enumvalues_7.js | 0 .../doxygen/html/search/enumvalues_8.html | 0 .../docs/doxygen/html/search/enumvalues_8.js | 0 .../doxygen/html/search/enumvalues_9.html | 0 .../docs/doxygen/html/search/enumvalues_9.js | 0 .../doxygen/html/search/enumvalues_a.html | 0 .../docs/doxygen/html/search/enumvalues_a.js | 0 .../doxygen/html/search/enumvalues_b.html | 0 .../docs/doxygen/html/search/enumvalues_b.js | 0 .../doxygen/html/search/enumvalues_c.html | 0 .../docs/doxygen/html/search/enumvalues_c.js | 0 .../doxygen/html/search/enumvalues_d.html | 0 .../docs/doxygen/html/search/enumvalues_d.js | 0 .../doxygen/html/search/enumvalues_e.html | 0 .../docs/doxygen/html/search/enumvalues_e.js | 0 .../doxygen/html/search/enumvalues_f.html | 0 .../docs/doxygen/html/search/enumvalues_f.js | 0 .../docs/doxygen/html/search/files_0.html | 0 .../docs/doxygen/html/search/files_0.js | 0 .../docs/doxygen/html/search/files_1.html | 0 .../docs/doxygen/html/search/files_1.js | 0 .../docs/doxygen/html/search/files_2.html | 0 .../docs/doxygen/html/search/files_2.js | 0 .../docs/doxygen/html/search/files_3.html | 0 .../docs/doxygen/html/search/files_3.js | 0 .../docs/doxygen/html/search/files_4.html | 0 .../docs/doxygen/html/search/files_4.js | 0 .../docs/doxygen/html/search/files_5.html | 0 .../docs/doxygen/html/search/files_5.js | 0 .../docs/doxygen/html/search/functions_0.html | 0 .../docs/doxygen/html/search/functions_0.js | 0 .../docs/doxygen/html/search/functions_1.html | 0 .../docs/doxygen/html/search/functions_1.js | 0 .../doxygen/html/search/functions_10.html | 0 .../docs/doxygen/html/search/functions_10.js | 0 .../doxygen/html/search/functions_11.html | 0 .../docs/doxygen/html/search/functions_11.js | 0 .../doxygen/html/search/functions_12.html | 0 .../docs/doxygen/html/search/functions_12.js | 0 .../doxygen/html/search/functions_13.html | 0 .../docs/doxygen/html/search/functions_13.js | 0 .../doxygen/html/search/functions_14.html | 0 .../docs/doxygen/html/search/functions_14.js | 0 .../doxygen/html/search/functions_15.html | 0 .../docs/doxygen/html/search/functions_15.js | 0 .../doxygen/html/search/functions_16.html | 0 .../docs/doxygen/html/search/functions_16.js | 0 .../doxygen/html/search/functions_17.html | 0 .../docs/doxygen/html/search/functions_17.js | 0 .../docs/doxygen/html/search/functions_2.html | 0 .../docs/doxygen/html/search/functions_2.js | 0 .../docs/doxygen/html/search/functions_3.html | 0 .../docs/doxygen/html/search/functions_3.js | 0 .../docs/doxygen/html/search/functions_4.html | 0 .../docs/doxygen/html/search/functions_4.js | 0 .../docs/doxygen/html/search/functions_5.html | 0 .../docs/doxygen/html/search/functions_5.js | 0 .../docs/doxygen/html/search/functions_6.html | 0 .../docs/doxygen/html/search/functions_6.js | 0 .../docs/doxygen/html/search/functions_7.html | 0 .../docs/doxygen/html/search/functions_7.js | 0 .../docs/doxygen/html/search/functions_8.html | 0 .../docs/doxygen/html/search/functions_8.js | 0 .../docs/doxygen/html/search/functions_9.html | 0 .../docs/doxygen/html/search/functions_9.js | 0 .../docs/doxygen/html/search/functions_a.html | 0 .../docs/doxygen/html/search/functions_a.js | 0 .../docs/doxygen/html/search/functions_b.html | 0 .../docs/doxygen/html/search/functions_b.js | 0 .../docs/doxygen/html/search/functions_c.html | 0 .../docs/doxygen/html/search/functions_c.js | 0 .../docs/doxygen/html/search/functions_d.html | 0 .../docs/doxygen/html/search/functions_d.js | 0 .../docs/doxygen/html/search/functions_e.html | 0 .../docs/doxygen/html/search/functions_e.js | 0 .../docs/doxygen/html/search/functions_f.html | 0 .../docs/doxygen/html/search/functions_f.js | 0 .../docs/doxygen/html/search/mag_sel.png | Bin .../doxygen/html/search/namespaces_0.html | 0 .../docs/doxygen/html/search/namespaces_0.js | 0 .../doxygen/html/search/namespaces_1.html | 0 .../docs/doxygen/html/search/namespaces_1.js | 0 .../docs/doxygen/html/search/nomatches.html | 0 .../docs/doxygen/html/search/pages_0.html | 0 .../docs/doxygen/html/search/pages_0.js | 0 .../docs/doxygen/html/search/pages_1.html | 0 .../docs/doxygen/html/search/pages_1.js | 0 .../docs/doxygen/html/search/pages_2.html | 0 .../docs/doxygen/html/search/pages_2.js | 0 .../docs/doxygen/html/search/related_0.html | 0 .../docs/doxygen/html/search/related_0.js | 0 .../docs/doxygen/html/search/search.css | 0 .../docs/doxygen/html/search/search.js | 0 .../docs/doxygen/html/search/search_l.png | Bin .../docs/doxygen/html/search/search_m.png | Bin .../docs/doxygen/html/search/search_r.png | Bin .../docs/doxygen/html/search/searchdata.js | 0 .../docs/doxygen/html/search/typedefs_0.html | 0 .../docs/doxygen/html/search/typedefs_0.js | 0 .../docs/doxygen/html/search/variables_0.html | 0 .../docs/doxygen/html/search/variables_0.js | 0 .../docs/doxygen/html/search/variables_1.html | 0 .../docs/doxygen/html/search/variables_1.js | 0 .../doxygen/html/search/variables_10.html | 0 .../docs/doxygen/html/search/variables_10.js | 0 .../doxygen/html/search/variables_11.html | 0 .../docs/doxygen/html/search/variables_11.js | 0 .../doxygen/html/search/variables_12.html | 0 .../docs/doxygen/html/search/variables_12.js | 0 .../doxygen/html/search/variables_13.html | 0 .../docs/doxygen/html/search/variables_13.js | 0 .../doxygen/html/search/variables_14.html | 0 .../docs/doxygen/html/search/variables_14.js | 0 .../doxygen/html/search/variables_15.html | 0 .../docs/doxygen/html/search/variables_15.js | 0 .../doxygen/html/search/variables_16.html | 0 .../docs/doxygen/html/search/variables_16.js | 0 .../doxygen/html/search/variables_17.html | 0 .../docs/doxygen/html/search/variables_17.js | 0 .../docs/doxygen/html/search/variables_2.html | 0 .../docs/doxygen/html/search/variables_2.js | 0 .../docs/doxygen/html/search/variables_3.html | 0 .../docs/doxygen/html/search/variables_3.js | 0 .../docs/doxygen/html/search/variables_4.html | 0 .../docs/doxygen/html/search/variables_4.js | 0 .../docs/doxygen/html/search/variables_5.html | 0 .../docs/doxygen/html/search/variables_5.js | 0 .../docs/doxygen/html/search/variables_6.html | 0 .../docs/doxygen/html/search/variables_6.js | 0 .../docs/doxygen/html/search/variables_7.html | 0 .../docs/doxygen/html/search/variables_7.js | 0 .../docs/doxygen/html/search/variables_8.html | 0 .../docs/doxygen/html/search/variables_8.js | 0 .../docs/doxygen/html/search/variables_9.html | 0 .../docs/doxygen/html/search/variables_9.js | 0 .../docs/doxygen/html/search/variables_a.html | 0 .../docs/doxygen/html/search/variables_a.js | 0 .../docs/doxygen/html/search/variables_b.html | 0 .../docs/doxygen/html/search/variables_b.js | 0 .../docs/doxygen/html/search/variables_c.html | 0 .../docs/doxygen/html/search/variables_c.js | 0 .../docs/doxygen/html/search/variables_d.html | 0 .../docs/doxygen/html/search/variables_d.js | 0 .../docs/doxygen/html/search/variables_e.html | 0 .../docs/doxygen/html/search/variables_e.js | 0 .../docs/doxygen/html/search/variables_f.html | 0 .../docs/doxygen/html/search/variables_f.js | 0 .../docs/doxygen/html/splitbar.png | Bin .../html/structCoronaSection-members.html | 0 .../doxygen/html/structCoronaSection.html | 0 .../html/structirparams__t-members.html | 0 .../docs/doxygen/html/structirparams__t.html | 0 .../html/structmatch__result__t-members.html | 0 .../doxygen/html/structmatch__result__t.html | 0 .../html/structstdAc_1_1state__t-members.html | 0 .../doxygen/html/structstdAc_1_1state__t.html | 0 .../docs/doxygen/html/sync_off.png | Bin .../docs/doxygen/html/sync_on.png | Bin .../docs/doxygen/html/tab_a.png | Bin .../docs/doxygen/html/tab_b.png | Bin .../docs/doxygen/html/tab_h.png | Bin .../docs/doxygen/html/tab_s.png | Bin .../docs/doxygen/html/tabs.css | 0 .../docs/doxygen/html/todo.html | 0 .../html/unionAirwellProtocol-members.html | 0 .../doxygen/html/unionAirwellProtocol.html | 0 .../html/unionAmcorProtocol-members.html | 0 .../docs/doxygen/html/unionAmcorProtocol.html | 0 .../html/unionArgoProtocol-members.html | 0 .../docs/doxygen/html/unionArgoProtocol.html | 0 .../html/unionCarrierProtocol-members.html | 0 .../doxygen/html/unionCarrierProtocol.html | 0 .../html/unionCoronaProtocol-members.html | 0 .../doxygen/html/unionCoronaProtocol.html | 0 .../html/unionCoronaProtocol__coll__graph.map | 0 .../html/unionCoronaProtocol__coll__graph.md5 | 0 .../html/unionCoronaProtocol__coll__graph.png | Bin .../html/unionDelonghiProtocol-members.html | 0 .../doxygen/html/unionDelonghiProtocol.html | 0 .../html/unionGreeProtocol-members.html | 0 .../docs/doxygen/html/unionGreeProtocol.html | 0 .../html/unionHaierProtocol-members.html | 0 .../docs/doxygen/html/unionHaierProtocol.html | 0 .../html/unionHaierYRW02Protocol-members.html | 0 .../doxygen/html/unionHaierYRW02Protocol.html | 0 .../html/unionMideaProtocol-members.html | 0 .../docs/doxygen/html/unionMideaProtocol.html | 0 .../html/unionVoltasProtocol-members.html | 0 .../doxygen/html/unionVoltasProtocol.html | 0 .../doxygen/html/unionmagiquest-members.html | 0 .../docs/doxygen/html/unionmagiquest.html | 0 .../docs/doxygen/html/zh-CN_8h.html | 0 .../docs/doxygen/html/zh-CN_8h_source.html | 0 .../docs/doxygen_index.md | 0 .../examples/BlynkIrRemote/BlynkIrRemote.ino | 0 .../examples/BlynkIrRemote/platformio.ini | 0 .../CommonAcControl/CommonAcControl.ino | 0 .../examples/CommonAcControl/platformio.ini | 0 .../ControlSamsungAC/ControlSamsungAC.ino | 0 .../examples/ControlSamsungAC/platformio.ini | 0 .../DumbIRRepeater/DumbIRRepeater.ino | 0 .../examples/DumbIRRepeater/platformio.ini | 0 .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.h | 0 .../examples/IRMQTTServer/IRMQTTServer.ino | 0 .../examples/IRMQTTServer/platformio.ini | 0 .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 0 .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRrecvDumpV3/BaseOTA.h | 0 .../examples/IRrecvDumpV3/IRrecvDumpV3.ino | 0 .../examples/IRrecvDumpV3/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 0 .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 0 .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 0 .../SmartIRRepeater/SmartIRRepeater.ino | 0 .../examples/SmartIRRepeater/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 0 .../examples/TurnOnGreeAC/TurnOnGreeAC.ino | 0 .../examples/TurnOnGreeAC/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 0 .../TurnOnMitsubishiHeavyAc.ino | 0 .../TurnOnMitsubishiHeavyAc/platformio.ini | 0 .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 0 .../examples/TurnOnPanasonicAC/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 0 .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 0 .../examples/Web-AC-control/README.md | 0 .../examples/Web-AC-control/Web-AC-control.h | 0 .../Web-AC-control/Web-AC-control.ino | 0 .../examples/Web-AC-control/data/favicon.ico | Bin .../Web-AC-control/data/level_1_off.svg | 0 .../Web-AC-control/data/level_1_on.svg | 0 .../Web-AC-control/data/level_2_off.svg | 0 .../Web-AC-control/data/level_2_on.svg | 0 .../Web-AC-control/data/level_3_off.svg | 0 .../Web-AC-control/data/level_3_on.svg | 0 .../Web-AC-control/data/level_4_off.svg | 0 .../Web-AC-control/data/level_4_on.svg | 0 .../examples/Web-AC-control/data/ui.html | 0 .../examples/Web-AC-control/data/ui.js | 0 .../examples/Web-AC-control/platformio.ini | 0 .../examples/Web-AC-control/printscreen.png | Bin .../IRremoteESP8266-2.7.11/keywords.txt | 0 .../IRremoteESP8266-2.7.11/library.json | 0 .../IRremoteESP8266-2.7.11/library.properties | 0 .../IRremoteESP8266-2.7.11/platformio.ini | 0 .../IRremoteESP8266-2.7.11/pylintrc | 0 .../IRremoteESP8266-2.7.11/src/CPPLINT.cfg | 0 .../IRremoteESP8266-2.7.11/src/IRac.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRac.h | 0 .../IRremoteESP8266-2.7.11/src/IRrecv.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRrecv.h | 0 .../src/IRremoteESP8266.h | 0 .../IRremoteESP8266-2.7.11/src/IRsend.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRsend.h | 0 .../IRremoteESP8266-2.7.11/src/IRtext.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRtext.h | 0 .../IRremoteESP8266-2.7.11/src/IRtimer.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRtimer.h | 0 .../IRremoteESP8266-2.7.11/src/IRutils.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRutils.h | 0 .../IRremoteESP8266-2.7.11/src/i18n.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Airwell.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Airwell.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Amcor.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Amcor.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Argo.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Argo.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Carrier.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Carrier.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Coolix.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Coolix.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Corona.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Corona.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Daikin.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Daikin.h | 0 .../src/ir_Delonghi.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Delonghi.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Denon.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Dish.cpp | 0 .../src/ir_Doshisha.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Electra.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Electra.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Epson.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Fujitsu.h | 0 .../IRremoteESP8266-2.7.11/src/ir_GICable.cpp | 0 .../src/ir_GlobalCache.cpp | 0 .../src/ir_Goodweather.cpp | 0 .../src/ir_Goodweather.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Gree.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Gree.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Haier.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Haier.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Hitachi.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Inax.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_JVC.cpp | 0 .../src/ir_Kelvinator.cpp | 0 .../src/ir_Kelvinator.h | 0 .../IRremoteESP8266-2.7.11/src/ir_LG.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Lego.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Lutron.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_MWM.cpp | 0 .../src/ir_Magiquest.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Magiquest.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Metz.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Midea.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Midea.h | 0 .../src/ir_Mitsubishi.cpp | 0 .../src/ir_Mitsubishi.h | 0 .../src/ir_MitsubishiHeavy.cpp | 0 .../src/ir_MitsubishiHeavy.h | 0 .../src/ir_Multibrackets.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_NEC.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_NEC.h | 0 .../src/ir_Neoclima.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Neoclima.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Nikai.cpp | 0 .../src/ir_Panasonic.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Panasonic.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Pronto.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_RCMM.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Samsung.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Samsung.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sanyo.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Sharp.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sharp.h | 0 .../src/ir_Sherwood.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sony.cpp | 0 .../src/ir_Symphony.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Tcl.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Tcl.h | 0 .../src/ir_Technibel.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Technibel.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Teco.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Teco.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Toshiba.h | 0 .../src/ir_Transcold.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Transcold.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Trotec.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Trotec.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Vestel.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Vestel.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Voltas.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Voltas.h | 0 .../src/ir_Whirlpool.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Whirlpool.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Whynter.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp | 0 .../src/locale/README.md | 0 .../IRremoteESP8266-2.7.11/src/locale/de-CH.h | 0 .../IRremoteESP8266-2.7.11/src/locale/de-DE.h | 0 .../src/locale/defaults.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-AU.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-IE.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-UK.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-US.h | 0 .../IRremoteESP8266-2.7.11/src/locale/es-ES.h | 0 .../IRremoteESP8266-2.7.11/src/locale/fr-FR.h | 0 .../IRremoteESP8266-2.7.11/src/locale/it-IT.h | 0 .../IRremoteESP8266-2.7.11/src/locale/zh-CN.h | 0 .../IRremoteESP8266-2.7.11/test/IRac_test.cpp | 0 .../test/IRrecv_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/IRsend_test.h | 0 .../test/IRutils_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/Makefile | 0 .../test/ir_Airwell_test.cpp | 0 .../test/ir_Aiwa_test.cpp | 0 .../test/ir_Amcor_test.cpp | 0 .../test/ir_Argo_test.cpp | 0 .../test/ir_Carrier_test.cpp | 0 .../test/ir_Coolix_test.cpp | 0 .../test/ir_Corona_test.cpp | 0 .../test/ir_Daikin_test.cpp | 0 .../test/ir_Delonghi_test.cpp | 0 .../test/ir_Denon_test.cpp | 0 .../test/ir_Dish_test.cpp | 0 .../test/ir_Doshisha_test.cpp | 0 .../test/ir_Electra_test.cpp | 0 .../test/ir_Epson_test.cpp | 0 .../test/ir_Fujitsu_test.cpp | 0 .../test/ir_GICable_test.cpp | 0 .../test/ir_GlobalCache_test.cpp | 0 .../test/ir_Goodweather_test.cpp | 0 .../test/ir_Gree_test.cpp | 0 .../test/ir_Haier_test.cpp | 0 .../test/ir_Hitachi_test.cpp | 0 .../test/ir_Inax_test.cpp | 0 .../test/ir_JVC_test.cpp | 0 .../test/ir_Kelvinator_test.cpp | 0 .../test/ir_LG_test.cpp | 0 .../test/ir_Lasertag_test.cpp | 0 .../test/ir_Lego_test.cpp | 0 .../test/ir_Lutron_test.cpp | 0 .../test/ir_MWM_test.cpp | 0 .../test/ir_Magiquest_test.cpp | 0 .../test/ir_Metz_test.cpp | 0 .../test/ir_Midea_test.cpp | 0 .../test/ir_MitsubishiHeavy_test.cpp | 0 .../test/ir_Mitsubishi_test.cpp | 0 .../test/ir_Multibrackets_test.cpp | 0 .../test/ir_NEC_test.cpp | 0 .../test/ir_Neoclima_test.cpp | 0 .../test/ir_Nikai_test.cpp | 0 .../test/ir_Panasonic_test.cpp | 0 .../test/ir_Pioneer_test.cpp | 0 .../test/ir_Pronto_test.cpp | 0 .../test/ir_RC5_RC6_test.cpp | 0 .../test/ir_RCMM_test.cpp | 0 .../test/ir_Samsung_test.cpp | 0 .../test/ir_Sanyo_test.cpp | 0 .../test/ir_Sharp_test.cpp | 0 .../test/ir_Sherwood_test.cpp | 0 .../test/ir_Sony_test.cpp | 0 .../test/ir_Symphony_test.cpp | 0 .../test/ir_Tcl_test.cpp | 0 .../test/ir_Technibel_test.cpp | 0 .../test/ir_Teco_test.cpp | 0 .../test/ir_Toshiba_test.cpp | 0 .../test/ir_Transcold_test.cpp | 0 .../test/ir_Trotec_test.cpp | 0 .../test/ir_Vestel_test.cpp | 0 .../test/ir_Voltas_test.cpp | 0 .../test/ir_Whirlpool_test.cpp | 0 .../test/ir_Whynter_test.cpp | 0 .../test/ir_Zepeal_test.cpp | 0 .../IRremoteESP8266-2.7.11/tools/Makefile | 0 .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 0 .../tools/auto_analyse_raw_data_test.py | 0 .../tools/gc_decode.cpp | 0 .../tools/generate_irtext_h.sh | 0 .../IRremoteESP8266-2.7.11/tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 .../tools/raw_to_pronto_code.py | 0 .../tools/raw_to_pronto_code_test.py | 0 .../tools/scrape_supported_devices.py | 0 .../NeoPixelBus-2.6.0/.gitattributes | 0 .../NeoPixelBus-2.6.0/.github/FUNDING.yml | 0 .../.github/ISSUE_TEMPLATE/all-others.md | 0 .../.github/ISSUE_TEMPLATE/bug_report.md | 0 .../.github/ISSUE_TEMPLATE/feature_request.md | 0 .../NeoPixelBus-2.6.0/.gitignore | 0 {lib => lib_basic}/NeoPixelBus-2.6.0/COPYING | 0 .../NeoPixelBus-2.6.0/ReadMe.md | 0 .../examples/DotStarTest/DotStarTest.ino | 0 .../NeoPixelBrightness/NeoPixelBrightness.ino | 0 .../examples/NeoPixelGamma/NeoPixelGamma.ino | 0 .../examples/NeoPixelTest/NeoPixelTest.ino | 0 .../NeoPixelAnimation/NeoPixelAnimation.ino | 0 .../NeoPixelCylon/NeoPixelCylon.ino | 0 .../NeoPixelFunFadeInOut.ino | 0 .../NeoPixelFunLoop/NeoPixelFunLoop.ino | 0 .../NeoPixelFunRandomChange.ino | 0 .../NeoPixelRotateLoop/NeoPixelRotateLoop.ino | 0 .../bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino | 0 .../bitmaps/NeoPixelBitmap/Strings.bmp | Bin .../bitmaps/NeoPixelBitmap/StringsW.bmp | Bin .../bitmaps/NeoPixelBufferCylon/Cylon.pdn | Bin .../bitmaps/NeoPixelBufferCylon/CylonGrb.h | 0 .../bitmaps/NeoPixelBufferCylon/CylonGrbw.h | 0 .../NeoPixelBufferCylon.ino | 0 .../NeoPixelBufferShader.ino | 0 .../NeoPixelDibTest/NeoPixelDibTest.ino | 0 .../NeoSegmentBus/NeoSegmentBus.ino | 0 .../NeoSegmentFade/NeoSegmentFade.ino | 0 .../NeoPixelMosaicDump/NeoPixelMosaicDump.ino | 0 .../NeoPixelMosaicTest/NeoPixelMosaicTest.ino | 0 .../NeoPixelRingTopologyTest.ino | 0 .../NeoPixelTilesDump/NeoPixelTilesDump.ino | 0 .../NeoPixelTilesTest/NeoPixelTilesTest.ino | 0 .../NeoPixelTopologyDump.ino | 0 .../NeoPixelTopologyTest.ino | 0 .../extras/curves/circular.png | Bin .../NeoPixelBus-2.6.0/extras/curves/cubic.png | Bin .../extras/curves/different.png | Bin .../extras/curves/exponential.png | Bin .../NeoPixelBus-2.6.0/extras/curves/gamma.png | Bin .../extras/curves/pronounced.png | Bin .../extras/curves/quadratic.png | Bin .../extras/curves/quintic.png | Bin .../extras/curves/sinusoidal.png | Bin .../NeoPixelBus-2.6.0/keywords.txt | 0 .../NeoPixelBus-2.6.0/library.json | 0 .../NeoPixelBus-2.6.0/library.properties | 0 .../NeoPixelBus-2.6.0/src/NeoPixelAnimator.h | 0 .../src/NeoPixelBrightnessBus.h | 0 .../NeoPixelBus-2.6.0/src/NeoPixelBus.h | 0 .../src/NeoPixelSegmentBus.h | 0 .../src/internal/DotStarColorFeatures.h | 0 .../src/internal/DotStarGenericMethod.h | 0 .../src/internal/Esp32_i2s.c | 0 .../src/internal/Esp32_i2s.h | 0 .../src/internal/HsbColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/HsbColor.h | 0 .../src/internal/HslColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/HslColor.h | 0 .../src/internal/HtmlColor.cpp | 0 .../src/internal/HtmlColor.h | 0 .../src/internal/HtmlColorNameStrings.cpp | 0 .../src/internal/HtmlColorNameStrings.h | 0 .../src/internal/HtmlColorNames.cpp | 0 .../src/internal/HtmlColorShortNames.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/Layouts.h | 0 .../src/internal/Lpd8806ColorFeatures.h | 0 .../src/internal/Lpd8806GenericMethod.h | 0 .../src/internal/NeoArmMethod.h | 0 .../src/internal/NeoAvrMethod.h | 0 .../src/internal/NeoBitmapFile.h | 0 .../src/internal/NeoBuffer.h | 0 .../src/internal/NeoBufferContext.h | 0 .../src/internal/NeoBufferMethods.h | 0 .../src/internal/NeoColorFeatures.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoDib.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoEase.h | 0 .../src/internal/NeoEsp32I2sMethod.h | 0 .../src/internal/NeoEsp32RmtMethod.cpp | 0 .../src/internal/NeoEsp32RmtMethod.h | 0 .../src/internal/NeoEsp8266DmaMethod.h | 0 .../src/internal/NeoEsp8266UartMethod.cpp | 0 .../src/internal/NeoEsp8266UartMethod.h | 0 .../src/internal/NeoEspBitBangMethod.h | 0 .../src/internal/NeoGamma.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/NeoGamma.h | 0 .../src/internal/NeoHueBlend.h | 0 .../src/internal/NeoMosaic.h | 0 .../src/internal/NeoNrf52xMethod.h | 0 .../src/internal/NeoPixelAnimator.cpp | 0 .../src/internal/NeoPixelAvr.c | 0 .../src/internal/NeoRingTopology.h | 0 .../src/internal/NeoSegmentFeatures.h | 0 .../src/internal/NeoSettings.h | 0 .../src/internal/NeoSpriteSheet.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoTiles.h | 0 .../src/internal/NeoTm1814ColorFeatures.h | 0 .../src/internal/NeoTopology.h | 0 .../src/internal/P9813ColorFeatures.h | 0 .../src/internal/P9813GenericMethod.h | 0 .../src/internal/RgbColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/RgbColor.h | 0 .../src/internal/RgbwColor.cpp | 0 .../src/internal/RgbwColor.h | 0 .../src/internal/SegmentDigit.cpp | 0 .../src/internal/SegmentDigit.h | 0 .../src/internal/TwoWireBitBangImple.h | 0 .../src/internal/TwoWireBitBangImpleAvr.h | 0 .../src/internal/TwoWireSpiImple.h | 0 .../src/internal/Ws2801GenericMethod.h | 0 .../OneWire.cpp | 0 .../OneWire.h | 0 .../README.md | 0 .../DS18x20_Temperature.pde | 0 .../examples/DS2408_Switch/DS2408_Switch.pde | 0 .../examples/DS250x_PROM/DS250x_PROM.pde | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 .../TasmotaModbus-1.2.0/README.md | 0 .../examples/modbustest/modbustest.ino | 0 .../TasmotaModbus-1.2.0/keywords.txt | 0 .../TasmotaModbus-1.2.0/library.json | 0 .../TasmotaModbus-1.2.0/library.properties | 0 .../TasmotaModbus-1.2.0/src/TasmotaModbus.cpp | 0 .../TasmotaModbus-1.2.0/src/TasmotaModbus.h | 0 .../UdpListener/library.properties | 0 .../UdpListener/src/UdpListener.h | 0 .../generator/generator.c | 0 .../generator/remapping.xlsx | Bin .../Unishox-1.0-shadinger/library.properties | 0 .../Unishox-1.0-shadinger/python/unishox.py | 0 .../Unishox-1.0-shadinger/src/unishox.cpp | 0 .../Unishox-1.0-shadinger/src/unishox.h | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_GFX.cpp | 0 .../Adafruit_GFX.h | 0 .../Adafruit_SPITFT.cpp | 0 .../Adafruit_SPITFT.h | 0 .../Adafruit_SPITFT_Macros.h | 0 .../Fonts/FreeMono12pt7b.h | 0 .../Fonts/FreeMono18pt7b.h | 0 .../Fonts/FreeMono24pt7b.h | 0 .../Fonts/FreeMono9pt7b.h | 0 .../Fonts/FreeMonoBold12pt7b.h | 0 .../Fonts/FreeMonoBold18pt7b.h | 0 .../Fonts/FreeMonoBold24pt7b.h | 0 .../Fonts/FreeMonoBold9pt7b.h | 0 .../Fonts/FreeMonoBoldOblique12pt7b.h | 0 .../Fonts/FreeMonoBoldOblique18pt7b.h | 0 .../Fonts/FreeMonoBoldOblique24pt7b.h | 0 .../Fonts/FreeMonoBoldOblique9pt7b.h | 0 .../Fonts/FreeMonoOblique12pt7b.h | 0 .../Fonts/FreeMonoOblique18pt7b.h | 0 .../Fonts/FreeMonoOblique24pt7b.h | 0 .../Fonts/FreeMonoOblique9pt7b.h | 0 .../Fonts/FreeSans12pt7b.h | 0 .../Fonts/FreeSans18pt7b.h | 0 .../Fonts/FreeSans24pt7b.h | 0 .../Fonts/FreeSans9pt7b.h | 0 .../Fonts/FreeSansBold12pt7b.h | 0 .../Fonts/FreeSansBold18pt7b.h | 0 .../Fonts/FreeSansBold24pt7b.h | 0 .../Fonts/FreeSansBold9pt7b.h | 0 .../Fonts/FreeSansBoldOblique12pt7b.h | 0 .../Fonts/FreeSansBoldOblique18pt7b.h | 0 .../Fonts/FreeSansBoldOblique24pt7b.h | 0 .../Fonts/FreeSansBoldOblique9pt7b.h | 0 .../Fonts/FreeSansOblique12pt7b.h | 0 .../Fonts/FreeSansOblique18pt7b.h | 0 .../Fonts/FreeSansOblique24pt7b.h | 0 .../Fonts/FreeSansOblique9pt7b.h | 0 .../Fonts/FreeSerif12pt7b.h | 0 .../Fonts/FreeSerif18pt7b.h | 0 .../Fonts/FreeSerif24pt7b.h | 0 .../Fonts/FreeSerif9pt7b.h | 0 .../Fonts/FreeSerifBold12pt7b.h | 0 .../Fonts/FreeSerifBold18pt7b.h | 0 .../Fonts/FreeSerifBold24pt7b.h | 0 .../Fonts/FreeSerifBold9pt7b.h | 0 .../Fonts/FreeSerifBoldItalic12pt7b.h | 0 .../Fonts/FreeSerifBoldItalic18pt7b.h | 0 .../Fonts/FreeSerifBoldItalic24pt7b.h | 0 .../Fonts/FreeSerifBoldItalic9pt7b.h | 0 .../Fonts/FreeSerifItalic12pt7b.h | 0 .../Fonts/FreeSerifItalic18pt7b.h | 0 .../Fonts/FreeSerifItalic24pt7b.h | 0 .../Fonts/FreeSerifItalic9pt7b.h | 0 .../Fonts/Org_01.h | 0 .../Fonts/Picopixel.h | 0 .../Fonts/Tiny3x3a2pt7b.h | 0 .../Fonts/TomThumb.h | 0 .../README.md | 0 .../examples/mock_ili9341/mock_ili9341.ino | 0 .../fontconvert/Makefile | 0 .../fontconvert/fontconvert.c | 0 .../fontconvert/fontconvert_win.md | 0 .../fontconvert/makefonts.sh | 0 .../gfxfont.h | 0 .../glcdfont.c | 0 .../library.properties | 0 .../license.txt | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_ILI9341.cpp | 0 .../Adafruit_ILI9341.h | 0 .../README.md | 0 .../breakouttouchpaint/.esp8266.test.skip | 0 .../breakouttouchpaint/breakouttouchpaint.ino | 0 .../fulltest_featherwing/.mega2560.test.skip | 0 .../fulltest_featherwing.ino | 0 .../examples/graphicstest/graphicstest.ino | 0 .../.mega2560.test.skip | 0 .../graphicstest_featherwing.ino | 0 .../examples/onoffbutton/onoffbutton.ino | 0 .../onoffbutton_breakout/.esp8266.test.skip | 0 .../onoffbutton_breakout.ino | 0 .../examples/pictureEmbed/dragon.h | 0 .../examples/pictureEmbed/pictureEmbed.ino | 0 .../examples/spitftbitmap/spitftbitmap.ino | 0 .../examples/touchpaint/touchpaint.ino | 0 .../.mega2560.test.skip | 0 .../touchpaint_featherwing.ino | 0 .../library.properties | 0 .../Adafruit_LEDBackpack.cpp | 0 .../Adafruit_LEDBackpack.h | 0 .../Adafruit_LED_Backpack-1.1.6/README.md | 0 .../Adafruit_LED_Backpack-1.1.6/README.txt | 0 .../examples/HT16K33/HT16K33.ino | 0 .../examples/bargraph24/bargraph24.ino | 0 .../examples/bicolor8x8/bicolor8x8.pde | 0 .../clock_sevenseg_ds1307.ino | 0 .../clock_sevenseg_gps/clock_sevenseg_gps.ino | 0 .../examples/matrix16x8/matrix16x8.ino | 0 .../examples/matrix8x8/matrix8x8.ino | 0 .../minimatrix16x8/minimatrix16x8.ino | 0 .../examples/quadalphanum/quadalphanum.ino | 0 .../quadalphanum_mini/quadalphanum_mini.ino | 0 .../examples/roboface/roboface.pde | 0 .../examples/sevenseg/sevenseg.ino | 0 .../examples/wavface/wavface.pde | 0 .../examples/wavface/wavs/beware_i.wav | Bin .../examples/wavface/wavs/ihunger.wav | Bin .../examples/wavface/wavs/run_cowd.wav | Bin .../library.properties | 0 .../Adafruit_LED_Backpack-1.1.6/license.txt | 0 .../Adafruit_SH1106.cpp | 0 .../Adafruit_SH1106.h | 0 .../Adafruit_SH1106-gemu-1.0/LICENSE.txt | 0 .../Adafruit_SH1106-gemu-1.0/README.md | 0 .../sh1106_128x64_i2c/sh1106_128x64_i2c.ino | 0 .../sh1106_128x64_spi/sh1106_128x64_spi.ino | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_SSD1306.cpp | 0 .../Adafruit_SSD1306.h | 0 .../Adafruit_SSD1306-1.3.0-gemu-1.1/README.md | 0 .../OLED_featherwing/OLED_featherwing.ino | 0 .../ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino | 0 .../ssd1306_128x32_spi/ssd1306_128x32_spi.ino | 0 .../ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino | 0 .../ssd1306_128x64_spi/ssd1306_128x64_spi.ino | 0 .../library.properties | 0 .../license.txt | 0 .../Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h | 0 .../Adafruit_SSD1351-gemu-1.0/README.md | 0 .../Adafruit_SSD1351-gemu-1.0/SSD1351.cpp | 0 .../Adafruit_SSD1351-gemu-1.0/SSD1351.h | 0 .../Adafruit_SSD1351-gemu-1.0/Tiger.c | 0 .../Adafruit_SSD1351-gemu-1.0/Tiger.rgb | Bin .../Adafruit_SSD1351-gemu-1.0/keywords.txt | 0 .../library.properties | 0 .../Adafruit_SSD1351-gemu-1.0/spi_register.h | 0 .../Arduino_ST7789.cpp | 0 .../Arduino_ST7789-gemu-1.0/Arduino_ST7789.h | 0 .../Arduino_ST7789-gemu-1.0/README.txt | 0 .../examples/graphicstest/graphicstest.ino | 2 +- .../Arduino_ST7789-gemu-1.0/keywords.txt | 0 .../library.properties | 0 .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp | 0 .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.h | 0 .../JaretBurkett_ILI9488-gemu-1.0/README.md | 0 .../examples/graphicstest/graphicstest.ino | 0 .../keywords.txt | 0 .../library.properties | 0 .../spi_register.h | 0 .../LiquidCrystal_I2C.cpp | 0 .../LiquidCrystal_I2C.h | 0 .../LiquidCrystal_I2C.o | Bin .../LiquidCrystal_I2C-1.1.3/README.md | 0 .../examples/CustomChars/CustomChars.pde | 0 .../examples/HelloWorld/HelloWorld.pde | 0 .../examples/SerialDisplay/SerialDisplay.pde | 0 .../LiquidCrystal_I2C-1.1.3/keywords.txt | 0 .../LiquidCrystal_I2C-1.1.3/library.json | 0 .../library.properties | 0 .../Xlatb_RA8876-gemu-1.0/RA8876.cpp | 0 .../Xlatb_RA8876-gemu-1.0/RA8876.h | 0 .../Xlatb_RA8876-gemu-1.0/README.md | 0 .../Xlatb_RA8876-gemu-1.0/keywords.txt | 0 .../Xlatb_RA8876-gemu-1.0/library.properties | 0 .../Xlatb_RA8876-gemu-1.0/spi_register.h | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Arduino/epd2in9-demo/epd2in9-demo.ino | 0 .../Arduino/libraries/readme.txt | 0 .../LICENSE | 0 .../Makefile | 0 .../README.md | 0 .../components/epaper-29-ws/component.mk | 0 .../components/epaper-29-ws/epaper-29-ws.c | 0 .../components/epaper-29-ws/epaper-29-ws.h | 0 .../components/epaper-29-ws/epaper_font.c | 0 .../components/epaper-29-ws/epaper_fonts.h | 0 .../components/epaper-29-ws/font16.c | 0 .../components/epaper-29-ws/font20.c | 0 .../components/epaper-29-ws/font8.c | 0 .../components/epaper-29-ws/imagedata.cpp | 0 .../components/epaper-29-ws/imagedata.h | 0 .../docs/Doxyfile | 0 .../docs/Makefile | 0 .../docs/README.md | 0 .../docs/conf.py | 0 .../docs/gen-dxd.py | 0 .../docs/index.rst | 0 .../docs/link-roles.py | 0 .../docs/repo_util.py | 0 .../docs/requirements.txt | 0 .../library.properties | 0 .../main/README.md | 0 .../main/component.mk | 0 .../main/esp-epaper-29-ws.c | 0 .../main/imagedata.c | 0 .../main/imagedata.h | 0 .../pictures/2.9inch_e-Paper_Datasheet.pdf | Bin .../pictures/e-paper-and-esp-sample-image.jpg | Bin .../pictures/e-paper-and-esp-sample-text.jpg | Bin .../pictures/espresif-logo.bmp | Bin .../pictures/image-conversion-setup.png | Bin .../src/epd2in9.cpp | 0 .../src/epd2in9.h | 0 .../src/epd4in2.cpp | 0 .../src/epd4in2.h | 0 .../src/epdif.cpp | 0 .../src/epdif.h | 0 .../src/epdpaint.cpp | 0 .../src/epdpaint.h | 0 .../src/font12.c | 0 .../src/font16.c | 0 .../src/font20.c | 0 .../src/font24.c | 0 .../src/font8.c | 0 .../src/fonts.h | 0 .../src/renderer.cpp | 0 .../src/renderer.h | 0 {lib => lib_div}/A4988_Stepper/README.adoc | 0 {lib => lib_div}/A4988_Stepper/keywords.txt | 0 .../A4988_Stepper/library.properties | 0 .../A4988_Stepper/src/A4988_Stepper.cpp | 0 .../A4988_Stepper/src/A4988_Stepper.h | 0 .../AT24C256/Eeprom24C128_256.cpp | 0 {lib => lib_div}/AT24C256/Eeprom24C128_256.h | 0 {lib => lib_div}/AT24C256/library.properties | 0 {lib => lib_div}/ArduinoNTPd/NTPPacket.cpp | 0 {lib => lib_div}/ArduinoNTPd/NTPPacket.h | 0 {lib => lib_div}/ArduinoNTPd/NTPServer.cpp | 0 {lib => lib_div}/ArduinoNTPd/NTPServer.h | 0 .../ArduinoNTPd/library.properties | 0 {lib => lib_div}/LibTeleinfo/README.md | 0 {lib => lib_div}/LibTeleinfo/library.json | 38 +- .../LibTeleinfo/library.properties | 16 +- .../LibTeleinfo/src/LibTeleinfo.cpp | 0 .../LibTeleinfo/src/LibTeleinfo.h | 370 +- {lib => lib_div}/NewPing-1.9.1/README.md | 0 .../NewPing15SensorsTimer.pde | 0 .../NewPing3Sensors/NewPing3Sensors.pde | 0 .../NewPingEventTimer/NewPingEventTimer.pde | 0 .../NewPingExample/NewPingExample.pde | 0 .../NewPingTimerMedian/NewPingTimerMedian.pde | 0 .../examples/TimerExample/TimerExample.pde | 0 {lib => lib_div}/NewPing-1.9.1/keywords.txt | 0 .../NewPing-1.9.1/library.properties | 0 .../NewPing-1.9.1/src/NewPing.cpp | 0 {lib => lib_div}/NewPing-1.9.1/src/NewPing.h | 0 {lib => lib_div}/OpenTherm-0.9.0/LICENSE | 0 {lib => lib_div}/OpenTherm-0.9.0/README.md | 0 {lib => lib_div}/OpenTherm-0.9.0/keywords.txt | 0 .../OpenTherm-0.9.0/library.properties | 0 .../OpenTherm-0.9.0/src/OpenTherm.cpp | 0 .../OpenTherm-0.9.0/src/OpenTherm.h | 0 {lib => lib_i2c}/Adafruit_BusIO/.travis.yml | 0 .../Adafruit_BusIO_Register.cpp | 0 .../Adafruit_BusIO/Adafruit_BusIO_Register.h | 0 .../Adafruit_BusIO/Adafruit_I2CDevice.cpp | 0 .../Adafruit_BusIO/Adafruit_I2CDevice.h | 0 .../Adafruit_BusIO/Adafruit_I2CRegister.h | 0 .../Adafruit_BusIO/Adafruit_SPIDevice.cpp | 0 .../Adafruit_BusIO/Adafruit_SPIDevice.h | 0 {lib => lib_i2c}/Adafruit_BusIO/LICENSE | 0 {lib => lib_i2c}/Adafruit_BusIO/README.md | 0 .../i2c_address_detect/i2c_address_detect.ino | 0 .../examples/i2c_readwrite/i2c_readwrite.ino | 0 .../examples/i2c_registers/i2c_registers.ino | 0 .../i2corspi_register/i2corspi_register.ino | 0 .../examples/spi_modetest/spi_modetest.ino | 0 .../examples/spi_readwrite/spi_readwrite.ino | 0 .../examples/spi_registers/spi_registers.ino | 0 .../Adafruit_BusIO/library.properties | 0 .../Adafruit_CCS811-1.0.0.14/.travis.yml | 0 .../Adafruit_CCS811.cpp | 0 .../Adafruit_CCS811.h | 0 .../Adafruit_CCS811-1.0.0.14/LICENSE | 0 .../Adafruit_CCS811-1.0.0.14/README.md | 0 .../CCS811_OLED_Demo/CCS811_OLED_Demo.ino | 0 .../examples/CCS811_test/CCS811_test.ino | 0 .../library.properties | 0 .../Adafruit_MAX31865.cpp | 0 .../Adafruit_MAX31865.h | 0 .../Adafruit_MAX31865-1.1.0-custom/README.md | 0 .../Adafruit_MAX31865-1.1.0-custom/README.txt | 0 .../examples/max31865/max31865.ino | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.github/workflows/githubci.yml | 0 .../Adafruit_MCP9808_Tasmota/.gitignore | 0 .../Adafruit_MCP9808.cpp | 0 .../Adafruit_MCP9808.h | 0 .../Adafruit_MCP9808_Tasmota/README.md | 0 .../Adafruit_MCP9808_Tasmota/assets/board.jpg | Bin .../code-of-conduct.md | 0 .../examples/mcp9808test/mcp9808test.ino | 0 .../library.properties | 0 .../Adafruit_MCP9808_Tasmota}/license.txt | 0 .../Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp | 0 .../Adafruit_SGP30-1.2.0/Adafruit_SGP30.h | 0 .../Adafruit_SGP30-1.2.0/README.md | 0 .../examples/sgp30test/sgp30test.ino | 0 .../Adafruit_SGP30-1.2.0/library.properties | 0 .../Adafruit_SGP30-1.2.0}/license.txt | 0 .../Adafruit_SGP30-1.2.0/travis.yml | 0 .../Adafruit_TSL2591.cpp | 0 .../Adafruit_TSL2591.h | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 {lib => lib_i2c}/Adafruit_VEML7700/.gitignore | 0 .../Adafruit_VEML7700/.travis.yml | 0 .../Adafruit_VEML7700/Adafruit_VEML7700.cpp | 0 .../Adafruit_VEML7700/Adafruit_VEML7700.h | 0 {lib => lib_i2c}/Adafruit_VEML7700/README.md | 0 .../examples/veml7700_test/veml7700_test.ino | 0 .../Adafruit_VEML7700/library.properties | 0 .../Adafruit_VEML7700/license.txt | 0 .../BME680_driver-bme680_v3.5.9/LICENSE | 0 .../BME680_driver-bme680_v3.5.9/README.md | 0 .../Self test/bme680_selftest.c | 0 .../Self test/bme680_selftest.h | 0 .../BME680_driver-bme680_v3.5.9/bme680.c | 0 .../BME680_driver-bme680_v3.5.9/bme680.h | 0 .../BME680_driver-bme680_v3.5.9/bme680_defs.h | 0 .../library.properties | 0 lib_i2c/FT5206_Library/.gitignore | 2 + {lib => lib_i2c}/FT5206_Library/LICENSE | 42 +- lib_i2c/FT5206_Library/README.md | 2 + {lib => lib_i2c}/FT5206_Library/keywords.txt | 58 +- .../FT5206_Library/library.properties | 18 +- .../FT5206_Library/src/FT5206.cpp | 216 +- {lib => lib_i2c}/FT5206_Library/src/FT5206.h | 246 +- .../FrogmoreScd30/FrogmoreScd30.cpp | 0 .../FrogmoreScd30/FrogmoreScd30.h | 0 .../FrogmoreScd30/library.properties | 0 {lib => lib_i2c}/HPMA115S0/LICENSE.md | 0 {lib => lib_i2c}/HPMA115S0/README.md | 0 .../HPMA115S0/example/example.ino | 0 {lib => lib_i2c}/HPMA115S0/library.properties | 0 {lib => lib_i2c}/HPMA115S0/src/hpma115S0.cpp | 0 {lib => lib_i2c}/HPMA115S0/src/hpma115S0.h | 0 {lib => lib_i2c}/I2Cdevlib-Core/.library.json | 0 {lib => lib_i2c}/I2Cdevlib-Core/I2Cdev.cpp | 0 {lib => lib_i2c}/I2Cdevlib-Core/I2Cdev.h | 0 {lib => lib_i2c}/I2Cdevlib-Core/keywords.txt | 0 {lib => lib_i2c}/I2Cdevlib-Core/library.json | 0 .../Examples/MPU6050_DMP6/MPU6050_DMP6.ino | 0 .../Processing/MPUTeapot/MPUTeapot.pde | 0 .../Examples/MPU6050_raw/MPU6050_raw.ino | 0 .../I2Cdevlib-MPU6050/MPU6050.cpp | 0 {lib => lib_i2c}/I2Cdevlib-MPU6050/MPU6050.h | 0 .../MPU6050_6Axis_MotionApps20.h | 0 .../MPU6050_9Axis_MotionApps41.h | 0 .../I2Cdevlib-MPU6050/helper_3dmath.h | 0 .../I2Cdevlib-MPU6050/library.properties | 0 .../Joba_Tsl2561-2.0.10/.gitignore | 0 .../Joba_Tsl2561-2.0.10/.hgignore | 0 .../Joba_Tsl2561-2.0.10/.travis.yml | 0 {lib => lib_i2c}/Joba_Tsl2561-2.0.10/COPYING | 0 .../Joba_Tsl2561-2.0.10/COPYING.LESSER | 0 {lib => lib_i2c}/Joba_Tsl2561-2.0.10/README | 0 .../examples/Autogain/Autogain.ino | 0 .../examples/Simple/Simple.ino | 0 .../examples/Testing/Testing.ino | 0 .../examples/Utility/Utility.ino | 0 .../examples/platformio.ini | 0 .../examples/platformio.sh | 0 .../Joba_Tsl2561-2.0.10/lib/readme.txt | 0 .../Joba_Tsl2561-2.0.10/library.json | 0 .../Joba_Tsl2561-2.0.10/library.properties | 0 .../Joba_Tsl2561-2.0.10/platformio.ini | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561.cpp | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561.h | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561Util.h | 0 {lib => lib_i2c}/LOLIN_HP303B/README.md | 0 .../i2c_background/i2c_background.ino | 0 .../examples/i2c_command/i2c_command.ino | 0 .../examples/i2c_interrupt/i2c_interrupt.ino | 0 .../LOLIN_HP303B/examples/library.properties | 0 {lib => lib_i2c}/LOLIN_HP303B/keywords.txt | 0 .../LOLIN_HP303B/library.properties | 0 .../LOLIN_HP303B/src/LOLIN_HP303B.cpp | 0 .../LOLIN_HP303B/src/LOLIN_HP303B.h | 0 .../LOLIN_HP303B/src/util/hp303b_consts.h | 0 {lib => lib_i2c}/LinkedList-1.2.3/LICENSE.txt | 0 .../LinkedList-1.2.3/LinkedList.h | 0 {lib => lib_i2c}/LinkedList-1.2.3/README.md | 0 .../examples/ClassList/ClassList.pde | 0 .../SimpleIntegerList/SimpleIntegerList.pde | 0 .../LinkedList-1.2.3/keywords.txt | 0 .../LinkedList-1.2.3/library.json | 0 .../LinkedList-1.2.3/library.properties | 0 .../Mutichannel_Gas_Sensor/License.txt | 0 .../Mutichannel_Gas_Sensor/README.md | 0 .../examples/GetVersion/GetVersion.ino | 0 .../examples/I2C_Address/I2C_Address.ino | 0 .../examples/RawData/RawData.ino | 0 .../ReadSensorValue_Grove.ino | 0 .../ReadSensorValue_Xadow.ino | 0 .../UpdateFrimware/UpdateFrimware.ino | 0 .../UpdateFrimware/bootloader_atmega168.h | 0 .../examples/UpdateFrimware/gpl.txt | 0 .../examples/calibration/calibration.ino | 0 .../factory_setting/factory_setting.ino | 0 .../examples/new_firmware/new_firmware.ino | 0 .../Mutichannel_Gas_Sensor/library.json | 0 .../Mutichannel_Gas_Sensor/library.properties | 0 .../src/MutichannelGasSensor.cpp | 0 .../src/MutichannelGasSensor.h | 0 .../mlx90640-library/MLX90640_API.cpp | 3280 ++++++++--------- .../mlx90640-library/MLX90640_API.h | 148 +- .../mlx90640-library/library.properties | 0 .../vl53l0x-arduino-1.02/.travis.yml | 0 .../vl53l0x-arduino-1.02/LICENSE.txt | 0 .../vl53l0x-arduino-1.02/README.md | 0 .../vl53l0x-arduino-1.02/VL53L0X.cpp | 0 .../vl53l0x-arduino-1.02/VL53L0X.h | 0 .../examples/Continuous/Continuous.ino | 0 .../examples/Single/Single.ino | 0 .../vl53l0x-arduino-1.02/keywords.txt | 0 .../vl53l0x-arduino-1.02/library.properties | 0 .../vl53l1x-arduino-1.01/LICENSE.txt | 0 .../vl53l1x-arduino-1.01/README.md | 0 .../vl53l1x-arduino-1.01/VL53L1X.cpp | 0 .../vl53l1x-arduino-1.01/VL53L1X.h | 0 .../examples/Continuous/Continuous.ino | 0 .../ContinuousWithDetails.ino | 0 .../vl53l1x-arduino-1.01/keywords.txt | 0 .../vl53l1x-arduino-1.01/library.properties | 0 {lib => lib_rf}/KeeloqLib/README.md | 0 {lib => lib_rf}/KeeloqLib/keywords.txt | 0 {lib => lib_rf}/KeeloqLib/library.properties | 0 {lib => lib_rf}/KeeloqLib/src/KeeloqLib.cpp | 0 {lib => lib_rf}/KeeloqLib/src/KeeloqLib.h | 0 .../tests/KeeloqLibTest/KeeloqLibTest.ino | 0 {lib => lib_rf}/RF24/.gitignore | 0 {lib => lib_rf}/RF24/CONTRIBUTING.md | 0 {lib => lib_rf}/RF24/Doxyfile | 0 {lib => lib_rf}/RF24/LICENSE | 0 {lib => lib_rf}/RF24/Makefile | 0 {lib => lib_rf}/RF24/README.md | 0 {lib => lib_rf}/RF24/RF24.cpp | 0 {lib => lib_rf}/RF24/RF24.h | 0 {lib => lib_rf}/RF24/RF24_config.h | 0 {lib => lib_rf}/RF24/configure | 0 {lib => lib_rf}/RF24/doxygen-custom.css | 0 .../GettingStarted/GettingStarted.ino | 0 .../GettingStarted_CallResponse.ino | 0 .../GettingStarted_HandlingData.ino | 0 .../GettingStarted_HandlingFailures.ino | 0 .../RF24/examples/Transfer/Transfer.ino | 0 .../TransferTimeouts/TransferTimeouts.ino | 0 .../RF24/examples/Usage/led_remote/Jamfile | 0 .../examples/Usage/led_remote/led_remote.pde | 0 .../RF24/examples/Usage/nordic_fob/Jamfile | 0 .../examples/Usage/nordic_fob/nordic_fob.pde | 0 .../examples/Usage/pingpair_maple/Jamfile | 0 .../examples/Usage/pingpair_maple/main.cpp | 0 .../Usage/pingpair_maple/pingpair_maple.pde | 0 {lib => lib_rf}/RF24/examples/Usage/readme.md | 0 .../examples/pingpair_ack/pingpair_ack.ino | 0 .../RF24/examples/pingpair_dyn/Jamfile | 0 .../examples/pingpair_dyn/pingpair_dyn.ino | 0 .../examples/pingpair_irq/pingpair_irq.ino | 0 .../pingpair_irq_simple.ino | 0 .../RF24/examples/pingpair_multi_dyn/Jamfile | 0 .../pingpair_multi_dyn/pingpair_multi_dyn.ino | 0 .../pingpair_sleepy/pingpair_sleepy.ino | 0 .../rf24_ATTiny/rf24ping85/rf24ping85.ino | 0 .../timingSearch3pin/timingSearch3pin.ino | 0 {lib => lib_rf}/RF24/examples/scanner/Jamfile | 0 .../RF24/examples/scanner/scanner.ino | 0 .../RF24/examples/starping/Jamfile | 0 .../RF24/examples/starping/starping.pde | 0 .../RF24/examples_linux/Makefile.examples | 0 .../RF24/examples_linux/extra/Makefile | 0 .../RF24/examples_linux/extra/rpi-hub.cpp | 0 .../RF24/examples_linux/extra/scanner.cpp | 0 .../RF24/examples_linux/gettingstarted.cpp | 0 .../gettingstarted_call_response.cpp | 0 .../RF24/examples_linux/interrupts/Makefile | 0 .../gettingstarted_call_response_int.cpp | 0 .../gettingstarted_call_response_int2.cpp | 0 .../interrupts/pingpair_dyn_int.cpp | 0 .../interrupts/transfer_interrupt.cpp | 0 .../RF24/examples_linux/pingpair_dyn.cpp | 0 .../RF24/examples_linux/pingpair_dyn.py | 0 {lib => lib_rf}/RF24/examples_linux/readme.md | 0 .../RF24/examples_linux/transfer.cpp | 0 {lib => lib_rf}/RF24/keywords.txt | 0 {lib => lib_rf}/RF24/library.json | 0 {lib => lib_rf}/RF24/library.properties | 0 {lib => lib_rf}/RF24/nRF24L01.h | 0 {lib => lib_rf}/RF24/printf.h | 0 .../RF24/pyRF24/crossunixccompiler.py | 0 {lib => lib_rf}/RF24/pyRF24/pyRF24.cpp | 0 .../RF24/pyRF24/pyRF24/crossunixccompiler.py | 0 {lib => lib_rf}/RF24/pyRF24/pyRF24/pyRF24.cpp | 0 {lib => lib_rf}/RF24/pyRF24/pyRF24/readme.md | 0 {lib => lib_rf}/RF24/pyRF24/pyRF24/setup.py | 0 .../RF24/pyRF24/pyRF24Mesh/example_master.py | 0 .../RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp | 0 .../RF24/pyRF24/pyRF24Mesh/setup.py | 0 .../pyRF24Network/examples/helloworld_rx.py | 0 .../pyRF24Network/examples/helloworld_tx.py | 0 .../pyRF24/pyRF24Network/pyRF24Network.cpp | 0 .../RF24/pyRF24/pyRF24Network/setup.py | 0 {lib => lib_rf}/RF24/pyRF24/readme.md | 0 {lib => lib_rf}/RF24/pyRF24/setup.py | 0 {lib => lib_rf}/RF24/tests/README | 0 {lib => lib_rf}/RF24/tests/native/Jamfile | 0 .../RF24/tests/native/pingpair_irq.pde | 0 {lib => lib_rf}/RF24/tests/native/printf.h | 0 .../RF24/tests/pingpair_blocking/Jamfile | 0 .../pingpair_blocking/pingpair_blocking.pde | 0 .../RF24/tests/pingpair_blocking/printf.h | 0 .../RF24/tests/pingpair_blocking/runtest.py | 0 .../RF24/tests/pingpair_blocking/runtests.sh | 0 .../RF24/tests/pingpair_blocking/test.ex | 0 .../RF24/tests/pingpair_test/Jamfile | 0 .../tests/pingpair_test/pingpair_test.pde | 0 .../RF24/tests/pingpair_test/printf.h | 0 .../RF24/tests/pingpair_test/runtest.py | 0 .../RF24/tests/pingpair_test/runtests.sh | 0 .../RF24/tests/pingpair_test/test.ex | 0 .../RF24/utility/ATTiny/RF24_arch_config.h | 0 {lib => lib_rf}/RF24/utility/ATTiny/spi.h | 0 .../RF24/utility/ATXMegaD3/README.md | 0 .../RF24/utility/ATXMegaD3/RF24_arch_config.h | 0 .../RF24/utility/ATXMegaD3/compatibility.c | 0 .../RF24/utility/ATXMegaD3/compatibility.h | 0 .../RF24/utility/ATXMegaD3/gpio.cpp | 0 {lib => lib_rf}/RF24/utility/ATXMegaD3/gpio.h | 0 .../RF24/utility/ATXMegaD3/gpio_helper.c | 0 .../RF24/utility/ATXMegaD3/gpio_helper.h | 0 .../RF24/utility/ATXMegaD3/includes.h | 0 .../RF24/utility/ATXMegaD3/spi.cpp | 0 {lib => lib_rf}/RF24/utility/ATXMegaD3/spi.h | 0 .../RF24/utility/Due/RF24_arch_config.h | 0 .../utility/LittleWire/RF24_arch_config.h | 0 .../RF24/utility/LittleWire/includes.h | 0 .../RF24/utility/MRAA/RF24_arch_config.h | 0 .../RF24/utility/MRAA/compatibility.c | 0 .../RF24/utility/MRAA/compatibility.h | 0 {lib => lib_rf}/RF24/utility/MRAA/gpio.cpp | 0 {lib => lib_rf}/RF24/utility/MRAA/gpio.h | 0 {lib => lib_rf}/RF24/utility/MRAA/includes.h | 0 {lib => lib_rf}/RF24/utility/MRAA/spi.cpp | 0 {lib => lib_rf}/RF24/utility/MRAA/spi.h | 0 .../RF24/utility/RPi/RF24_arch_config.h | 0 {lib => lib_rf}/RF24/utility/RPi/bcm2835.c | 0 {lib => lib_rf}/RF24/utility/RPi/bcm2835.h | 0 {lib => lib_rf}/RF24/utility/RPi/includes.h | 0 {lib => lib_rf}/RF24/utility/RPi/interrupt.c | 0 {lib => lib_rf}/RF24/utility/RPi/interrupt.h | 0 {lib => lib_rf}/RF24/utility/RPi/spi.cpp | 0 {lib => lib_rf}/RF24/utility/RPi/spi.h | 0 .../RF24/utility/SPIDEV/RF24_arch_config.h | 0 .../RF24/utility/SPIDEV/compatibility.c | 0 .../RF24/utility/SPIDEV/compatibility.h | 0 {lib => lib_rf}/RF24/utility/SPIDEV/gpio.cpp | 0 {lib => lib_rf}/RF24/utility/SPIDEV/gpio.h | 0 .../RF24/utility/SPIDEV/includes.h | 0 .../RF24/utility/SPIDEV/interrupt.c | 0 .../RF24/utility/SPIDEV/interrupt.h | 0 {lib => lib_rf}/RF24/utility/SPIDEV/spi.cpp | 0 {lib => lib_rf}/RF24/utility/SPIDEV/spi.h | 0 .../RF24/utility/Teensy/RF24_arch_config.h | 0 .../RF24/utility/Template/RF24_arch_config.h | 0 .../RF24/utility/Template/compatibility.h | 0 {lib => lib_rf}/RF24/utility/Template/gpio.h | 0 .../RF24/utility/Template/includes.h | 0 {lib => lib_rf}/RF24/utility/Template/spi.h | 0 .../RF24/utility/wiringPi/RF24_arch_config.h | 0 .../RF24/utility/wiringPi/includes.h | 0 {lib => lib_rf}/RF24/utility/wiringPi/spi.cpp | 0 {lib => lib_rf}/RF24/utility/wiringPi/spi.h | 0 {lib => lib_rf}/RF24/wikidoc.xslt | 0 {lib => lib_rf}/cc1101/README.md | 0 {lib => lib_rf}/cc1101/cc1101.cpp | 0 {lib => lib_rf}/cc1101/cc1101.h | 0 {lib => lib_rf}/cc1101/cc1101.h.txt | 0 {lib => lib_rf}/cc1101/ccpacket.h | 0 {lib => lib_rf}/cc1101/library.properties | 0 {lib => lib_rf}/rc-switch/.gitignore | 0 {lib => lib_rf}/rc-switch/README.md | 0 .../ReceiveDemo_Advanced.ino | 0 .../examples/ReceiveDemo_Advanced/output.ino | 0 .../ReceiveDemo_Simple/ReceiveDemo_Simple.ino | 0 .../rc-switch/examples/SendDemo/SendDemo.ino | 0 .../TypeA_WithDIPSwitches.ino | 0 .../TypeA_WithDIPSwitches_Lightweight.ino | 0 .../TypeB_WithRotaryOrSlidingSwitches.ino | 0 .../TypeC_Intertechno/TypeC_Intertechno.ino | 0 .../examples/TypeD_REV/TypeD_REV.ino | 0 .../examples/Webserver/Webserver.ino | 0 {lib => lib_rf}/rc-switch/keywords.txt | 0 {lib => lib_rf}/rc-switch/library.json | 0 {lib => lib_rf}/rc-switch/library.properties | 0 {lib => lib_rf}/rc-switch/platformio.ini | 0 {lib => lib_rf}/rc-switch/src/RCSwitch.cpp | 0 {lib => lib_rf}/rc-switch/src/RCSwitch.h | 0 {lib => lib_ssl}/base64-1.1.1/LICENSE | 0 {lib => lib_ssl}/base64-1.1.1/Makefile | 0 {lib => lib_ssl}/base64-1.1.1/README.md | 0 {lib => lib_ssl}/base64-1.1.1/catch.cpp | 0 {lib => lib_ssl}/base64-1.1.1/catch.hpp | 0 .../base64-1.1.1/library.properties | 0 {lib => lib_ssl}/base64-1.1.1/src/base64.hpp | 0 .../bearssl_esp8266-customized.txt | 0 .../bearssl-esp8266/conf/esp8266.mk | 0 .../bearssl-esp8266/library.properties | 0 .../bearssl-esp8266/src/aead/ccm.c | 0 .../bearssl-esp8266/src/aead/eax.c | 0 .../bearssl-esp8266/src/aead/gcm.c | 0 .../bearssl-esp8266/src/codec/ccopy.c | 0 .../bearssl-esp8266/src/codec/dec16be.c | 0 .../bearssl-esp8266/src/codec/dec16le.c | 0 .../bearssl-esp8266/src/codec/dec32be.c | 0 .../bearssl-esp8266/src/codec/dec32le.c | 0 .../bearssl-esp8266/src/codec/dec64be.c | 0 .../bearssl-esp8266/src/codec/dec64le.c | 0 .../bearssl-esp8266/src/codec/enc16be.c | 0 .../bearssl-esp8266/src/codec/enc16le.c | 0 .../bearssl-esp8266/src/codec/enc32be.c | 0 .../bearssl-esp8266/src/codec/enc32le.c | 0 .../bearssl-esp8266/src/codec/enc64be.c | 0 .../bearssl-esp8266/src/codec/enc64le.c | 0 .../bearssl-esp8266/src/codec/pemdec.c | 0 .../bearssl-esp8266/src/codec/pemenc.c | 0 .../bearssl-esp8266/src/ec/ec_all_m15.c | 0 .../bearssl-esp8266/src/ec/ec_c25519_i15.c | 0 .../bearssl-esp8266/src/ec/ec_curve25519.c | 0 .../bearssl-esp8266/src/ec/ec_default.c | 0 .../bearssl-esp8266/src/ec/ec_keygen.c | 0 .../bearssl-esp8266/src/ec/ec_p256_m15.c | 0 .../bearssl-esp8266/src/ec/ec_prime_i15.c | 0 .../bearssl-esp8266/src/ec/ec_pubkey.c | 0 .../bearssl-esp8266/src/ec/ec_secp256r1.c | 0 .../bearssl-esp8266/src/ec/ec_secp384r1.c | 0 .../bearssl-esp8266/src/ec/ec_secp521r1.c | 0 .../bearssl-esp8266/src/ec/ecdsa_atr.c | 0 .../src/ec/ecdsa_default_sign_asn1.c | 0 .../src/ec/ecdsa_default_sign_raw.c | 0 .../src/ec/ecdsa_default_vrfy_asn1.c | 0 .../src/ec/ecdsa_default_vrfy_raw.c | 0 .../bearssl-esp8266/src/ec/ecdsa_i15_bits.c | 0 .../src/ec/ecdsa_i15_sign_asn1.c | 0 .../src/ec/ecdsa_i15_sign_raw.c | 0 .../src/ec/ecdsa_i15_vrfy_asn1.c | 0 .../src/ec/ecdsa_i15_vrfy_raw.c | 0 .../bearssl-esp8266/src/ec/ecdsa_rta.c | 0 .../bearssl-esp8266/src/hash/dig_oid.c | 0 .../bearssl-esp8266/src/hash/dig_size.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul32.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul64.c | 0 .../bearssl-esp8266/src/hash/ghash_pclmul.c | 0 .../bearssl-esp8266/src/hash/md5.c | 0 .../bearssl-esp8266/src/hash/md5sha1.c | 0 .../bearssl-esp8266/src/hash/mgf1.c | 0 .../bearssl-esp8266/src/hash/multihash.c | 0 .../bearssl-esp8266/src/hash/sha1.c | 0 .../bearssl-esp8266/src/hash/sha2big.c | 0 .../bearssl-esp8266/src/hash/sha2small.c | 0 .../bearssl-esp8266/src/int/i15_add.c | 0 .../bearssl-esp8266/src/int/i15_bitlen.c | 0 .../bearssl-esp8266/src/int/i15_decmod.c | 0 .../bearssl-esp8266/src/int/i15_decode.c | 0 .../bearssl-esp8266/src/int/i15_decred.c | 0 .../bearssl-esp8266/src/int/i15_encode.c | 0 .../bearssl-esp8266/src/int/i15_fmont.c | 0 .../bearssl-esp8266/src/int/i15_iszero.c | 0 .../bearssl-esp8266/src/int/i15_moddiv.c | 0 .../bearssl-esp8266/src/int/i15_modpow.c | 0 .../bearssl-esp8266/src/int/i15_modpow2.c | 0 .../bearssl-esp8266/src/int/i15_montmul.c | 0 .../bearssl-esp8266/src/int/i15_mulacc.c | 0 .../bearssl-esp8266/src/int/i15_muladd.c | 0 .../bearssl-esp8266/src/int/i15_ninv15.c | 0 .../bearssl-esp8266/src/int/i15_reduce.c | 0 .../bearssl-esp8266/src/int/i15_rshift.c | 0 .../bearssl-esp8266/src/int/i15_sub.c | 0 .../bearssl-esp8266/src/int/i15_tmont.c | 0 .../bearssl-esp8266/src/kdf/hkdf.c | 0 .../bearssl-esp8266/src/kdf/shake.c | 0 .../bearssl-esp8266/src/mac/hmac.c | 0 .../bearssl-esp8266/src/mac/hmac_ct.c | 0 .../bearssl-esp8266/src/pgmspace_bearssl.h | 0 .../bearssl-esp8266/src/rand/aesctr_drbg.c | 0 .../bearssl-esp8266/src/rand/hmac_drbg.c | 0 .../bearssl-esp8266/src/rand/sysrng.c | 0 .../src/rsa/rsa_default_keygen.c | 0 .../src/rsa/rsa_default_modulus.c | 0 .../src/rsa/rsa_default_oaep_decrypt.c | 0 .../src/rsa/rsa_default_oaep_encrypt.c | 0 .../src/rsa/rsa_default_pkcs1_sign.c | 0 .../src/rsa/rsa_default_pkcs1_vrfy.c | 0 .../src/rsa/rsa_default_priv.c | 0 .../src/rsa/rsa_default_privexp.c | 0 .../src/rsa/rsa_default_pss_sign.c | 0 .../src/rsa/rsa_default_pss_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_default_pub.c | 0 .../src/rsa/rsa_default_pubexp.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_keygen.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_modulus.c | 0 .../src/rsa/rsa_i15_oaep_decrypt.c | 0 .../src/rsa/rsa_i15_oaep_encrypt.c | 0 .../src/rsa/rsa_i15_pkcs1_sign.c | 0 .../src/rsa/rsa_i15_pkcs1_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_priv.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_privexp.c | 0 .../src/rsa/rsa_i15_pss_sign.c | 0 .../src/rsa/rsa_i15_pss_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_pub.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_pubexp.c | 0 .../bearssl-esp8266/src/rsa/rsa_oaep_pad.c | 0 .../bearssl-esp8266/src/rsa/rsa_oaep_unpad.c | 0 .../src/rsa/rsa_pkcs1_sig_pad.c | 0 .../src/rsa/rsa_pkcs1_sig_unpad.c | 0 .../bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c | 0 .../src/rsa/rsa_pss_sig_unpad.c | 0 .../bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c | 0 .../bearssl-esp8266/src/settings.c | 0 .../bearssl-esp8266/src/ssl/prf.c | 0 .../bearssl-esp8266/src/ssl/prf_md5sha1.c | 0 .../bearssl-esp8266/src/ssl/prf_sha256.c | 0 .../bearssl-esp8266/src/ssl/prf_sha384.c | 0 .../src/ssl/ssl_ccert_single_ec.c | 0 .../src/ssl/ssl_ccert_single_rsa.c | 0 .../bearssl-esp8266/src/ssl/ssl_client.c | 0 .../src/ssl/ssl_client_default_rsapub.c | 0 .../bearssl-esp8266/src/ssl/ssl_client_full.c | 0 .../bearssl-esp8266/src/ssl/ssl_engine.c | 0 .../src/ssl/ssl_engine_default_aescbc.c | 0 .../src/ssl/ssl_engine_default_aesccm.c | 0 .../src/ssl/ssl_engine_default_aesgcm.c | 0 .../src/ssl/ssl_engine_default_chapol.c | 0 .../src/ssl/ssl_engine_default_descbc.c | 0 .../src/ssl/ssl_engine_default_ec.c | 0 .../src/ssl/ssl_engine_default_ecdsa.c | 0 .../src/ssl/ssl_engine_default_rsavrfy.c | 0 .../bearssl-esp8266/src/ssl/ssl_hashes.c | 0 .../bearssl-esp8266/src/ssl/ssl_hs_client.c | 0 .../bearssl-esp8266/src/ssl/ssl_hs_server.c | 0 .../bearssl-esp8266/src/ssl/ssl_io.c | 0 .../bearssl-esp8266/src/ssl/ssl_keyexport.c | 0 .../bearssl-esp8266/src/ssl/ssl_lru.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_cbc.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_ccm.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_chapol.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_gcm.c | 0 .../src/ssl/ssl_scert_single_ec.c | 0 .../src/ssl/ssl_scert_single_rsa.c | 0 .../src/symcipher/aes_big_cbcdec.c | 0 .../src/symcipher/aes_big_cbcenc.c | 0 .../src/symcipher/aes_big_ctr.c | 0 .../src/symcipher/aes_big_ctrcbc.c | 0 .../src/symcipher/aes_big_dec.c | 0 .../src/symcipher/aes_big_enc.c | 0 .../src/symcipher/aes_common.c | 0 .../bearssl-esp8266/src/symcipher/aes_ct.c | 0 .../bearssl-esp8266/src/symcipher/aes_ct64.c | 0 .../src/symcipher/aes_ct64_cbcdec.c | 0 .../src/symcipher/aes_ct64_cbcenc.c | 0 .../src/symcipher/aes_ct64_ctr.c | 0 .../src/symcipher/aes_ct64_ctrcbc.c | 0 .../src/symcipher/aes_ct64_dec.c | 0 .../src/symcipher/aes_ct64_enc.c | 0 .../src/symcipher/aes_ct_cbcdec.c | 0 .../src/symcipher/aes_ct_cbcenc.c | 0 .../src/symcipher/aes_ct_ctr.c | 0 .../src/symcipher/aes_ct_ctrcbc.c | 0 .../src/symcipher/aes_ct_dec.c | 0 .../src/symcipher/aes_ct_enc.c | 0 .../src/symcipher/aes_small_cbcdec.c | 0 .../src/symcipher/aes_small_cbcenc.c | 0 .../src/symcipher/aes_small_ctr.c | 0 .../src/symcipher/aes_small_ctrcbc.c | 0 .../src/symcipher/aes_small_dec.c | 0 .../src/symcipher/aes_small_enc.c | 0 .../src/symcipher/chacha20_ct.c | 0 .../src/symcipher/chacha20_sse2.c | 0 .../bearssl-esp8266/src/symcipher/des_ct.c | 0 .../src/symcipher/des_ct_cbcdec.c | 0 .../src/symcipher/des_ct_cbcenc.c | 0 .../src/symcipher/des_support.c | 0 .../bearssl-esp8266/src/symcipher/des_tab.c | 0 .../src/symcipher/des_tab_cbcdec.c | 0 .../src/symcipher/des_tab_cbcenc.c | 0 .../src/symcipher/poly1305_ctmul.c | 0 .../src/symcipher/poly1305_ctmul32.c | 0 .../src/symcipher/poly1305_ctmulq.c | 0 .../src/symcipher/poly1305_i15.c | 0 .../bearssl-esp8266/src/t_bearssl.h | 0 .../bearssl-esp8266/src/t_bearssl_aead.h | 0 .../bearssl-esp8266/src/t_bearssl_block.h | 0 .../bearssl-esp8266/src/t_bearssl_ec.h | 0 .../bearssl-esp8266/src/t_bearssl_hash.h | 0 .../bearssl-esp8266/src/t_bearssl_hmac.h | 0 .../bearssl-esp8266/src/t_bearssl_kdf.h | 0 .../bearssl-esp8266/src/t_bearssl_pem.h | 0 .../bearssl-esp8266/src/t_bearssl_prf.h | 0 .../bearssl-esp8266/src/t_bearssl_rand.h | 0 .../bearssl-esp8266/src/t_bearssl_rsa.h | 0 .../bearssl-esp8266/src/t_bearssl_ssl.h | 0 .../src/t_bearssl_tasmota_config.h | 0 .../bearssl-esp8266/src/t_bearssl_x509.h | 0 .../bearssl-esp8266/src/t_config.h | 0 .../bearssl-esp8266/src/t_inner.h | 0 .../bearssl-esp8266/src/x509/asn1enc.c | 0 .../src/x509/encode_ec_pk8der.c | 0 .../src/x509/encode_ec_rawder.c | 0 .../src/x509/encode_rsa_pk8der.c | 0 .../src/x509/encode_rsa_rawder.c | 0 .../bearssl-esp8266/src/x509/pkey_decoder.c | 0 .../bearssl-esp8266/src/x509/skey_decoder.c | 0 .../bearssl-esp8266/src/x509/x509_decoder.c | 0 .../bearssl-esp8266/src/x509/x509_knownkey.c | 0 .../bearssl-esp8266/src/x509/x509_minimal.c | 0 .../src/x509/x509_minimal_full.c | 0 platformio.ini | 11 +- platformio_tasmota32.ini | 14 +- platformio_tasmota_env.ini | 59 +- platformio_tasmota_env.ini.new | 144 + platformio_tasmota_env32.ini | 42 +- 2940 files changed, 2451 insertions(+), 2261 deletions(-) delete mode 100755 lib/FT5206_Library/.gitignore delete mode 100755 lib/FT5206_Library/README.md rename {lib => lib_audio}/ESP8266Audio/.github/workflows/pr-or-master-push.yml (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/LICENSE (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/README.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/MixerSample/MixerSample.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/MixerSample/viola.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/WebRadio/WebRadio.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/WebRadio/web.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/examples/WebRadio/web.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/keywords.txt (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/library.json (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/library.properties (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSource.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceBuffer.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceBuffer.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceFATFS.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceFS.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceFS.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceHTTPStream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceICYStream.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceICYStream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceID3.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceID3.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceLittleFS.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourcePROGMEM.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSD.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSD.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSPIFFS.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSTDIO.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileSourceSTDIO.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileStream.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioFileStream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGenerator.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorAAC.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorAAC.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorFLAC.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorFLAC.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMIDI.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMIDI.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMOD.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMOD.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMP3.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMP3.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMP3a.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorMP3a.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorOpus.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorOpus.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorRTTTL.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorRTTTL.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorTalkie.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorTalkie.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorWAV.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioGeneratorWAV.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioLogger.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioLogger.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutput.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputBuffer.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputBuffer.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputFilterDecimate.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputFilterDecimate.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputI2S.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputI2S.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputI2SNoDAC.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputMixer.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputMixer.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputNull.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSPDIF.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSPDIF.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSPIFFSWAV.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSTDIO.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSTDIO.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSerialWAV.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioOutputSerialWAV.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/AudioStatus.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/driver/SinglePinI2SDriver.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/AUTHORS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/COPYING.FDL (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/COPYING.GPL (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/COPYING.LGPL (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/COPYING.Xiph (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/assert.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/callback.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/export.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/format.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/metadata.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/ordinals.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/FLAC/stream_decoder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/README (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/README.ESP8266 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/bitmath.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/bitreader.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/config.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/cpu.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/crc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/fixed.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/float.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/format.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/lpc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/md5.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/memory.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/bitmath.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/bitreader.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/cpu.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/crc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/fixed.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/float.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/format.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/lpc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/macros.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/md5.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/memory.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/metadata.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/private/window.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/protected/all.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/protected/stream_decoder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/protected/stream_encoder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/alloc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/compat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/endswap.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/getopt.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/macros.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/private.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/safe_str.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/share/utf8.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/stream_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libflac/window.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/aaccommon.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/aacdec.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/aacdec.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/aactabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/assembly.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/bitstream.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/bitstream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/buffers.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/coder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/dct4.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/decelmnt.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/dequant.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/fft.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/filefmt.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/huffman.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/hufftabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/imdct.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/noiseless.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/pns.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/readme.txt (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbr.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbr.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrfft.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrfreq.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhfadj.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhfgen.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhuff.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrimdct.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrmath.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrqmf.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrside.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/sbrtabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/statname.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/stproc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/tns.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-aac/trigtabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/LICENSE.txt (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/RCSL.txt (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/RPSL.txt (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/assembly.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/bitstream.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/buffers.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/coder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/dct32.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/dequant.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/dqchan.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/huffman.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/hufftabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/imdct.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3common.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3dec.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3dec.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3tabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/player.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/polyphase.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/scalfact.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/statname.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/stproc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/subband.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libhelix-mp3/trigtabs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/CHANGES (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/COPYING (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/COPYRIGHT (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/CREDITS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/D.dat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/LICENSE (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/README (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/README.ESP8266 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/TODO (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/VERSION (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/bit.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/bit.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/config.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/decoder.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/fixed.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/fixed.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/frame.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/frame.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/global.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/huffman.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/huffman.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/imdct_s.dat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/layer3.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/layer3.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/mad.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/mad.h.sed (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/qc_table.dat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/rq_table.dat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/sf_table.dat.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/stream.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/stream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/synth.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/synth.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/timer.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/timer.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/version.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libmad/version.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/AUTHORS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/CHANGES (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/COPYING (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/README.esp8266.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/README.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/bitwise.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/config.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/crctable.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/framing.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/ogg.pc (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/ogg/config_types.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/ogg/ogg.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libogg/ogg/os_types.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/AUTHORS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/COPYING (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/ChangeLog (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/INSTALL (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/NEWS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/README (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/analysis.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/arch.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/bands.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/bands.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt_encoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt_lpc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/celt_lpc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/cpu_support.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/cwrs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/cwrs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/ecintrin.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entcode.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entcode.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entdec.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entdec.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entenc.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/entenc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/fixed_debug.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/fixed_generic.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/float_cast.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/kiss_fft.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/kiss_fft.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/laplace.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/laplace.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/mathops.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/mathops.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/mdct.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/mdct.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/mfrngcod.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/modes.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/modes.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/os_support.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/pitch.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/pitch.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/quant_bands.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/quant_bands.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/rate.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/rate.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/stack_alloc.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/static_modes_fixed.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/static_modes_float.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/vq.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/celt/vq.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/config.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/mapping_matrix.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/mapping_matrix.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/mlp.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus.pc (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_custom.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_defines.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_encoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_multistream.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_multistream.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_multistream_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_multistream_encoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_private.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_projection.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_projection_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_projection_encoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/opus_types.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/repacketizer.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/A2NLSF.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/API.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/CNG.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/Inlines.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/LPC_fit.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/MacroCount.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/MacroDebug.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF2A.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_VQ.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_decode.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_encode.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_unpack.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NSQ.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NSQ.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/PLC.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/PLC.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/SigProc_FIX.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/VAD.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/biquad_alt.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/bwexpander.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/bwexpander_32.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/check_control_input.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/code_signs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/control.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/control_SNR.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/control_codec.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/debug.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/debug.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/dec_API.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_core.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_frame.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_indices.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_parameters.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_pitch.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decode_pulses.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/decoder_set_fs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/define.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/enc_API.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/encode_indices.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/encode_pulses.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/errors.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/gain_quant.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/init_decoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/init_encoder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/interpolate.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/lin2log.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/log2lin.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/macros.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/main.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/pitch_est_defines.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/pitch_est_tables.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/process_NLSFs.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_down2.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_down2_3.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_rom.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_rom.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/resampler_structs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/shell_coder.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/sigm_Q15.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/sort.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/structs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/table_LSF_cos.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_LTP.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_gain.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_other.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/tuning_parameters.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/silk/typedef.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libopus/tansig_table.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libtinysoundfont/LICENSE (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libtinysoundfont/README.ESP8266 (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libtinysoundfont/README.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/libtinysoundfont/tsf.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/AUTHORS (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/COPYING (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/README.esp8266.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/README.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/config.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/info.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/internal.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/internal.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/opusfile.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/opusfile.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/opusfile.pc (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/opusfile/stream.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/src/spiram-fast.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/common.sh (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/Arduino.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/Makefile (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/Serial.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/aac.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/midi.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/mp3.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/opus.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/pgmspace.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/test_8u_16.wav (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266Audio/tests/host/wav.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/README.md (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/examples/Speak/Speak.ino (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/library.json (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/library.properties (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/ESP8266SAM.cpp (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/ESP8266SAM.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/ReciterTabs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/RenderTabs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/SamData.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/SamTabs.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/reciter.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/reciter.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/render.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/render.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/sam.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/sam.h (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/samdebug.c (100%) mode change 100755 => 100644 rename {lib => lib_audio}/ESP8266SAM/src/samdebug.h (100%) mode change 100755 => 100644 rename {lib => lib_basic}/C2Programmer-1.0.0/README.md (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/keywords.txt (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/library.json (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/library.properties (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/src/c2.cpp (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/src/c2.h (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/src/ihx.cpp (100%) rename {lib => lib_basic}/C2Programmer-1.0.0/src/ihx.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.github/Contributors.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.github/issue_template.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.gitignore (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.gitmodules (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.style.yapf (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/.travis.yml (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/CPPLINT.cfg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/Doxyfile (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/LICENSE.txt (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/README.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/README_fr.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/ReleaseNotes.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/SupportedProtocols.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/README.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/README_fr.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/_config.yml (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen_index.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/keywords.txt (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/library.json (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/library.properties (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/platformio.ini (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/pylintrc (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/CPPLINT.cfg (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRac.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRac.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRrecv.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRrecv.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRsend.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRsend.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRtext.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRtext.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRtimer.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRtimer.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRutils.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/IRutils.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/i18n.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Airwell.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Amcor.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Argo.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Argo.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Carrier.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Coolix.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Corona.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Corona.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Daikin.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Delonghi.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Denon.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Dish.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Electra.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Electra.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Epson.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_GICable.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Goodweather.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Gree.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Gree.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Haier.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Haier.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Hitachi.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Inax.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_JVC.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_LG.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_LG.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lego.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_MWM.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Magiquest.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Metz.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Midea.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Midea.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_NEC.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_NEC.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Neoclima.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Panasonic.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Samsung.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sanyo.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sharp.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sony.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Tcl.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Technibel.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Teco.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Teco.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Toshiba.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Transcold.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Trotec.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Vestel.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Voltas.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/README.md (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/de-CH.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/de-DE.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/defaults.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-AU.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-IE.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-UK.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-US.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/es-ES.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/fr-FR.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/it-IT.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/src/locale/zh-CN.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRac_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRrecv_test.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRsend_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRsend_test.h (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/IRutils_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/Makefile (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/Makefile (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/gc_decode.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/mkkeywords (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py (100%) rename {lib => lib_basic}/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.gitattributes (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.github/FUNDING.yml (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/.gitignore (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/COPYING (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/ReadMe.md (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/circular.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/cubic.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/different.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/exponential.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/gamma.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/pronounced.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/quadratic.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/quintic.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/keywords.txt (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/library.json (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/library.properties (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelBus.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HsbColor.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HslColor.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HslColor.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColor.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Layouts.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoDib.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEase.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoGamma.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSettings.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTiles.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTopology.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbColor.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbwColor.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h (100%) rename {lib => lib_basic}/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/OneWire.h (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/README.md (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/keywords.txt (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/library.json (100%) rename {lib => lib_basic}/OneWire-Stickbreaker-20190506-1.1/library.properties (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/README.md (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/keywords.txt (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/library.json (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/library.properties (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp (100%) rename {lib => lib_basic}/TasmotaModbus-1.2.0/src/TasmotaModbus.h (100%) rename {lib => lib_basic}/UdpListener/library.properties (100%) rename {lib => lib_basic}/UdpListener/src/UdpListener.h (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/generator/generator.c (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/generator/remapping.xlsx (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/library.properties (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/python/unishox.py (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/src/unishox.cpp (100%) rename {lib => lib_basic}/Unishox-1.0-shadinger/src/unishox.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties (100%) rename {lib => lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino (100%) rename {lib => lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/README.md (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/README.txt (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/library.properties (100%) rename {lib => lib_display}/Adafruit_LED_Backpack-1.1.6/license.txt (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/LICENSE.txt (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/README.md (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino (100%) rename {lib => lib_display}/Adafruit_SH1106-gemu-1.0/library.properties (100%) rename {lib/Adafruit_MCP9808_Tasmota => lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1}/.github/ISSUE_TEMPLATE.md (100%) rename {lib/Adafruit_MCP9808_Tasmota => lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1}/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties (100%) rename {lib/Adafruit_MCP9808_Tasmota => lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1}/license.txt (100%) rename {lib => lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/README.md (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/SSD1351.h (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/Tiger.c (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/Tiger.rgb (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/keywords.txt (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/library.properties (100%) rename {lib => lib_display}/Adafruit_SSD1351-gemu-1.0/spi_register.h (100%) rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp (100%) mode change 100755 => 100644 rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h (100%) mode change 100755 => 100644 rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/README.txt (100%) mode change 100755 => 100644 rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino (99%) mode change 100755 => 100644 rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/keywords.txt (100%) rename {lib => lib_display}/Arduino_ST7789-gemu-1.0/library.properties (100%) mode change 100755 => 100644 rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/README.md (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/keywords.txt (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/library.properties (100%) rename {lib => lib_display}/JaretBurkett_ILI9488-gemu-1.0/spi_register.h (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/README.md (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/keywords.txt (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/library.json (100%) rename {lib => lib_display}/LiquidCrystal_I2C-1.1.3/library.properties (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/RA8876.cpp (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/RA8876.h (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/README.md (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/keywords.txt (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/library.properties (100%) rename {lib => lib_display}/Xlatb_RA8876-gemu-1.0/spi_register.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Makefile (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/README.md (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/library.properties (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp (100%) rename {lib => lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h (100%) rename {lib => lib_div}/A4988_Stepper/README.adoc (100%) rename {lib => lib_div}/A4988_Stepper/keywords.txt (100%) mode change 100755 => 100644 rename {lib => lib_div}/A4988_Stepper/library.properties (100%) rename {lib => lib_div}/A4988_Stepper/src/A4988_Stepper.cpp (100%) rename {lib => lib_div}/A4988_Stepper/src/A4988_Stepper.h (100%) rename {lib => lib_div}/AT24C256/Eeprom24C128_256.cpp (100%) rename {lib => lib_div}/AT24C256/Eeprom24C128_256.h (100%) rename {lib => lib_div}/AT24C256/library.properties (100%) rename {lib => lib_div}/ArduinoNTPd/NTPPacket.cpp (100%) rename {lib => lib_div}/ArduinoNTPd/NTPPacket.h (100%) rename {lib => lib_div}/ArduinoNTPd/NTPServer.cpp (100%) rename {lib => lib_div}/ArduinoNTPd/NTPServer.h (100%) rename {lib => lib_div}/ArduinoNTPd/library.properties (100%) rename {lib => lib_div}/LibTeleinfo/README.md (100%) mode change 100755 => 100644 rename {lib => lib_div}/LibTeleinfo/library.json (95%) mode change 100755 => 100644 rename {lib => lib_div}/LibTeleinfo/library.properties (95%) mode change 100755 => 100644 rename {lib => lib_div}/LibTeleinfo/src/LibTeleinfo.cpp (100%) rename {lib => lib_div}/LibTeleinfo/src/LibTeleinfo.h (97%) mode change 100755 => 100644 rename {lib => lib_div}/NewPing-1.9.1/README.md (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/examples/TimerExample/TimerExample.pde (100%) rename {lib => lib_div}/NewPing-1.9.1/keywords.txt (100%) rename {lib => lib_div}/NewPing-1.9.1/library.properties (100%) rename {lib => lib_div}/NewPing-1.9.1/src/NewPing.cpp (100%) rename {lib => lib_div}/NewPing-1.9.1/src/NewPing.h (100%) rename {lib => lib_div}/OpenTherm-0.9.0/LICENSE (100%) rename {lib => lib_div}/OpenTherm-0.9.0/README.md (100%) rename {lib => lib_div}/OpenTherm-0.9.0/keywords.txt (100%) rename {lib => lib_div}/OpenTherm-0.9.0/library.properties (100%) rename {lib => lib_div}/OpenTherm-0.9.0/src/OpenTherm.cpp (100%) rename {lib => lib_div}/OpenTherm-0.9.0/src/OpenTherm.h (100%) rename {lib => lib_i2c}/Adafruit_BusIO/.travis.yml (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_BusIO_Register.cpp (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_BusIO_Register.h (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_I2CDevice.cpp (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_I2CDevice.h (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_I2CRegister.h (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_SPIDevice.cpp (100%) rename {lib => lib_i2c}/Adafruit_BusIO/Adafruit_SPIDevice.h (100%) rename {lib => lib_i2c}/Adafruit_BusIO/LICENSE (100%) rename {lib => lib_i2c}/Adafruit_BusIO/README.md (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/examples/spi_registers/spi_registers.ino (100%) rename {lib => lib_i2c}/Adafruit_BusIO/library.properties (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/.travis.yml (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/LICENSE (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/README.md (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino (100%) rename {lib => lib_i2c}/Adafruit_CCS811-1.0.0.14/library.properties (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/README.md (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/README.txt (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino (100%) rename {lib => lib_i2c}/Adafruit_MAX31865-1.1.0-custom/library.properties (100%) rename {lib/Adafruit_SSD1306-1.3.0-gemu-1.1 => lib_i2c/Adafruit_MCP9808_Tasmota}/.github/ISSUE_TEMPLATE.md (100%) rename {lib/Adafruit_SSD1306-1.3.0-gemu-1.1 => lib_i2c/Adafruit_MCP9808_Tasmota}/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/.gitignore (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/README.md (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/assets/board.jpg (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/code-of-conduct.md (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino (100%) rename {lib => lib_i2c}/Adafruit_MCP9808_Tasmota/library.properties (100%) rename {lib/Adafruit_SGP30-1.2.0 => lib_i2c/Adafruit_MCP9808_Tasmota}/license.txt (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/README.md (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/library.properties (100%) rename {lib/Adafruit_SSD1306-1.3.0-gemu-1.1 => lib_i2c/Adafruit_SGP30-1.2.0}/license.txt (100%) rename {lib => lib_i2c}/Adafruit_SGP30-1.2.0/travis.yml (100%) rename {lib => lib_i2c}/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp (100%) rename {lib => lib_i2c}/Adafruit_TSL2591_Library/Adafruit_TSL2591.h (100%) rename {lib => lib_i2c}/Adafruit_TSL2591_Library/library.properties (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/.gitignore (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/.travis.yml (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/Adafruit_VEML7700.cpp (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/Adafruit_VEML7700.h (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/README.md (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/library.properties (100%) rename {lib => lib_i2c}/Adafruit_VEML7700/license.txt (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/LICENSE (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/README.md (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/bme680.c (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/bme680.h (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/bme680_defs.h (100%) rename {lib => lib_i2c}/BME680_driver-bme680_v3.5.9/library.properties (100%) create mode 100644 lib_i2c/FT5206_Library/.gitignore rename {lib => lib_i2c}/FT5206_Library/LICENSE (98%) mode change 100755 => 100644 create mode 100644 lib_i2c/FT5206_Library/README.md rename {lib => lib_i2c}/FT5206_Library/keywords.txt (96%) mode change 100755 => 100644 rename {lib => lib_i2c}/FT5206_Library/library.properties (90%) mode change 100755 => 100644 rename {lib => lib_i2c}/FT5206_Library/src/FT5206.cpp (96%) mode change 100755 => 100644 rename {lib => lib_i2c}/FT5206_Library/src/FT5206.h (96%) mode change 100755 => 100644 rename {lib => lib_i2c}/FrogmoreScd30/FrogmoreScd30.cpp (100%) rename {lib => lib_i2c}/FrogmoreScd30/FrogmoreScd30.h (100%) rename {lib => lib_i2c}/FrogmoreScd30/library.properties (100%) rename {lib => lib_i2c}/HPMA115S0/LICENSE.md (100%) rename {lib => lib_i2c}/HPMA115S0/README.md (100%) rename {lib => lib_i2c}/HPMA115S0/example/example.ino (100%) rename {lib => lib_i2c}/HPMA115S0/library.properties (100%) rename {lib => lib_i2c}/HPMA115S0/src/hpma115S0.cpp (100%) rename {lib => lib_i2c}/HPMA115S0/src/hpma115S0.h (100%) rename {lib => lib_i2c}/I2Cdevlib-Core/.library.json (100%) rename {lib => lib_i2c}/I2Cdevlib-Core/I2Cdev.cpp (100%) rename {lib => lib_i2c}/I2Cdevlib-Core/I2Cdev.h (100%) rename {lib => lib_i2c}/I2Cdevlib-Core/keywords.txt (100%) rename {lib => lib_i2c}/I2Cdevlib-Core/library.json (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/MPU6050.cpp (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/MPU6050.h (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/helper_3dmath.h (100%) rename {lib => lib_i2c}/I2Cdevlib-MPU6050/library.properties (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/.gitignore (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/.hgignore (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/.travis.yml (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/COPYING (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/COPYING.LESSER (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/README (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/platformio.ini (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/examples/platformio.sh (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/lib/readme.txt (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/library.json (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/library.properties (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/platformio.ini (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561.h (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp (100%) rename {lib => lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h (100%) rename {lib => lib_i2c}/LOLIN_HP303B/README.md (100%) rename {lib => lib_i2c}/LOLIN_HP303B/examples/i2c_background/i2c_background.ino (100%) rename {lib => lib_i2c}/LOLIN_HP303B/examples/i2c_command/i2c_command.ino (100%) rename {lib => lib_i2c}/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino (100%) rename {lib => lib_i2c}/LOLIN_HP303B/examples/library.properties (100%) rename {lib => lib_i2c}/LOLIN_HP303B/keywords.txt (100%) rename {lib => lib_i2c}/LOLIN_HP303B/library.properties (100%) rename {lib => lib_i2c}/LOLIN_HP303B/src/LOLIN_HP303B.cpp (100%) rename {lib => lib_i2c}/LOLIN_HP303B/src/LOLIN_HP303B.h (100%) rename {lib => lib_i2c}/LOLIN_HP303B/src/util/hp303b_consts.h (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/LICENSE.txt (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/LinkedList.h (100%) mode change 100755 => 100644 rename {lib => lib_i2c}/LinkedList-1.2.3/README.md (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/examples/ClassList/ClassList.pde (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/keywords.txt (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/library.json (100%) rename {lib => lib_i2c}/LinkedList-1.2.3/library.properties (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/License.txt (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/README.md (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/library.json (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/library.properties (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp (100%) rename {lib => lib_i2c}/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h (100%) rename {lib => lib_i2c}/mlx90640-library/MLX90640_API.cpp (96%) rename {lib => lib_i2c}/mlx90640-library/MLX90640_API.h (97%) rename {lib => lib_i2c}/mlx90640-library/library.properties (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/.travis.yml (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/LICENSE.txt (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/README.md (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.cpp (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.h (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/examples/Single/Single.ino (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/keywords.txt (100%) rename {lib => lib_i2c}/vl53l0x-arduino-1.02/library.properties (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/LICENSE.txt (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/README.md (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.cpp (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.h (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/keywords.txt (100%) rename {lib => lib_i2c}/vl53l1x-arduino-1.01/library.properties (100%) rename {lib => lib_rf}/KeeloqLib/README.md (100%) rename {lib => lib_rf}/KeeloqLib/keywords.txt (100%) rename {lib => lib_rf}/KeeloqLib/library.properties (100%) rename {lib => lib_rf}/KeeloqLib/src/KeeloqLib.cpp (100%) rename {lib => lib_rf}/KeeloqLib/src/KeeloqLib.h (100%) rename {lib => lib_rf}/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino (100%) rename {lib => lib_rf}/RF24/.gitignore (100%) rename {lib => lib_rf}/RF24/CONTRIBUTING.md (100%) rename {lib => lib_rf}/RF24/Doxyfile (100%) rename {lib => lib_rf}/RF24/LICENSE (100%) rename {lib => lib_rf}/RF24/Makefile (100%) rename {lib => lib_rf}/RF24/README.md (100%) rename {lib => lib_rf}/RF24/RF24.cpp (100%) rename {lib => lib_rf}/RF24/RF24.h (100%) rename {lib => lib_rf}/RF24/RF24_config.h (100%) rename {lib => lib_rf}/RF24/configure (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/doxygen-custom.css (100%) rename {lib => lib_rf}/RF24/examples/GettingStarted/GettingStarted.ino (100%) rename {lib => lib_rf}/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino (100%) rename {lib => lib_rf}/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino (100%) rename {lib => lib_rf}/RF24/examples/Transfer/Transfer.ino (100%) rename {lib => lib_rf}/RF24/examples/TransferTimeouts/TransferTimeouts.ino (100%) rename {lib => lib_rf}/RF24/examples/Usage/led_remote/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/Usage/led_remote/led_remote.pde (100%) rename {lib => lib_rf}/RF24/examples/Usage/nordic_fob/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/Usage/nordic_fob/nordic_fob.pde (100%) rename {lib => lib_rf}/RF24/examples/Usage/pingpair_maple/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/Usage/pingpair_maple/main.cpp (100%) rename {lib => lib_rf}/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde (100%) rename {lib => lib_rf}/RF24/examples/Usage/readme.md (100%) rename {lib => lib_rf}/RF24/examples/pingpair_ack/pingpair_ack.ino (100%) rename {lib => lib_rf}/RF24/examples/pingpair_dyn/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/pingpair_dyn/pingpair_dyn.ino (100%) rename {lib => lib_rf}/RF24/examples/pingpair_irq/pingpair_irq.ino (100%) rename {lib => lib_rf}/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino (100%) rename {lib => lib_rf}/RF24/examples/pingpair_multi_dyn/Jamfile (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino (100%) rename {lib => lib_rf}/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino (100%) rename {lib => lib_rf}/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino (100%) rename {lib => lib_rf}/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino (100%) rename {lib => lib_rf}/RF24/examples/scanner/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/scanner/scanner.ino (100%) rename {lib => lib_rf}/RF24/examples/starping/Jamfile (100%) rename {lib => lib_rf}/RF24/examples/starping/starping.pde (100%) rename {lib => lib_rf}/RF24/examples_linux/Makefile.examples (100%) rename {lib => lib_rf}/RF24/examples_linux/extra/Makefile (100%) rename {lib => lib_rf}/RF24/examples_linux/extra/rpi-hub.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/extra/scanner.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/gettingstarted.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/gettingstarted_call_response.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/interrupts/Makefile (100%) rename {lib => lib_rf}/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/interrupts/transfer_interrupt.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/pingpair_dyn.cpp (100%) rename {lib => lib_rf}/RF24/examples_linux/pingpair_dyn.py (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/examples_linux/readme.md (100%) rename {lib => lib_rf}/RF24/examples_linux/transfer.cpp (100%) rename {lib => lib_rf}/RF24/keywords.txt (100%) rename {lib => lib_rf}/RF24/library.json (100%) rename {lib => lib_rf}/RF24/library.properties (100%) rename {lib => lib_rf}/RF24/nRF24L01.h (100%) rename {lib => lib_rf}/RF24/printf.h (100%) rename {lib => lib_rf}/RF24/pyRF24/crossunixccompiler.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24.cpp (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24/crossunixccompiler.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24/pyRF24.cpp (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24/readme.md (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24/setup.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Mesh/example_master.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Mesh/setup.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp (100%) rename {lib => lib_rf}/RF24/pyRF24/pyRF24Network/setup.py (100%) rename {lib => lib_rf}/RF24/pyRF24/readme.md (100%) rename {lib => lib_rf}/RF24/pyRF24/setup.py (100%) rename {lib => lib_rf}/RF24/tests/README (100%) rename {lib => lib_rf}/RF24/tests/native/Jamfile (100%) rename {lib => lib_rf}/RF24/tests/native/pingpair_irq.pde (100%) rename {lib => lib_rf}/RF24/tests/native/printf.h (100%) rename {lib => lib_rf}/RF24/tests/pingpair_blocking/Jamfile (100%) rename {lib => lib_rf}/RF24/tests/pingpair_blocking/pingpair_blocking.pde (100%) rename {lib => lib_rf}/RF24/tests/pingpair_blocking/printf.h (100%) rename {lib => lib_rf}/RF24/tests/pingpair_blocking/runtest.py (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/tests/pingpair_blocking/runtests.sh (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/tests/pingpair_blocking/test.ex (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/tests/pingpair_test/Jamfile (100%) rename {lib => lib_rf}/RF24/tests/pingpair_test/pingpair_test.pde (100%) rename {lib => lib_rf}/RF24/tests/pingpair_test/printf.h (100%) rename {lib => lib_rf}/RF24/tests/pingpair_test/runtest.py (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/tests/pingpair_test/runtests.sh (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/tests/pingpair_test/test.ex (100%) mode change 100755 => 100644 rename {lib => lib_rf}/RF24/utility/ATTiny/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/ATTiny/spi.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/README.md (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/compatibility.c (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/compatibility.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/gpio.cpp (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/gpio.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/gpio_helper.c (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/gpio_helper.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/includes.h (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/spi.cpp (100%) rename {lib => lib_rf}/RF24/utility/ATXMegaD3/spi.h (100%) rename {lib => lib_rf}/RF24/utility/Due/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/LittleWire/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/LittleWire/includes.h (100%) rename {lib => lib_rf}/RF24/utility/MRAA/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/MRAA/compatibility.c (100%) rename {lib => lib_rf}/RF24/utility/MRAA/compatibility.h (100%) rename {lib => lib_rf}/RF24/utility/MRAA/gpio.cpp (100%) rename {lib => lib_rf}/RF24/utility/MRAA/gpio.h (100%) rename {lib => lib_rf}/RF24/utility/MRAA/includes.h (100%) rename {lib => lib_rf}/RF24/utility/MRAA/spi.cpp (100%) rename {lib => lib_rf}/RF24/utility/MRAA/spi.h (100%) rename {lib => lib_rf}/RF24/utility/RPi/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/RPi/bcm2835.c (100%) rename {lib => lib_rf}/RF24/utility/RPi/bcm2835.h (100%) rename {lib => lib_rf}/RF24/utility/RPi/includes.h (100%) rename {lib => lib_rf}/RF24/utility/RPi/interrupt.c (100%) rename {lib => lib_rf}/RF24/utility/RPi/interrupt.h (100%) rename {lib => lib_rf}/RF24/utility/RPi/spi.cpp (100%) rename {lib => lib_rf}/RF24/utility/RPi/spi.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/compatibility.c (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/compatibility.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/gpio.cpp (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/gpio.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/includes.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/interrupt.c (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/interrupt.h (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/spi.cpp (100%) rename {lib => lib_rf}/RF24/utility/SPIDEV/spi.h (100%) rename {lib => lib_rf}/RF24/utility/Teensy/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/Template/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/Template/compatibility.h (100%) rename {lib => lib_rf}/RF24/utility/Template/gpio.h (100%) rename {lib => lib_rf}/RF24/utility/Template/includes.h (100%) rename {lib => lib_rf}/RF24/utility/Template/spi.h (100%) rename {lib => lib_rf}/RF24/utility/wiringPi/RF24_arch_config.h (100%) rename {lib => lib_rf}/RF24/utility/wiringPi/includes.h (100%) rename {lib => lib_rf}/RF24/utility/wiringPi/spi.cpp (100%) rename {lib => lib_rf}/RF24/utility/wiringPi/spi.h (100%) rename {lib => lib_rf}/RF24/wikidoc.xslt (100%) rename {lib => lib_rf}/cc1101/README.md (100%) rename {lib => lib_rf}/cc1101/cc1101.cpp (100%) rename {lib => lib_rf}/cc1101/cc1101.h (100%) rename {lib => lib_rf}/cc1101/cc1101.h.txt (100%) rename {lib => lib_rf}/cc1101/ccpacket.h (100%) rename {lib => lib_rf}/cc1101/library.properties (100%) rename {lib => lib_rf}/rc-switch/.gitignore (100%) rename {lib => lib_rf}/rc-switch/README.md (100%) rename {lib => lib_rf}/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino (100%) rename {lib => lib_rf}/rc-switch/examples/ReceiveDemo_Advanced/output.ino (100%) rename {lib => lib_rf}/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino (100%) rename {lib => lib_rf}/rc-switch/examples/SendDemo/SendDemo.ino (100%) rename {lib => lib_rf}/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino (100%) rename {lib => lib_rf}/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino (100%) rename {lib => lib_rf}/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino (100%) rename {lib => lib_rf}/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino (100%) rename {lib => lib_rf}/rc-switch/examples/TypeD_REV/TypeD_REV.ino (100%) rename {lib => lib_rf}/rc-switch/examples/Webserver/Webserver.ino (100%) rename {lib => lib_rf}/rc-switch/keywords.txt (100%) rename {lib => lib_rf}/rc-switch/library.json (100%) rename {lib => lib_rf}/rc-switch/library.properties (100%) rename {lib => lib_rf}/rc-switch/platformio.ini (100%) rename {lib => lib_rf}/rc-switch/src/RCSwitch.cpp (100%) rename {lib => lib_rf}/rc-switch/src/RCSwitch.h (100%) rename {lib => lib_ssl}/base64-1.1.1/LICENSE (100%) rename {lib => lib_ssl}/base64-1.1.1/Makefile (100%) rename {lib => lib_ssl}/base64-1.1.1/README.md (100%) rename {lib => lib_ssl}/base64-1.1.1/catch.cpp (100%) rename {lib => lib_ssl}/base64-1.1.1/catch.hpp (100%) rename {lib => lib_ssl}/base64-1.1.1/library.properties (100%) rename {lib => lib_ssl}/base64-1.1.1/src/base64.hpp (100%) rename {lib => lib_ssl}/bearssl-esp8266/bearssl_esp8266-customized.txt (100%) rename {lib => lib_ssl}/bearssl-esp8266/conf/esp8266.mk (100%) rename {lib => lib_ssl}/bearssl-esp8266/library.properties (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/aead/ccm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/aead/eax.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/aead/gcm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/ccopy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec16be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec16le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec32be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec32le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec64be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/dec64le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc16be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc16le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc32be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc32le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc64be.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/enc64le.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/pemdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/codec/pemenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_all_m15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_c25519_i15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_curve25519.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_default.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_keygen.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_p256_m15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_prime_i15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_pubkey.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_secp256r1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_secp384r1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ec_secp521r1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_atr.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_bits.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ec/ecdsa_rta.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/dig_oid.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/dig_size.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul32.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul64.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/ghash_pclmul.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/md5.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/md5sha1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/mgf1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/multihash.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/sha1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/sha2big.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/hash/sha2small.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_add.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_bitlen.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_decmod.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_decode.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_decred.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_encode.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_fmont.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_iszero.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_moddiv.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_modpow.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_modpow2.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_montmul.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_mulacc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_muladd.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_ninv15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_reduce.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_rshift.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_sub.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/int/i15_tmont.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/kdf/hkdf.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/kdf/shake.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/mac/hmac.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/mac/hmac_ct.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/pgmspace_bearssl.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rand/aesctr_drbg.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rand/hmac_drbg.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rand/sysrng.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_keygen.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_modulus.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_priv.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_privexp.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pub.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pubexp.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_keygen.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_modulus.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_priv.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_privexp.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pub.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_oaep_pad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/settings.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/prf.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/prf_md5sha1.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/prf_sha256.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/prf_sha384.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_client.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_client_full.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_hashes.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_hs_client.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_hs_server.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_io.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_keyexport.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_lru.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_cbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_ccm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_chapol.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_gcm.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_ctr.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_dec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_enc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_common.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_dec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_enc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_ctr.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_dec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_enc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_ctr.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_dec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_enc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/chacha20_ct.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/chacha20_sse2.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_ct.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_support.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_tab.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmul.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_i15.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_aead.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_block.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_ec.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_hash.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_hmac.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_kdf.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_pem.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_prf.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_rand.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_rsa.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_ssl.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_tasmota_config.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_bearssl_x509.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_config.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/t_inner.h (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/asn1enc.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/encode_ec_pk8der.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/encode_ec_rawder.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/encode_rsa_pk8der.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/encode_rsa_rawder.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/pkey_decoder.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/skey_decoder.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/x509_decoder.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/x509_knownkey.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/x509_minimal.c (100%) rename {lib => lib_ssl}/bearssl-esp8266/src/x509/x509_minimal_full.c (100%) create mode 100644 platformio_tasmota_env.ini.new diff --git a/lib/FT5206_Library/.gitignore b/lib/FT5206_Library/.gitignore deleted file mode 100755 index 9d2e4113a..000000000 --- a/lib/FT5206_Library/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.vscode -.DS_Store \ No newline at end of file diff --git a/lib/FT5206_Library/README.md b/lib/FT5206_Library/README.md deleted file mode 100755 index 2d6fffa6b..000000000 --- a/lib/FT5206_Library/README.md +++ /dev/null @@ -1,2 +0,0 @@ -FT5206 Library -===================================== \ No newline at end of file diff --git a/lib/ESP8266Audio/.github/workflows/pr-or-master-push.yml b/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/.github/workflows/pr-or-master-push.yml rename to lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml diff --git a/lib/ESP8266Audio/LICENSE b/lib_audio/ESP8266Audio/LICENSE old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/LICENSE rename to lib_audio/ESP8266Audio/LICENSE diff --git a/lib/ESP8266Audio/README.md b/lib_audio/ESP8266Audio/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/README.md rename to lib_audio/ESP8266Audio/README.md diff --git a/lib/ESP8266Audio/examples/MixerSample/MixerSample.ino b/lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/MixerSample/MixerSample.ino rename to lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino diff --git a/lib/ESP8266Audio/examples/MixerSample/viola.h b/lib_audio/ESP8266Audio/examples/MixerSample/viola.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/MixerSample/viola.h rename to lib_audio/ESP8266Audio/examples/MixerSample/viola.h diff --git a/lib/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino b/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino rename to lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino diff --git a/lib/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac b/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac rename to lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac diff --git a/lib/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h b/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h rename to lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h diff --git a/lib/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino b/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino rename to lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino diff --git a/lib/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino b/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino rename to lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino diff --git a/lib/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h b/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h rename to lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino b/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 b/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid b/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino b/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 b/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 diff --git a/lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid b/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid rename to lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid diff --git a/lib/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino b/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino rename to lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino diff --git a/lib/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h b/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h rename to lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h diff --git a/lib/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino b/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino rename to lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino diff --git a/lib/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 b/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 rename to lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 diff --git a/lib/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino b/lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino rename to lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino diff --git a/lib/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino b/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino rename to lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino diff --git a/lib/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus b/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus rename to lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus diff --git a/lib/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino b/lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino rename to lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino diff --git a/lib/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino b/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino rename to lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino diff --git a/lib/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h b/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h rename to lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h diff --git a/lib/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino b/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino rename to lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino diff --git a/lib/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png b/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png rename to lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png diff --git a/lib/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino b/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino rename to lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino diff --git a/lib/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino b/lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino rename to lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino diff --git a/lib/ESP8266Audio/examples/WebRadio/WebRadio.ino b/lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/WebRadio/WebRadio.ino rename to lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino diff --git a/lib/ESP8266Audio/examples/WebRadio/web.cpp b/lib_audio/ESP8266Audio/examples/WebRadio/web.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/WebRadio/web.cpp rename to lib_audio/ESP8266Audio/examples/WebRadio/web.cpp diff --git a/lib/ESP8266Audio/examples/WebRadio/web.h b/lib_audio/ESP8266Audio/examples/WebRadio/web.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/examples/WebRadio/web.h rename to lib_audio/ESP8266Audio/examples/WebRadio/web.h diff --git a/lib/ESP8266Audio/keywords.txt b/lib_audio/ESP8266Audio/keywords.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/keywords.txt rename to lib_audio/ESP8266Audio/keywords.txt diff --git a/lib/ESP8266Audio/library.json b/lib_audio/ESP8266Audio/library.json old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/library.json rename to lib_audio/ESP8266Audio/library.json diff --git a/lib/ESP8266Audio/library.properties b/lib_audio/ESP8266Audio/library.properties old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/library.properties rename to lib_audio/ESP8266Audio/library.properties diff --git a/lib/ESP8266Audio/src/AudioFileSource.h b/lib_audio/ESP8266Audio/src/AudioFileSource.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSource.h rename to lib_audio/ESP8266Audio/src/AudioFileSource.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceBuffer.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceBuffer.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceBuffer.h b/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceBuffer.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceFATFS.h b/lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceFATFS.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceFS.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceFS.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceFS.h b/lib_audio/ESP8266Audio/src/AudioFileSourceFS.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceFS.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceFS.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceHTTPStream.h b/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceHTTPStream.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceICYStream.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceICYStream.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceICYStream.h b/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceICYStream.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceID3.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceID3.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceID3.h b/lib_audio/ESP8266Audio/src/AudioFileSourceID3.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceID3.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceID3.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceLittleFS.h b/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceLittleFS.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h diff --git a/lib/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourcePROGMEM.h b/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourcePROGMEM.h rename to lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceSD.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSD.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceSD.h b/lib_audio/ESP8266Audio/src/AudioFileSourceSD.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSD.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceSD.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceSPIFFS.h b/lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSPIFFS.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h b/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h diff --git a/lib/ESP8266Audio/src/AudioFileSourceSTDIO.cpp b/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSTDIO.cpp rename to lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp diff --git a/lib/ESP8266Audio/src/AudioFileSourceSTDIO.h b/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileSourceSTDIO.h rename to lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h diff --git a/lib/ESP8266Audio/src/AudioFileStream.cpp b/lib_audio/ESP8266Audio/src/AudioFileStream.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileStream.cpp rename to lib_audio/ESP8266Audio/src/AudioFileStream.cpp diff --git a/lib/ESP8266Audio/src/AudioFileStream.h b/lib_audio/ESP8266Audio/src/AudioFileStream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioFileStream.h rename to lib_audio/ESP8266Audio/src/AudioFileStream.h diff --git a/lib/ESP8266Audio/src/AudioGenerator.h b/lib_audio/ESP8266Audio/src/AudioGenerator.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGenerator.h rename to lib_audio/ESP8266Audio/src/AudioGenerator.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorAAC.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorAAC.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorAAC.h b/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorAAC.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorFLAC.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorFLAC.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorFLAC.h b/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorFLAC.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorMIDI.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMIDI.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorMIDI.h b/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMIDI.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorMOD.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMOD.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorMOD.h b/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMOD.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorMP3.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMP3.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorMP3.h b/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMP3.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorMP3a.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMP3a.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorMP3a.h b/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorMP3a.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorOpus.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorOpus.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorOpus.h b/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorOpus.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorRTTTL.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorRTTTL.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorRTTTL.h b/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorRTTTL.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorTalkie.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorTalkie.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorTalkie.h b/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorTalkie.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h diff --git a/lib/ESP8266Audio/src/AudioGeneratorWAV.cpp b/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorWAV.cpp rename to lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp diff --git a/lib/ESP8266Audio/src/AudioGeneratorWAV.h b/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioGeneratorWAV.h rename to lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h diff --git a/lib/ESP8266Audio/src/AudioLogger.cpp b/lib_audio/ESP8266Audio/src/AudioLogger.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioLogger.cpp rename to lib_audio/ESP8266Audio/src/AudioLogger.cpp diff --git a/lib/ESP8266Audio/src/AudioLogger.h b/lib_audio/ESP8266Audio/src/AudioLogger.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioLogger.h rename to lib_audio/ESP8266Audio/src/AudioLogger.h diff --git a/lib/ESP8266Audio/src/AudioOutput.h b/lib_audio/ESP8266Audio/src/AudioOutput.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutput.h rename to lib_audio/ESP8266Audio/src/AudioOutput.h diff --git a/lib/ESP8266Audio/src/AudioOutputBuffer.cpp b/lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputBuffer.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputBuffer.h b/lib_audio/ESP8266Audio/src/AudioOutputBuffer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputBuffer.h rename to lib_audio/ESP8266Audio/src/AudioOutputBuffer.h diff --git a/lib/ESP8266Audio/src/AudioOutputFilterDecimate.cpp b/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputFilterDecimate.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputFilterDecimate.h b/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputFilterDecimate.h rename to lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h diff --git a/lib/ESP8266Audio/src/AudioOutputI2S.cpp b/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputI2S.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputI2S.h b/lib_audio/ESP8266Audio/src/AudioOutputI2S.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputI2S.h rename to lib_audio/ESP8266Audio/src/AudioOutputI2S.h diff --git a/lib/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp b/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputI2SNoDAC.h b/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputI2SNoDAC.h rename to lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h diff --git a/lib/ESP8266Audio/src/AudioOutputMixer.cpp b/lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputMixer.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputMixer.h b/lib_audio/ESP8266Audio/src/AudioOutputMixer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputMixer.h rename to lib_audio/ESP8266Audio/src/AudioOutputMixer.h diff --git a/lib/ESP8266Audio/src/AudioOutputNull.h b/lib_audio/ESP8266Audio/src/AudioOutputNull.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputNull.h rename to lib_audio/ESP8266Audio/src/AudioOutputNull.h diff --git a/lib/ESP8266Audio/src/AudioOutputSPDIF.cpp b/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSPDIF.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputSPDIF.h b/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSPDIF.h rename to lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h diff --git a/lib/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp b/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputSPIFFSWAV.h b/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSPIFFSWAV.h rename to lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h diff --git a/lib/ESP8266Audio/src/AudioOutputSTDIO.cpp b/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSTDIO.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputSTDIO.h b/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSTDIO.h rename to lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h diff --git a/lib/ESP8266Audio/src/AudioOutputSerialWAV.cpp b/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSerialWAV.cpp rename to lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp diff --git a/lib/ESP8266Audio/src/AudioOutputSerialWAV.h b/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioOutputSerialWAV.h rename to lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h diff --git a/lib/ESP8266Audio/src/AudioStatus.h b/lib_audio/ESP8266Audio/src/AudioStatus.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/AudioStatus.h rename to lib_audio/ESP8266Audio/src/AudioStatus.h diff --git a/lib/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp b/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp rename to lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp diff --git a/lib/ESP8266Audio/src/driver/SinglePinI2SDriver.h b/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/driver/SinglePinI2SDriver.h rename to lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h diff --git a/lib/ESP8266Audio/src/libflac/AUTHORS b/lib_audio/ESP8266Audio/src/libflac/AUTHORS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/AUTHORS rename to lib_audio/ESP8266Audio/src/libflac/AUTHORS diff --git a/lib/ESP8266Audio/src/libflac/COPYING.FDL b/lib_audio/ESP8266Audio/src/libflac/COPYING.FDL old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/COPYING.FDL rename to lib_audio/ESP8266Audio/src/libflac/COPYING.FDL diff --git a/lib/ESP8266Audio/src/libflac/COPYING.GPL b/lib_audio/ESP8266Audio/src/libflac/COPYING.GPL old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/COPYING.GPL rename to lib_audio/ESP8266Audio/src/libflac/COPYING.GPL diff --git a/lib/ESP8266Audio/src/libflac/COPYING.LGPL b/lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/COPYING.LGPL rename to lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL diff --git a/lib/ESP8266Audio/src/libflac/COPYING.Xiph b/lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/COPYING.Xiph rename to lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph diff --git a/lib/ESP8266Audio/src/libflac/FLAC/assert.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/assert.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/callback.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/callback.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/export.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/export.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/export.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/export.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/format.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/format.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/format.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/format.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/metadata.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/metadata.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/ordinals.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/ordinals.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h diff --git a/lib/ESP8266Audio/src/libflac/FLAC/stream_decoder.h b/lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/FLAC/stream_decoder.h rename to lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h diff --git a/lib/ESP8266Audio/src/libflac/README b/lib_audio/ESP8266Audio/src/libflac/README old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/README rename to lib_audio/ESP8266Audio/src/libflac/README diff --git a/lib/ESP8266Audio/src/libflac/README.ESP8266 b/lib_audio/ESP8266Audio/src/libflac/README.ESP8266 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/README.ESP8266 rename to lib_audio/ESP8266Audio/src/libflac/README.ESP8266 diff --git a/lib/ESP8266Audio/src/libflac/bitmath.c b/lib_audio/ESP8266Audio/src/libflac/bitmath.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/bitmath.c rename to lib_audio/ESP8266Audio/src/libflac/bitmath.c diff --git a/lib/ESP8266Audio/src/libflac/bitreader.c b/lib_audio/ESP8266Audio/src/libflac/bitreader.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/bitreader.c rename to lib_audio/ESP8266Audio/src/libflac/bitreader.c diff --git a/lib/ESP8266Audio/src/libflac/config.h b/lib_audio/ESP8266Audio/src/libflac/config.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/config.h rename to lib_audio/ESP8266Audio/src/libflac/config.h diff --git a/lib/ESP8266Audio/src/libflac/cpu.c b/lib_audio/ESP8266Audio/src/libflac/cpu.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/cpu.c rename to lib_audio/ESP8266Audio/src/libflac/cpu.c diff --git a/lib/ESP8266Audio/src/libflac/crc.c b/lib_audio/ESP8266Audio/src/libflac/crc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/crc.c rename to lib_audio/ESP8266Audio/src/libflac/crc.c diff --git a/lib/ESP8266Audio/src/libflac/fixed.c b/lib_audio/ESP8266Audio/src/libflac/fixed.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/fixed.c rename to lib_audio/ESP8266Audio/src/libflac/fixed.c diff --git a/lib/ESP8266Audio/src/libflac/float.c b/lib_audio/ESP8266Audio/src/libflac/float.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/float.c rename to lib_audio/ESP8266Audio/src/libflac/float.c diff --git a/lib/ESP8266Audio/src/libflac/format.c b/lib_audio/ESP8266Audio/src/libflac/format.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/format.c rename to lib_audio/ESP8266Audio/src/libflac/format.c diff --git a/lib/ESP8266Audio/src/libflac/lpc.c b/lib_audio/ESP8266Audio/src/libflac/lpc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/lpc.c rename to lib_audio/ESP8266Audio/src/libflac/lpc.c diff --git a/lib/ESP8266Audio/src/libflac/md5.c b/lib_audio/ESP8266Audio/src/libflac/md5.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/md5.c rename to lib_audio/ESP8266Audio/src/libflac/md5.c diff --git a/lib/ESP8266Audio/src/libflac/memory.c b/lib_audio/ESP8266Audio/src/libflac/memory.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/memory.c rename to lib_audio/ESP8266Audio/src/libflac/memory.c diff --git a/lib/ESP8266Audio/src/libflac/private/bitmath.h b/lib_audio/ESP8266Audio/src/libflac/private/bitmath.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/bitmath.h rename to lib_audio/ESP8266Audio/src/libflac/private/bitmath.h diff --git a/lib/ESP8266Audio/src/libflac/private/bitreader.h b/lib_audio/ESP8266Audio/src/libflac/private/bitreader.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/bitreader.h rename to lib_audio/ESP8266Audio/src/libflac/private/bitreader.h diff --git a/lib/ESP8266Audio/src/libflac/private/cpu.h b/lib_audio/ESP8266Audio/src/libflac/private/cpu.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/cpu.h rename to lib_audio/ESP8266Audio/src/libflac/private/cpu.h diff --git a/lib/ESP8266Audio/src/libflac/private/crc.h b/lib_audio/ESP8266Audio/src/libflac/private/crc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/crc.h rename to lib_audio/ESP8266Audio/src/libflac/private/crc.h diff --git a/lib/ESP8266Audio/src/libflac/private/fixed.h b/lib_audio/ESP8266Audio/src/libflac/private/fixed.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/fixed.h rename to lib_audio/ESP8266Audio/src/libflac/private/fixed.h diff --git a/lib/ESP8266Audio/src/libflac/private/float.h b/lib_audio/ESP8266Audio/src/libflac/private/float.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/float.h rename to lib_audio/ESP8266Audio/src/libflac/private/float.h diff --git a/lib/ESP8266Audio/src/libflac/private/format.h b/lib_audio/ESP8266Audio/src/libflac/private/format.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/format.h rename to lib_audio/ESP8266Audio/src/libflac/private/format.h diff --git a/lib/ESP8266Audio/src/libflac/private/lpc.h b/lib_audio/ESP8266Audio/src/libflac/private/lpc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/lpc.h rename to lib_audio/ESP8266Audio/src/libflac/private/lpc.h diff --git a/lib/ESP8266Audio/src/libflac/private/macros.h b/lib_audio/ESP8266Audio/src/libflac/private/macros.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/macros.h rename to lib_audio/ESP8266Audio/src/libflac/private/macros.h diff --git a/lib/ESP8266Audio/src/libflac/private/md5.h b/lib_audio/ESP8266Audio/src/libflac/private/md5.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/md5.h rename to lib_audio/ESP8266Audio/src/libflac/private/md5.h diff --git a/lib/ESP8266Audio/src/libflac/private/memory.h b/lib_audio/ESP8266Audio/src/libflac/private/memory.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/memory.h rename to lib_audio/ESP8266Audio/src/libflac/private/memory.h diff --git a/lib/ESP8266Audio/src/libflac/private/metadata.h b/lib_audio/ESP8266Audio/src/libflac/private/metadata.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/metadata.h rename to lib_audio/ESP8266Audio/src/libflac/private/metadata.h diff --git a/lib/ESP8266Audio/src/libflac/private/window.h b/lib_audio/ESP8266Audio/src/libflac/private/window.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/private/window.h rename to lib_audio/ESP8266Audio/src/libflac/private/window.h diff --git a/lib/ESP8266Audio/src/libflac/protected/all.h b/lib_audio/ESP8266Audio/src/libflac/protected/all.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/protected/all.h rename to lib_audio/ESP8266Audio/src/libflac/protected/all.h diff --git a/lib/ESP8266Audio/src/libflac/protected/stream_decoder.h b/lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/protected/stream_decoder.h rename to lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h diff --git a/lib/ESP8266Audio/src/libflac/protected/stream_encoder.h b/lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/protected/stream_encoder.h rename to lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h diff --git a/lib/ESP8266Audio/src/libflac/share/alloc.h b/lib_audio/ESP8266Audio/src/libflac/share/alloc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/alloc.h rename to lib_audio/ESP8266Audio/src/libflac/share/alloc.h diff --git a/lib/ESP8266Audio/src/libflac/share/compat.h b/lib_audio/ESP8266Audio/src/libflac/share/compat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/compat.h rename to lib_audio/ESP8266Audio/src/libflac/share/compat.h diff --git a/lib/ESP8266Audio/src/libflac/share/endswap.h b/lib_audio/ESP8266Audio/src/libflac/share/endswap.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/endswap.h rename to lib_audio/ESP8266Audio/src/libflac/share/endswap.h diff --git a/lib/ESP8266Audio/src/libflac/share/getopt.h b/lib_audio/ESP8266Audio/src/libflac/share/getopt.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/getopt.h rename to lib_audio/ESP8266Audio/src/libflac/share/getopt.h diff --git a/lib/ESP8266Audio/src/libflac/share/macros.h b/lib_audio/ESP8266Audio/src/libflac/share/macros.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/macros.h rename to lib_audio/ESP8266Audio/src/libflac/share/macros.h diff --git a/lib/ESP8266Audio/src/libflac/share/private.h b/lib_audio/ESP8266Audio/src/libflac/share/private.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/private.h rename to lib_audio/ESP8266Audio/src/libflac/share/private.h diff --git a/lib/ESP8266Audio/src/libflac/share/safe_str.h b/lib_audio/ESP8266Audio/src/libflac/share/safe_str.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/safe_str.h rename to lib_audio/ESP8266Audio/src/libflac/share/safe_str.h diff --git a/lib/ESP8266Audio/src/libflac/share/utf8.h b/lib_audio/ESP8266Audio/src/libflac/share/utf8.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/share/utf8.h rename to lib_audio/ESP8266Audio/src/libflac/share/utf8.h diff --git a/lib/ESP8266Audio/src/libflac/stream_decoder.c b/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/stream_decoder.c rename to lib_audio/ESP8266Audio/src/libflac/stream_decoder.c diff --git a/lib/ESP8266Audio/src/libflac/window.c b/lib_audio/ESP8266Audio/src/libflac/window.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libflac/window.c rename to lib_audio/ESP8266Audio/src/libflac/window.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/aaccommon.h b/lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/aaccommon.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/aacdec.c b/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/aacdec.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/aacdec.h b/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/aacdec.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/aactabs.c b/lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/aactabs.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/assembly.h b/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/assembly.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/bitstream.c b/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/bitstream.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/bitstream.h b/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/bitstream.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/buffers.c b/lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/buffers.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/coder.h b/lib_audio/ESP8266Audio/src/libhelix-aac/coder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/coder.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/coder.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/dct4.c b/lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/dct4.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/decelmnt.c b/lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/decelmnt.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/dequant.c b/lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/dequant.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/fft.c b/lib_audio/ESP8266Audio/src/libhelix-aac/fft.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/fft.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/fft.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/filefmt.c b/lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/filefmt.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/huffman.c b/lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/huffman.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/hufftabs.c b/lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/hufftabs.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/imdct.c b/lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/imdct.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/noiseless.c b/lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/noiseless.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/pns.c b/lib_audio/ESP8266Audio/src/libhelix-aac/pns.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/pns.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/pns.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/readme.txt b/lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/readme.txt rename to lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbr.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbr.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbr.h b/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbr.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrfft.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrfft.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrfreq.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrfreq.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrhfadj.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrhfadj.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrhfgen.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrhfgen.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrhuff.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrhuff.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrimdct.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrimdct.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrmath.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrmath.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrqmf.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrqmf.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrside.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrside.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/sbrtabs.c b/lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/sbrtabs.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/statname.h b/lib_audio/ESP8266Audio/src/libhelix-aac/statname.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/statname.h rename to lib_audio/ESP8266Audio/src/libhelix-aac/statname.h diff --git a/lib/ESP8266Audio/src/libhelix-aac/stproc.c b/lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/stproc.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/tns.c b/lib_audio/ESP8266Audio/src/libhelix-aac/tns.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/tns.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/tns.c diff --git a/lib/ESP8266Audio/src/libhelix-aac/trigtabs.c b/lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-aac/trigtabs.c rename to lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/LICENSE.txt b/lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/LICENSE.txt rename to lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt diff --git a/lib/ESP8266Audio/src/libhelix-mp3/RCSL.txt b/lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/RCSL.txt rename to lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt diff --git a/lib/ESP8266Audio/src/libhelix-mp3/RPSL.txt b/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/RPSL.txt rename to lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt diff --git a/lib/ESP8266Audio/src/libhelix-mp3/assembly.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/assembly.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/bitstream.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/bitstream.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/buffers.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/buffers.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/coder.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/coder.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/dct32.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/dct32.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/dequant.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/dequant.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/dqchan.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/dqchan.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/huffman.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/huffman.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/hufftabs.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/hufftabs.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/imdct.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/imdct.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/mp3common.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/mp3common.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/mp3dec.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/mp3dec.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/mp3dec.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/mp3dec.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/mp3tabs.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/mp3tabs.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/player.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/player.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/player.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/player.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/polyphase.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/polyphase.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/scalfact.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/scalfact.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/statname.h b/lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/statname.h rename to lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h diff --git a/lib/ESP8266Audio/src/libhelix-mp3/stproc.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/stproc.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/subband.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/subband.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c diff --git a/lib/ESP8266Audio/src/libhelix-mp3/trigtabs.c b/lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libhelix-mp3/trigtabs.c rename to lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c diff --git a/lib/ESP8266Audio/src/libmad/CHANGES b/lib_audio/ESP8266Audio/src/libmad/CHANGES old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/CHANGES rename to lib_audio/ESP8266Audio/src/libmad/CHANGES diff --git a/lib/ESP8266Audio/src/libmad/COPYING b/lib_audio/ESP8266Audio/src/libmad/COPYING old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/COPYING rename to lib_audio/ESP8266Audio/src/libmad/COPYING diff --git a/lib/ESP8266Audio/src/libmad/COPYRIGHT b/lib_audio/ESP8266Audio/src/libmad/COPYRIGHT old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/COPYRIGHT rename to lib_audio/ESP8266Audio/src/libmad/COPYRIGHT diff --git a/lib/ESP8266Audio/src/libmad/CREDITS b/lib_audio/ESP8266Audio/src/libmad/CREDITS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/CREDITS rename to lib_audio/ESP8266Audio/src/libmad/CREDITS diff --git a/lib/ESP8266Audio/src/libmad/D.dat.h b/lib_audio/ESP8266Audio/src/libmad/D.dat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/D.dat.h rename to lib_audio/ESP8266Audio/src/libmad/D.dat.h diff --git a/lib/ESP8266Audio/src/libmad/LICENSE b/lib_audio/ESP8266Audio/src/libmad/LICENSE old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/LICENSE rename to lib_audio/ESP8266Audio/src/libmad/LICENSE diff --git a/lib/ESP8266Audio/src/libmad/README b/lib_audio/ESP8266Audio/src/libmad/README old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/README rename to lib_audio/ESP8266Audio/src/libmad/README diff --git a/lib/ESP8266Audio/src/libmad/README.ESP8266 b/lib_audio/ESP8266Audio/src/libmad/README.ESP8266 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/README.ESP8266 rename to lib_audio/ESP8266Audio/src/libmad/README.ESP8266 diff --git a/lib/ESP8266Audio/src/libmad/TODO b/lib_audio/ESP8266Audio/src/libmad/TODO old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/TODO rename to lib_audio/ESP8266Audio/src/libmad/TODO diff --git a/lib/ESP8266Audio/src/libmad/VERSION b/lib_audio/ESP8266Audio/src/libmad/VERSION old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/VERSION rename to lib_audio/ESP8266Audio/src/libmad/VERSION diff --git a/lib/ESP8266Audio/src/libmad/bit.c b/lib_audio/ESP8266Audio/src/libmad/bit.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/bit.c rename to lib_audio/ESP8266Audio/src/libmad/bit.c diff --git a/lib/ESP8266Audio/src/libmad/bit.h b/lib_audio/ESP8266Audio/src/libmad/bit.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/bit.h rename to lib_audio/ESP8266Audio/src/libmad/bit.h diff --git a/lib/ESP8266Audio/src/libmad/config.h b/lib_audio/ESP8266Audio/src/libmad/config.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/config.h rename to lib_audio/ESP8266Audio/src/libmad/config.h diff --git a/lib/ESP8266Audio/src/libmad/decoder.c b/lib_audio/ESP8266Audio/src/libmad/decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/decoder.c rename to lib_audio/ESP8266Audio/src/libmad/decoder.c diff --git a/lib/ESP8266Audio/src/libmad/decoder.h b/lib_audio/ESP8266Audio/src/libmad/decoder.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/decoder.h rename to lib_audio/ESP8266Audio/src/libmad/decoder.h diff --git a/lib/ESP8266Audio/src/libmad/fixed.c b/lib_audio/ESP8266Audio/src/libmad/fixed.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/fixed.c rename to lib_audio/ESP8266Audio/src/libmad/fixed.c diff --git a/lib/ESP8266Audio/src/libmad/fixed.h b/lib_audio/ESP8266Audio/src/libmad/fixed.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/fixed.h rename to lib_audio/ESP8266Audio/src/libmad/fixed.h diff --git a/lib/ESP8266Audio/src/libmad/frame.c b/lib_audio/ESP8266Audio/src/libmad/frame.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/frame.c rename to lib_audio/ESP8266Audio/src/libmad/frame.c diff --git a/lib/ESP8266Audio/src/libmad/frame.h b/lib_audio/ESP8266Audio/src/libmad/frame.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/frame.h rename to lib_audio/ESP8266Audio/src/libmad/frame.h diff --git a/lib/ESP8266Audio/src/libmad/global.h b/lib_audio/ESP8266Audio/src/libmad/global.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/global.h rename to lib_audio/ESP8266Audio/src/libmad/global.h diff --git a/lib/ESP8266Audio/src/libmad/huffman.c b/lib_audio/ESP8266Audio/src/libmad/huffman.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/huffman.c rename to lib_audio/ESP8266Audio/src/libmad/huffman.c diff --git a/lib/ESP8266Audio/src/libmad/huffman.h b/lib_audio/ESP8266Audio/src/libmad/huffman.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/huffman.h rename to lib_audio/ESP8266Audio/src/libmad/huffman.h diff --git a/lib/ESP8266Audio/src/libmad/imdct_s.dat.h b/lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/imdct_s.dat.h rename to lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h diff --git a/lib/ESP8266Audio/src/libmad/layer3.c b/lib_audio/ESP8266Audio/src/libmad/layer3.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/layer3.c rename to lib_audio/ESP8266Audio/src/libmad/layer3.c diff --git a/lib/ESP8266Audio/src/libmad/layer3.h b/lib_audio/ESP8266Audio/src/libmad/layer3.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/layer3.h rename to lib_audio/ESP8266Audio/src/libmad/layer3.h diff --git a/lib/ESP8266Audio/src/libmad/mad.h b/lib_audio/ESP8266Audio/src/libmad/mad.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/mad.h rename to lib_audio/ESP8266Audio/src/libmad/mad.h diff --git a/lib/ESP8266Audio/src/libmad/mad.h.sed b/lib_audio/ESP8266Audio/src/libmad/mad.h.sed old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/mad.h.sed rename to lib_audio/ESP8266Audio/src/libmad/mad.h.sed diff --git a/lib/ESP8266Audio/src/libmad/qc_table.dat.h b/lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/qc_table.dat.h rename to lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h diff --git a/lib/ESP8266Audio/src/libmad/rq_table.dat.h b/lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/rq_table.dat.h rename to lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h diff --git a/lib/ESP8266Audio/src/libmad/sf_table.dat.h b/lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/sf_table.dat.h rename to lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h diff --git a/lib/ESP8266Audio/src/libmad/stream.c b/lib_audio/ESP8266Audio/src/libmad/stream.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/stream.c rename to lib_audio/ESP8266Audio/src/libmad/stream.c diff --git a/lib/ESP8266Audio/src/libmad/stream.h b/lib_audio/ESP8266Audio/src/libmad/stream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/stream.h rename to lib_audio/ESP8266Audio/src/libmad/stream.h diff --git a/lib/ESP8266Audio/src/libmad/synth.c b/lib_audio/ESP8266Audio/src/libmad/synth.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/synth.c rename to lib_audio/ESP8266Audio/src/libmad/synth.c diff --git a/lib/ESP8266Audio/src/libmad/synth.h b/lib_audio/ESP8266Audio/src/libmad/synth.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/synth.h rename to lib_audio/ESP8266Audio/src/libmad/synth.h diff --git a/lib/ESP8266Audio/src/libmad/timer.c b/lib_audio/ESP8266Audio/src/libmad/timer.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/timer.c rename to lib_audio/ESP8266Audio/src/libmad/timer.c diff --git a/lib/ESP8266Audio/src/libmad/timer.h b/lib_audio/ESP8266Audio/src/libmad/timer.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/timer.h rename to lib_audio/ESP8266Audio/src/libmad/timer.h diff --git a/lib/ESP8266Audio/src/libmad/version.c b/lib_audio/ESP8266Audio/src/libmad/version.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/version.c rename to lib_audio/ESP8266Audio/src/libmad/version.c diff --git a/lib/ESP8266Audio/src/libmad/version.h b/lib_audio/ESP8266Audio/src/libmad/version.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libmad/version.h rename to lib_audio/ESP8266Audio/src/libmad/version.h diff --git a/lib/ESP8266Audio/src/libogg/AUTHORS b/lib_audio/ESP8266Audio/src/libogg/AUTHORS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/AUTHORS rename to lib_audio/ESP8266Audio/src/libogg/AUTHORS diff --git a/lib/ESP8266Audio/src/libogg/CHANGES b/lib_audio/ESP8266Audio/src/libogg/CHANGES old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/CHANGES rename to lib_audio/ESP8266Audio/src/libogg/CHANGES diff --git a/lib/ESP8266Audio/src/libogg/COPYING b/lib_audio/ESP8266Audio/src/libogg/COPYING old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/COPYING rename to lib_audio/ESP8266Audio/src/libogg/COPYING diff --git a/lib/ESP8266Audio/src/libogg/README.esp8266.md b/lib_audio/ESP8266Audio/src/libogg/README.esp8266.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/README.esp8266.md rename to lib_audio/ESP8266Audio/src/libogg/README.esp8266.md diff --git a/lib/ESP8266Audio/src/libogg/README.md b/lib_audio/ESP8266Audio/src/libogg/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/README.md rename to lib_audio/ESP8266Audio/src/libogg/README.md diff --git a/lib/ESP8266Audio/src/libogg/bitwise.c b/lib_audio/ESP8266Audio/src/libogg/bitwise.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/bitwise.c rename to lib_audio/ESP8266Audio/src/libogg/bitwise.c diff --git a/lib/ESP8266Audio/src/libogg/config.h b/lib_audio/ESP8266Audio/src/libogg/config.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/config.h rename to lib_audio/ESP8266Audio/src/libogg/config.h diff --git a/lib/ESP8266Audio/src/libogg/crctable.h b/lib_audio/ESP8266Audio/src/libogg/crctable.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/crctable.h rename to lib_audio/ESP8266Audio/src/libogg/crctable.h diff --git a/lib/ESP8266Audio/src/libogg/framing.c b/lib_audio/ESP8266Audio/src/libogg/framing.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/framing.c rename to lib_audio/ESP8266Audio/src/libogg/framing.c diff --git a/lib/ESP8266Audio/src/libogg/ogg.pc b/lib_audio/ESP8266Audio/src/libogg/ogg.pc old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/ogg.pc rename to lib_audio/ESP8266Audio/src/libogg/ogg.pc diff --git a/lib/ESP8266Audio/src/libogg/ogg/config_types.h b/lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/ogg/config_types.h rename to lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h diff --git a/lib/ESP8266Audio/src/libogg/ogg/ogg.h b/lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/ogg/ogg.h rename to lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h diff --git a/lib/ESP8266Audio/src/libogg/ogg/os_types.h b/lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libogg/ogg/os_types.h rename to lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h diff --git a/lib/ESP8266Audio/src/libopus/AUTHORS b/lib_audio/ESP8266Audio/src/libopus/AUTHORS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/AUTHORS rename to lib_audio/ESP8266Audio/src/libopus/AUTHORS diff --git a/lib/ESP8266Audio/src/libopus/COPYING b/lib_audio/ESP8266Audio/src/libopus/COPYING old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/COPYING rename to lib_audio/ESP8266Audio/src/libopus/COPYING diff --git a/lib/ESP8266Audio/src/libopus/ChangeLog b/lib_audio/ESP8266Audio/src/libopus/ChangeLog old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/ChangeLog rename to lib_audio/ESP8266Audio/src/libopus/ChangeLog diff --git a/lib/ESP8266Audio/src/libopus/INSTALL b/lib_audio/ESP8266Audio/src/libopus/INSTALL old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/INSTALL rename to lib_audio/ESP8266Audio/src/libopus/INSTALL diff --git a/lib/ESP8266Audio/src/libopus/NEWS b/lib_audio/ESP8266Audio/src/libopus/NEWS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/NEWS rename to lib_audio/ESP8266Audio/src/libopus/NEWS diff --git a/lib/ESP8266Audio/src/libopus/README b/lib_audio/ESP8266Audio/src/libopus/README old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/README rename to lib_audio/ESP8266Audio/src/libopus/README diff --git a/lib/ESP8266Audio/src/libopus/analysis.h b/lib_audio/ESP8266Audio/src/libopus/analysis.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/analysis.h rename to lib_audio/ESP8266Audio/src/libopus/analysis.h diff --git a/lib/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h b/lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h rename to lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h diff --git a/lib/ESP8266Audio/src/libopus/celt/arch.h b/lib_audio/ESP8266Audio/src/libopus/celt/arch.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/arch.h rename to lib_audio/ESP8266Audio/src/libopus/celt/arch.h diff --git a/lib/ESP8266Audio/src/libopus/celt/bands.c b/lib_audio/ESP8266Audio/src/libopus/celt/bands.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/bands.c rename to lib_audio/ESP8266Audio/src/libopus/celt/bands.c diff --git a/lib/ESP8266Audio/src/libopus/celt/bands.h b/lib_audio/ESP8266Audio/src/libopus/celt/bands.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/bands.h rename to lib_audio/ESP8266Audio/src/libopus/celt/bands.h diff --git a/lib/ESP8266Audio/src/libopus/celt/celt.c b/lib_audio/ESP8266Audio/src/libopus/celt/celt.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt.c rename to lib_audio/ESP8266Audio/src/libopus/celt/celt.c diff --git a/lib/ESP8266Audio/src/libopus/celt/celt.h b/lib_audio/ESP8266Audio/src/libopus/celt/celt.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt.h rename to lib_audio/ESP8266Audio/src/libopus/celt/celt.h diff --git a/lib/ESP8266Audio/src/libopus/celt/celt_decoder.c b/lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt_decoder.c rename to lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c diff --git a/lib/ESP8266Audio/src/libopus/celt/celt_encoder.c b/lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt_encoder.c rename to lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c diff --git a/lib/ESP8266Audio/src/libopus/celt/celt_lpc.c b/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt_lpc.c rename to lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c diff --git a/lib/ESP8266Audio/src/libopus/celt/celt_lpc.h b/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/celt_lpc.h rename to lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h diff --git a/lib/ESP8266Audio/src/libopus/celt/cpu_support.h b/lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/cpu_support.h rename to lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h diff --git a/lib/ESP8266Audio/src/libopus/celt/cwrs.c b/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/cwrs.c rename to lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c diff --git a/lib/ESP8266Audio/src/libopus/celt/cwrs.h b/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/cwrs.h rename to lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h diff --git a/lib/ESP8266Audio/src/libopus/celt/ecintrin.h b/lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/ecintrin.h rename to lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h diff --git a/lib/ESP8266Audio/src/libopus/celt/entcode.c b/lib_audio/ESP8266Audio/src/libopus/celt/entcode.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entcode.c rename to lib_audio/ESP8266Audio/src/libopus/celt/entcode.c diff --git a/lib/ESP8266Audio/src/libopus/celt/entcode.h b/lib_audio/ESP8266Audio/src/libopus/celt/entcode.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entcode.h rename to lib_audio/ESP8266Audio/src/libopus/celt/entcode.h diff --git a/lib/ESP8266Audio/src/libopus/celt/entdec.c b/lib_audio/ESP8266Audio/src/libopus/celt/entdec.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entdec.c rename to lib_audio/ESP8266Audio/src/libopus/celt/entdec.c diff --git a/lib/ESP8266Audio/src/libopus/celt/entdec.h b/lib_audio/ESP8266Audio/src/libopus/celt/entdec.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entdec.h rename to lib_audio/ESP8266Audio/src/libopus/celt/entdec.h diff --git a/lib/ESP8266Audio/src/libopus/celt/entenc.c b/lib_audio/ESP8266Audio/src/libopus/celt/entenc.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entenc.c rename to lib_audio/ESP8266Audio/src/libopus/celt/entenc.c diff --git a/lib/ESP8266Audio/src/libopus/celt/entenc.h b/lib_audio/ESP8266Audio/src/libopus/celt/entenc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/entenc.h rename to lib_audio/ESP8266Audio/src/libopus/celt/entenc.h diff --git a/lib/ESP8266Audio/src/libopus/celt/fixed_debug.h b/lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/fixed_debug.h rename to lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h diff --git a/lib/ESP8266Audio/src/libopus/celt/fixed_generic.h b/lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/fixed_generic.h rename to lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h diff --git a/lib/ESP8266Audio/src/libopus/celt/float_cast.h b/lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/float_cast.h rename to lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h diff --git a/lib/ESP8266Audio/src/libopus/celt/kiss_fft.c b/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/kiss_fft.c rename to lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c diff --git a/lib/ESP8266Audio/src/libopus/celt/kiss_fft.h b/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/kiss_fft.h rename to lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h diff --git a/lib/ESP8266Audio/src/libopus/celt/laplace.c b/lib_audio/ESP8266Audio/src/libopus/celt/laplace.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/laplace.c rename to lib_audio/ESP8266Audio/src/libopus/celt/laplace.c diff --git a/lib/ESP8266Audio/src/libopus/celt/laplace.h b/lib_audio/ESP8266Audio/src/libopus/celt/laplace.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/laplace.h rename to lib_audio/ESP8266Audio/src/libopus/celt/laplace.h diff --git a/lib/ESP8266Audio/src/libopus/celt/mathops.c b/lib_audio/ESP8266Audio/src/libopus/celt/mathops.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/mathops.c rename to lib_audio/ESP8266Audio/src/libopus/celt/mathops.c diff --git a/lib/ESP8266Audio/src/libopus/celt/mathops.h b/lib_audio/ESP8266Audio/src/libopus/celt/mathops.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/mathops.h rename to lib_audio/ESP8266Audio/src/libopus/celt/mathops.h diff --git a/lib/ESP8266Audio/src/libopus/celt/mdct.c b/lib_audio/ESP8266Audio/src/libopus/celt/mdct.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/mdct.c rename to lib_audio/ESP8266Audio/src/libopus/celt/mdct.c diff --git a/lib/ESP8266Audio/src/libopus/celt/mdct.h b/lib_audio/ESP8266Audio/src/libopus/celt/mdct.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/mdct.h rename to lib_audio/ESP8266Audio/src/libopus/celt/mdct.h diff --git a/lib/ESP8266Audio/src/libopus/celt/mfrngcod.h b/lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/mfrngcod.h rename to lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h diff --git a/lib/ESP8266Audio/src/libopus/celt/modes.c b/lib_audio/ESP8266Audio/src/libopus/celt/modes.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/modes.c rename to lib_audio/ESP8266Audio/src/libopus/celt/modes.c diff --git a/lib/ESP8266Audio/src/libopus/celt/modes.h b/lib_audio/ESP8266Audio/src/libopus/celt/modes.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/modes.h rename to lib_audio/ESP8266Audio/src/libopus/celt/modes.h diff --git a/lib/ESP8266Audio/src/libopus/celt/os_support.h b/lib_audio/ESP8266Audio/src/libopus/celt/os_support.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/os_support.h rename to lib_audio/ESP8266Audio/src/libopus/celt/os_support.h diff --git a/lib/ESP8266Audio/src/libopus/celt/pitch.c b/lib_audio/ESP8266Audio/src/libopus/celt/pitch.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/pitch.c rename to lib_audio/ESP8266Audio/src/libopus/celt/pitch.c diff --git a/lib/ESP8266Audio/src/libopus/celt/pitch.h b/lib_audio/ESP8266Audio/src/libopus/celt/pitch.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/pitch.h rename to lib_audio/ESP8266Audio/src/libopus/celt/pitch.h diff --git a/lib/ESP8266Audio/src/libopus/celt/quant_bands.c b/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/quant_bands.c rename to lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c diff --git a/lib/ESP8266Audio/src/libopus/celt/quant_bands.h b/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/quant_bands.h rename to lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h diff --git a/lib/ESP8266Audio/src/libopus/celt/rate.c b/lib_audio/ESP8266Audio/src/libopus/celt/rate.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/rate.c rename to lib_audio/ESP8266Audio/src/libopus/celt/rate.c diff --git a/lib/ESP8266Audio/src/libopus/celt/rate.h b/lib_audio/ESP8266Audio/src/libopus/celt/rate.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/rate.h rename to lib_audio/ESP8266Audio/src/libopus/celt/rate.h diff --git a/lib/ESP8266Audio/src/libopus/celt/stack_alloc.h b/lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/stack_alloc.h rename to lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h diff --git a/lib/ESP8266Audio/src/libopus/celt/static_modes_fixed.h b/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/static_modes_fixed.h rename to lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h diff --git a/lib/ESP8266Audio/src/libopus/celt/static_modes_float.h b/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/static_modes_float.h rename to lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h diff --git a/lib/ESP8266Audio/src/libopus/celt/vq.c b/lib_audio/ESP8266Audio/src/libopus/celt/vq.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/vq.c rename to lib_audio/ESP8266Audio/src/libopus/celt/vq.c diff --git a/lib/ESP8266Audio/src/libopus/celt/vq.h b/lib_audio/ESP8266Audio/src/libopus/celt/vq.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/celt/vq.h rename to lib_audio/ESP8266Audio/src/libopus/celt/vq.h diff --git a/lib/ESP8266Audio/src/libopus/config.h b/lib_audio/ESP8266Audio/src/libopus/config.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/config.h rename to lib_audio/ESP8266Audio/src/libopus/config.h diff --git a/lib/ESP8266Audio/src/libopus/mapping_matrix.c b/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/mapping_matrix.c rename to lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c diff --git a/lib/ESP8266Audio/src/libopus/mapping_matrix.h b/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/mapping_matrix.h rename to lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h diff --git a/lib/ESP8266Audio/src/libopus/mlp.h b/lib_audio/ESP8266Audio/src/libopus/mlp.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/mlp.h rename to lib_audio/ESP8266Audio/src/libopus/mlp.h diff --git a/lib/ESP8266Audio/src/libopus/opus.c b/lib_audio/ESP8266Audio/src/libopus/opus.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus.c rename to lib_audio/ESP8266Audio/src/libopus/opus.c diff --git a/lib/ESP8266Audio/src/libopus/opus.h b/lib_audio/ESP8266Audio/src/libopus/opus.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus.h rename to lib_audio/ESP8266Audio/src/libopus/opus.h diff --git a/lib/ESP8266Audio/src/libopus/opus.pc b/lib_audio/ESP8266Audio/src/libopus/opus.pc old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus.pc rename to lib_audio/ESP8266Audio/src/libopus/opus.pc diff --git a/lib/ESP8266Audio/src/libopus/opus_custom.h b/lib_audio/ESP8266Audio/src/libopus/opus_custom.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_custom.h rename to lib_audio/ESP8266Audio/src/libopus/opus_custom.h diff --git a/lib/ESP8266Audio/src/libopus/opus_decoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_decoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_decoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_defines.h b/lib_audio/ESP8266Audio/src/libopus/opus_defines.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_defines.h rename to lib_audio/ESP8266Audio/src/libopus/opus_defines.h diff --git a/lib/ESP8266Audio/src/libopus/opus_encoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_encoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_encoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_encoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_multistream.c b/lib_audio/ESP8266Audio/src/libopus/opus_multistream.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_multistream.c rename to lib_audio/ESP8266Audio/src/libopus/opus_multistream.c diff --git a/lib/ESP8266Audio/src/libopus/opus_multistream.h b/lib_audio/ESP8266Audio/src/libopus/opus_multistream.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_multistream.h rename to lib_audio/ESP8266Audio/src/libopus/opus_multistream.h diff --git a/lib/ESP8266Audio/src/libopus/opus_multistream_decoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_multistream_decoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_multistream_encoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_multistream_encoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_private.h b/lib_audio/ESP8266Audio/src/libopus/opus_private.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_private.h rename to lib_audio/ESP8266Audio/src/libopus/opus_private.h diff --git a/lib/ESP8266Audio/src/libopus/opus_projection.h b/lib_audio/ESP8266Audio/src/libopus/opus_projection.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_projection.h rename to lib_audio/ESP8266Audio/src/libopus/opus_projection.h diff --git a/lib/ESP8266Audio/src/libopus/opus_projection_decoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_projection_decoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_projection_encoder.c b/lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_projection_encoder.c rename to lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c diff --git a/lib/ESP8266Audio/src/libopus/opus_types.h b/lib_audio/ESP8266Audio/src/libopus/opus_types.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/opus_types.h rename to lib_audio/ESP8266Audio/src/libopus/opus_types.h diff --git a/lib/ESP8266Audio/src/libopus/repacketizer.c b/lib_audio/ESP8266Audio/src/libopus/repacketizer.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/repacketizer.c rename to lib_audio/ESP8266Audio/src/libopus/repacketizer.c diff --git a/lib/ESP8266Audio/src/libopus/silk/A2NLSF.c b/lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/A2NLSF.c rename to lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c diff --git a/lib/ESP8266Audio/src/libopus/silk/API.h b/lib_audio/ESP8266Audio/src/libopus/silk/API.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/API.h rename to lib_audio/ESP8266Audio/src/libopus/silk/API.h diff --git a/lib/ESP8266Audio/src/libopus/silk/CNG.c b/lib_audio/ESP8266Audio/src/libopus/silk/CNG.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/CNG.c rename to lib_audio/ESP8266Audio/src/libopus/silk/CNG.c diff --git a/lib/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c b/lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c rename to lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c diff --git a/lib/ESP8266Audio/src/libopus/silk/Inlines.h b/lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/Inlines.h rename to lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h diff --git a/lib/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c b/lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c rename to lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c diff --git a/lib/ESP8266Audio/src/libopus/silk/LPC_fit.c b/lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/LPC_fit.c rename to lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c diff --git a/lib/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c b/lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c rename to lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c diff --git a/lib/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c b/lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c rename to lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c diff --git a/lib/ESP8266Audio/src/libopus/silk/MacroCount.h b/lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/MacroCount.h rename to lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h diff --git a/lib/ESP8266Audio/src/libopus/silk/MacroDebug.h b/lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/MacroDebug.h rename to lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF2A.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF2A.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_VQ.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_VQ.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_decode.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_decode.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_encode.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_encode.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NLSF_unpack.c b/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NLSF_unpack.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NSQ.c b/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NSQ.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c diff --git a/lib/ESP8266Audio/src/libopus/silk/NSQ.h b/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NSQ.h rename to lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h diff --git a/lib/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c b/lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c rename to lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c diff --git a/lib/ESP8266Audio/src/libopus/silk/PLC.c b/lib_audio/ESP8266Audio/src/libopus/silk/PLC.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/PLC.c rename to lib_audio/ESP8266Audio/src/libopus/silk/PLC.c diff --git a/lib/ESP8266Audio/src/libopus/silk/PLC.h b/lib_audio/ESP8266Audio/src/libopus/silk/PLC.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/PLC.h rename to lib_audio/ESP8266Audio/src/libopus/silk/PLC.h diff --git a/lib/ESP8266Audio/src/libopus/silk/SigProc_FIX.h b/lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/SigProc_FIX.h rename to lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h diff --git a/lib/ESP8266Audio/src/libopus/silk/VAD.c b/lib_audio/ESP8266Audio/src/libopus/silk/VAD.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/VAD.c rename to lib_audio/ESP8266Audio/src/libopus/silk/VAD.c diff --git a/lib/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c b/lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c rename to lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c diff --git a/lib/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c b/lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c rename to lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c diff --git a/lib/ESP8266Audio/src/libopus/silk/biquad_alt.c b/lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/biquad_alt.c rename to lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c diff --git a/lib/ESP8266Audio/src/libopus/silk/bwexpander.c b/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/bwexpander.c rename to lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c diff --git a/lib/ESP8266Audio/src/libopus/silk/bwexpander_32.c b/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/bwexpander_32.c rename to lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c diff --git a/lib/ESP8266Audio/src/libopus/silk/check_control_input.c b/lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/check_control_input.c rename to lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c diff --git a/lib/ESP8266Audio/src/libopus/silk/code_signs.c b/lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/code_signs.c rename to lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c diff --git a/lib/ESP8266Audio/src/libopus/silk/control.h b/lib_audio/ESP8266Audio/src/libopus/silk/control.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/control.h rename to lib_audio/ESP8266Audio/src/libopus/silk/control.h diff --git a/lib/ESP8266Audio/src/libopus/silk/control_SNR.c b/lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/control_SNR.c rename to lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c diff --git a/lib/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c b/lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c rename to lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c diff --git a/lib/ESP8266Audio/src/libopus/silk/control_codec.c b/lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/control_codec.c rename to lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c diff --git a/lib/ESP8266Audio/src/libopus/silk/debug.c b/lib_audio/ESP8266Audio/src/libopus/silk/debug.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/debug.c rename to lib_audio/ESP8266Audio/src/libopus/silk/debug.c diff --git a/lib/ESP8266Audio/src/libopus/silk/debug.h b/lib_audio/ESP8266Audio/src/libopus/silk/debug.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/debug.h rename to lib_audio/ESP8266Audio/src/libopus/silk/debug.h diff --git a/lib/ESP8266Audio/src/libopus/silk/dec_API.c b/lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/dec_API.c rename to lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_core.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_core.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_frame.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_frame.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_indices.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_indices.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_parameters.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_parameters.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_pitch.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_pitch.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decode_pulses.c b/lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decode_pulses.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c diff --git a/lib/ESP8266Audio/src/libopus/silk/decoder_set_fs.c b/lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/decoder_set_fs.c rename to lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c diff --git a/lib/ESP8266Audio/src/libopus/silk/define.h b/lib_audio/ESP8266Audio/src/libopus/silk/define.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/define.h rename to lib_audio/ESP8266Audio/src/libopus/silk/define.h diff --git a/lib/ESP8266Audio/src/libopus/silk/enc_API.c b/lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/enc_API.c rename to lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c diff --git a/lib/ESP8266Audio/src/libopus/silk/encode_indices.c b/lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/encode_indices.c rename to lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c diff --git a/lib/ESP8266Audio/src/libopus/silk/encode_pulses.c b/lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/encode_pulses.c rename to lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c diff --git a/lib/ESP8266Audio/src/libopus/silk/errors.h b/lib_audio/ESP8266Audio/src/libopus/silk/errors.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/errors.h rename to lib_audio/ESP8266Audio/src/libopus/silk/errors.h diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo diff --git a/lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o b/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o rename to lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o diff --git a/lib/ESP8266Audio/src/libopus/silk/gain_quant.c b/lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/gain_quant.c rename to lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c diff --git a/lib/ESP8266Audio/src/libopus/silk/init_decoder.c b/lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/init_decoder.c rename to lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c diff --git a/lib/ESP8266Audio/src/libopus/silk/init_encoder.c b/lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/init_encoder.c rename to lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c diff --git a/lib/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c b/lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c rename to lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c diff --git a/lib/ESP8266Audio/src/libopus/silk/interpolate.c b/lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/interpolate.c rename to lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c diff --git a/lib/ESP8266Audio/src/libopus/silk/lin2log.c b/lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/lin2log.c rename to lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c diff --git a/lib/ESP8266Audio/src/libopus/silk/log2lin.c b/lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/log2lin.c rename to lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c diff --git a/lib/ESP8266Audio/src/libopus/silk/macros.h b/lib_audio/ESP8266Audio/src/libopus/silk/macros.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/macros.h rename to lib_audio/ESP8266Audio/src/libopus/silk/macros.h diff --git a/lib/ESP8266Audio/src/libopus/silk/main.h b/lib_audio/ESP8266Audio/src/libopus/silk/main.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/main.h rename to lib_audio/ESP8266Audio/src/libopus/silk/main.h diff --git a/lib/ESP8266Audio/src/libopus/silk/pitch_est_defines.h b/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/pitch_est_defines.h rename to lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h diff --git a/lib/ESP8266Audio/src/libopus/silk/pitch_est_tables.c b/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/pitch_est_tables.c rename to lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c diff --git a/lib/ESP8266Audio/src/libopus/silk/process_NLSFs.c b/lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/process_NLSFs.c rename to lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c diff --git a/lib/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c b/lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c rename to lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_down2.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_down2.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_down2_3.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_down2_3.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_private.h b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_private.h rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_rom.c b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_rom.c rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_rom.h b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_rom.h rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h diff --git a/lib/ESP8266Audio/src/libopus/silk/resampler_structs.h b/lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/resampler_structs.h rename to lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h diff --git a/lib/ESP8266Audio/src/libopus/silk/shell_coder.c b/lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/shell_coder.c rename to lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c diff --git a/lib/ESP8266Audio/src/libopus/silk/sigm_Q15.c b/lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/sigm_Q15.c rename to lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c diff --git a/lib/ESP8266Audio/src/libopus/silk/sort.c b/lib_audio/ESP8266Audio/src/libopus/silk/sort.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/sort.c rename to lib_audio/ESP8266Audio/src/libopus/silk/sort.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c diff --git a/lib/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c b/lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c rename to lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c diff --git a/lib/ESP8266Audio/src/libopus/silk/structs.h b/lib_audio/ESP8266Audio/src/libopus/silk/structs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/structs.h rename to lib_audio/ESP8266Audio/src/libopus/silk/structs.h diff --git a/lib/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c b/lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c rename to lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c diff --git a/lib/ESP8266Audio/src/libopus/silk/table_LSF_cos.c b/lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/table_LSF_cos.c rename to lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables.h b/lib_audio/ESP8266Audio/src/libopus/silk/tables.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables.h rename to lib_audio/ESP8266Audio/src/libopus/silk/tables.h diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_LTP.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_LTP.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_gain.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_gain.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_other.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_other.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c b/lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c rename to lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c diff --git a/lib/ESP8266Audio/src/libopus/silk/tuning_parameters.h b/lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/tuning_parameters.h rename to lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h diff --git a/lib/ESP8266Audio/src/libopus/silk/typedef.h b/lib_audio/ESP8266Audio/src/libopus/silk/typedef.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/silk/typedef.h rename to lib_audio/ESP8266Audio/src/libopus/silk/typedef.h diff --git a/lib/ESP8266Audio/src/libopus/tansig_table.h b/lib_audio/ESP8266Audio/src/libopus/tansig_table.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libopus/tansig_table.h rename to lib_audio/ESP8266Audio/src/libopus/tansig_table.h diff --git a/lib/ESP8266Audio/src/libtinysoundfont/LICENSE b/lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libtinysoundfont/LICENSE rename to lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE diff --git a/lib/ESP8266Audio/src/libtinysoundfont/README.ESP8266 b/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libtinysoundfont/README.ESP8266 rename to lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 diff --git a/lib/ESP8266Audio/src/libtinysoundfont/README.md b/lib_audio/ESP8266Audio/src/libtinysoundfont/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libtinysoundfont/README.md rename to lib_audio/ESP8266Audio/src/libtinysoundfont/README.md diff --git a/lib/ESP8266Audio/src/libtinysoundfont/tsf.h b/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/libtinysoundfont/tsf.h rename to lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h diff --git a/lib/ESP8266Audio/src/opusfile/AUTHORS b/lib_audio/ESP8266Audio/src/opusfile/AUTHORS old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/AUTHORS rename to lib_audio/ESP8266Audio/src/opusfile/AUTHORS diff --git a/lib/ESP8266Audio/src/opusfile/COPYING b/lib_audio/ESP8266Audio/src/opusfile/COPYING old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/COPYING rename to lib_audio/ESP8266Audio/src/opusfile/COPYING diff --git a/lib/ESP8266Audio/src/opusfile/README.esp8266.md b/lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/README.esp8266.md rename to lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md diff --git a/lib/ESP8266Audio/src/opusfile/README.md b/lib_audio/ESP8266Audio/src/opusfile/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/README.md rename to lib_audio/ESP8266Audio/src/opusfile/README.md diff --git a/lib/ESP8266Audio/src/opusfile/config.h b/lib_audio/ESP8266Audio/src/opusfile/config.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/config.h rename to lib_audio/ESP8266Audio/src/opusfile/config.h diff --git a/lib/ESP8266Audio/src/opusfile/info.c b/lib_audio/ESP8266Audio/src/opusfile/info.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/info.c rename to lib_audio/ESP8266Audio/src/opusfile/info.c diff --git a/lib/ESP8266Audio/src/opusfile/internal.c b/lib_audio/ESP8266Audio/src/opusfile/internal.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/internal.c rename to lib_audio/ESP8266Audio/src/opusfile/internal.c diff --git a/lib/ESP8266Audio/src/opusfile/internal.h b/lib_audio/ESP8266Audio/src/opusfile/internal.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/internal.h rename to lib_audio/ESP8266Audio/src/opusfile/internal.h diff --git a/lib/ESP8266Audio/src/opusfile/opusfile.c b/lib_audio/ESP8266Audio/src/opusfile/opusfile.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/opusfile.c rename to lib_audio/ESP8266Audio/src/opusfile/opusfile.c diff --git a/lib/ESP8266Audio/src/opusfile/opusfile.h b/lib_audio/ESP8266Audio/src/opusfile/opusfile.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/opusfile.h rename to lib_audio/ESP8266Audio/src/opusfile/opusfile.h diff --git a/lib/ESP8266Audio/src/opusfile/opusfile.pc b/lib_audio/ESP8266Audio/src/opusfile/opusfile.pc old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/opusfile.pc rename to lib_audio/ESP8266Audio/src/opusfile/opusfile.pc diff --git a/lib/ESP8266Audio/src/opusfile/stream.c b/lib_audio/ESP8266Audio/src/opusfile/stream.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/opusfile/stream.c rename to lib_audio/ESP8266Audio/src/opusfile/stream.c diff --git a/lib/ESP8266Audio/src/spiram-fast.h b/lib_audio/ESP8266Audio/src/spiram-fast.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/src/spiram-fast.h rename to lib_audio/ESP8266Audio/src/spiram-fast.h diff --git a/lib/ESP8266Audio/tests/common.sh b/lib_audio/ESP8266Audio/tests/common.sh old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/common.sh rename to lib_audio/ESP8266Audio/tests/common.sh diff --git a/lib/ESP8266Audio/tests/host/Arduino.h b/lib_audio/ESP8266Audio/tests/host/Arduino.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/Arduino.h rename to lib_audio/ESP8266Audio/tests/host/Arduino.h diff --git a/lib/ESP8266Audio/tests/host/Makefile b/lib_audio/ESP8266Audio/tests/host/Makefile old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/Makefile rename to lib_audio/ESP8266Audio/tests/host/Makefile diff --git a/lib/ESP8266Audio/tests/host/Serial.cpp b/lib_audio/ESP8266Audio/tests/host/Serial.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/Serial.cpp rename to lib_audio/ESP8266Audio/tests/host/Serial.cpp diff --git a/lib/ESP8266Audio/tests/host/aac.cpp b/lib_audio/ESP8266Audio/tests/host/aac.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/aac.cpp rename to lib_audio/ESP8266Audio/tests/host/aac.cpp diff --git a/lib/ESP8266Audio/tests/host/midi.cpp b/lib_audio/ESP8266Audio/tests/host/midi.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/midi.cpp rename to lib_audio/ESP8266Audio/tests/host/midi.cpp diff --git a/lib/ESP8266Audio/tests/host/mp3.cpp b/lib_audio/ESP8266Audio/tests/host/mp3.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/mp3.cpp rename to lib_audio/ESP8266Audio/tests/host/mp3.cpp diff --git a/lib/ESP8266Audio/tests/host/opus.cpp b/lib_audio/ESP8266Audio/tests/host/opus.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/opus.cpp rename to lib_audio/ESP8266Audio/tests/host/opus.cpp diff --git a/lib/ESP8266Audio/tests/host/pgmspace.h b/lib_audio/ESP8266Audio/tests/host/pgmspace.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/pgmspace.h rename to lib_audio/ESP8266Audio/tests/host/pgmspace.h diff --git a/lib/ESP8266Audio/tests/host/test_8u_16.wav b/lib_audio/ESP8266Audio/tests/host/test_8u_16.wav old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/test_8u_16.wav rename to lib_audio/ESP8266Audio/tests/host/test_8u_16.wav diff --git a/lib/ESP8266Audio/tests/host/wav.cpp b/lib_audio/ESP8266Audio/tests/host/wav.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266Audio/tests/host/wav.cpp rename to lib_audio/ESP8266Audio/tests/host/wav.cpp diff --git a/lib/ESP8266SAM/README.md b/lib_audio/ESP8266SAM/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/README.md rename to lib_audio/ESP8266SAM/README.md diff --git a/lib/ESP8266SAM/examples/Speak/Speak.ino b/lib_audio/ESP8266SAM/examples/Speak/Speak.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/examples/Speak/Speak.ino rename to lib_audio/ESP8266SAM/examples/Speak/Speak.ino diff --git a/lib/ESP8266SAM/library.json b/lib_audio/ESP8266SAM/library.json old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/library.json rename to lib_audio/ESP8266SAM/library.json diff --git a/lib/ESP8266SAM/library.properties b/lib_audio/ESP8266SAM/library.properties old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/library.properties rename to lib_audio/ESP8266SAM/library.properties diff --git a/lib/ESP8266SAM/src/ESP8266SAM.cpp b/lib_audio/ESP8266SAM/src/ESP8266SAM.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/ESP8266SAM.cpp rename to lib_audio/ESP8266SAM/src/ESP8266SAM.cpp diff --git a/lib/ESP8266SAM/src/ESP8266SAM.h b/lib_audio/ESP8266SAM/src/ESP8266SAM.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/ESP8266SAM.h rename to lib_audio/ESP8266SAM/src/ESP8266SAM.h diff --git a/lib/ESP8266SAM/src/ReciterTabs.h b/lib_audio/ESP8266SAM/src/ReciterTabs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/ReciterTabs.h rename to lib_audio/ESP8266SAM/src/ReciterTabs.h diff --git a/lib/ESP8266SAM/src/RenderTabs.h b/lib_audio/ESP8266SAM/src/RenderTabs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/RenderTabs.h rename to lib_audio/ESP8266SAM/src/RenderTabs.h diff --git a/lib/ESP8266SAM/src/SamData.h b/lib_audio/ESP8266SAM/src/SamData.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/SamData.h rename to lib_audio/ESP8266SAM/src/SamData.h diff --git a/lib/ESP8266SAM/src/SamTabs.h b/lib_audio/ESP8266SAM/src/SamTabs.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/SamTabs.h rename to lib_audio/ESP8266SAM/src/SamTabs.h diff --git a/lib/ESP8266SAM/src/reciter.c b/lib_audio/ESP8266SAM/src/reciter.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/reciter.c rename to lib_audio/ESP8266SAM/src/reciter.c diff --git a/lib/ESP8266SAM/src/reciter.h b/lib_audio/ESP8266SAM/src/reciter.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/reciter.h rename to lib_audio/ESP8266SAM/src/reciter.h diff --git a/lib/ESP8266SAM/src/render.c b/lib_audio/ESP8266SAM/src/render.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/render.c rename to lib_audio/ESP8266SAM/src/render.c diff --git a/lib/ESP8266SAM/src/render.h b/lib_audio/ESP8266SAM/src/render.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/render.h rename to lib_audio/ESP8266SAM/src/render.h diff --git a/lib/ESP8266SAM/src/sam.c b/lib_audio/ESP8266SAM/src/sam.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/sam.c rename to lib_audio/ESP8266SAM/src/sam.c diff --git a/lib/ESP8266SAM/src/sam.h b/lib_audio/ESP8266SAM/src/sam.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/sam.h rename to lib_audio/ESP8266SAM/src/sam.h diff --git a/lib/ESP8266SAM/src/samdebug.c b/lib_audio/ESP8266SAM/src/samdebug.c old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/samdebug.c rename to lib_audio/ESP8266SAM/src/samdebug.c diff --git a/lib/ESP8266SAM/src/samdebug.h b/lib_audio/ESP8266SAM/src/samdebug.h old mode 100755 new mode 100644 similarity index 100% rename from lib/ESP8266SAM/src/samdebug.h rename to lib_audio/ESP8266SAM/src/samdebug.h diff --git a/lib/C2Programmer-1.0.0/README.md b/lib_basic/C2Programmer-1.0.0/README.md similarity index 100% rename from lib/C2Programmer-1.0.0/README.md rename to lib_basic/C2Programmer-1.0.0/README.md diff --git a/lib/C2Programmer-1.0.0/keywords.txt b/lib_basic/C2Programmer-1.0.0/keywords.txt similarity index 100% rename from lib/C2Programmer-1.0.0/keywords.txt rename to lib_basic/C2Programmer-1.0.0/keywords.txt diff --git a/lib/C2Programmer-1.0.0/library.json b/lib_basic/C2Programmer-1.0.0/library.json similarity index 100% rename from lib/C2Programmer-1.0.0/library.json rename to lib_basic/C2Programmer-1.0.0/library.json diff --git a/lib/C2Programmer-1.0.0/library.properties b/lib_basic/C2Programmer-1.0.0/library.properties similarity index 100% rename from lib/C2Programmer-1.0.0/library.properties rename to lib_basic/C2Programmer-1.0.0/library.properties diff --git a/lib/C2Programmer-1.0.0/src/c2.cpp b/lib_basic/C2Programmer-1.0.0/src/c2.cpp similarity index 100% rename from lib/C2Programmer-1.0.0/src/c2.cpp rename to lib_basic/C2Programmer-1.0.0/src/c2.cpp diff --git a/lib/C2Programmer-1.0.0/src/c2.h b/lib_basic/C2Programmer-1.0.0/src/c2.h similarity index 100% rename from lib/C2Programmer-1.0.0/src/c2.h rename to lib_basic/C2Programmer-1.0.0/src/c2.h diff --git a/lib/C2Programmer-1.0.0/src/ihx.cpp b/lib_basic/C2Programmer-1.0.0/src/ihx.cpp similarity index 100% rename from lib/C2Programmer-1.0.0/src/ihx.cpp rename to lib_basic/C2Programmer-1.0.0/src/ihx.cpp diff --git a/lib/C2Programmer-1.0.0/src/ihx.h b/lib_basic/C2Programmer-1.0.0/src/ihx.h similarity index 100% rename from lib/C2Programmer-1.0.0/src/ihx.h rename to lib_basic/C2Programmer-1.0.0/src/ihx.h diff --git a/lib/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md b/lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md rename to lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md diff --git a/lib/IRremoteESP8266-2.7.11/.github/Contributors.md b/lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.github/Contributors.md rename to lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md diff --git a/lib/IRremoteESP8266-2.7.11/.github/issue_template.md b/lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.github/issue_template.md rename to lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md diff --git a/lib/IRremoteESP8266-2.7.11/.gitignore b/lib_basic/IRremoteESP8266-2.7.11/.gitignore similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.gitignore rename to lib_basic/IRremoteESP8266-2.7.11/.gitignore diff --git a/lib/IRremoteESP8266-2.7.11/.gitmodules b/lib_basic/IRremoteESP8266-2.7.11/.gitmodules similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.gitmodules rename to lib_basic/IRremoteESP8266-2.7.11/.gitmodules diff --git a/lib/IRremoteESP8266-2.7.11/.style.yapf b/lib_basic/IRremoteESP8266-2.7.11/.style.yapf similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.style.yapf rename to lib_basic/IRremoteESP8266-2.7.11/.style.yapf diff --git a/lib/IRremoteESP8266-2.7.11/.travis.yml b/lib_basic/IRremoteESP8266-2.7.11/.travis.yml similarity index 100% rename from lib/IRremoteESP8266-2.7.11/.travis.yml rename to lib_basic/IRremoteESP8266-2.7.11/.travis.yml diff --git a/lib/IRremoteESP8266-2.7.11/CPPLINT.cfg b/lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/CPPLINT.cfg rename to lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.11/Doxyfile b/lib_basic/IRremoteESP8266-2.7.11/Doxyfile similarity index 100% rename from lib/IRremoteESP8266-2.7.11/Doxyfile rename to lib_basic/IRremoteESP8266-2.7.11/Doxyfile diff --git a/lib/IRremoteESP8266-2.7.11/LICENSE.txt b/lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.7.11/LICENSE.txt rename to lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.7.11/README.md b/lib_basic/IRremoteESP8266-2.7.11/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/README.md rename to lib_basic/IRremoteESP8266-2.7.11/README.md diff --git a/lib/IRremoteESP8266-2.7.11/README_fr.md b/lib_basic/IRremoteESP8266-2.7.11/README_fr.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/README_fr.md rename to lib_basic/IRremoteESP8266-2.7.11/README_fr.md diff --git a/lib/IRremoteESP8266-2.7.11/ReleaseNotes.md b/lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/ReleaseNotes.md rename to lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md diff --git a/lib/IRremoteESP8266-2.7.11/SupportedProtocols.md b/lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/SupportedProtocols.md rename to lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md diff --git a/lib/IRremoteESP8266-2.7.11/docs/README.md b/lib_basic/IRremoteESP8266-2.7.11/docs/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/README.md rename to lib_basic/IRremoteESP8266-2.7.11/docs/README.md diff --git a/lib/IRremoteESP8266-2.7.11/docs/README_fr.md b/lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/README_fr.md rename to lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md diff --git a/lib/IRremoteESP8266-2.7.11/docs/_config.yml b/lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/_config.yml rename to lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html diff --git a/lib/IRremoteESP8266-2.7.11/docs/doxygen_index.md b/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/docs/doxygen_index.md rename to lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md diff --git a/lib/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h b/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png b/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png similarity index 100% rename from lib/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png rename to lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png diff --git a/lib/IRremoteESP8266-2.7.11/keywords.txt b/lib_basic/IRremoteESP8266-2.7.11/keywords.txt similarity index 100% rename from lib/IRremoteESP8266-2.7.11/keywords.txt rename to lib_basic/IRremoteESP8266-2.7.11/keywords.txt diff --git a/lib/IRremoteESP8266-2.7.11/library.json b/lib_basic/IRremoteESP8266-2.7.11/library.json similarity index 100% rename from lib/IRremoteESP8266-2.7.11/library.json rename to lib_basic/IRremoteESP8266-2.7.11/library.json diff --git a/lib/IRremoteESP8266-2.7.11/library.properties b/lib_basic/IRremoteESP8266-2.7.11/library.properties similarity index 100% rename from lib/IRremoteESP8266-2.7.11/library.properties rename to lib_basic/IRremoteESP8266-2.7.11/library.properties diff --git a/lib/IRremoteESP8266-2.7.11/platformio.ini b/lib_basic/IRremoteESP8266-2.7.11/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.11/platformio.ini rename to lib_basic/IRremoteESP8266-2.7.11/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.11/pylintrc b/lib_basic/IRremoteESP8266-2.7.11/pylintrc similarity index 100% rename from lib/IRremoteESP8266-2.7.11/pylintrc rename to lib_basic/IRremoteESP8266-2.7.11/pylintrc diff --git a/lib/IRremoteESP8266-2.7.11/src/CPPLINT.cfg b/lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/CPPLINT.cfg rename to lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.11/src/IRac.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRac.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRac.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRac.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRac.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRac.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRrecv.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRrecv.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRrecv.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRrecv.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRsend.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRsend.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRsend.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRsend.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRtext.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRtext.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRtext.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRtext.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRtimer.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRtimer.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRtimer.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRtimer.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h diff --git a/lib/IRremoteESP8266-2.7.11/src/IRutils.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRutils.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/IRutils.h b/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/IRutils.h rename to lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h diff --git a/lib/IRremoteESP8266-2.7.11/src/i18n.h b/lib_basic/IRremoteESP8266-2.7.11/src/i18n.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/i18n.h rename to lib_basic/IRremoteESP8266-2.7.11/src/i18n.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Airwell.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Airwell.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Amcor.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Amcor.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Argo.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Argo.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Argo.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Argo.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Carrier.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Carrier.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Coolix.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Coolix.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Corona.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Corona.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Corona.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Corona.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Daikin.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Daikin.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Delonghi.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Delonghi.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Denon.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Denon.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Dish.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Dish.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Electra.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Electra.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Electra.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Electra.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Epson.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Epson.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_GICable.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_GICable.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Goodweather.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Goodweather.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Gree.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Gree.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Gree.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Gree.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Haier.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Haier.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Haier.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Haier.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Hitachi.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Hitachi.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Inax.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Inax.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_JVC.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_JVC.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_LG.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_LG.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_LG.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_LG.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Lego.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Lego.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_MWM.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_MWM.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Magiquest.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Magiquest.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Metz.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Metz.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Midea.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Midea.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Midea.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Midea.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_NEC.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_NEC.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_NEC.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_NEC.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Neoclima.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Neoclima.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Panasonic.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Panasonic.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Samsung.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Samsung.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sanyo.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sanyo.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sharp.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sharp.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Sony.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Sony.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Tcl.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Tcl.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Technibel.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Technibel.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Teco.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Teco.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Teco.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Teco.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Toshiba.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Toshiba.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Transcold.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Transcold.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Trotec.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Trotec.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Vestel.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Vestel.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Voltas.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Voltas.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp b/lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp rename to lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/README.md b/lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/README.md rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/de-CH.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/de-CH.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/de-DE.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/de-DE.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/defaults.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/defaults.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/en-AU.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/en-AU.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/en-IE.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/en-IE.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/en-UK.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/en-UK.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/en-US.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/en-US.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/es-ES.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/es-ES.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/fr-FR.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/fr-FR.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/it-IT.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/it-IT.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h diff --git a/lib/IRremoteESP8266-2.7.11/src/locale/zh-CN.h b/lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/src/locale/zh-CN.h rename to lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h diff --git a/lib/IRremoteESP8266-2.7.11/test/IRac_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRac_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/IRrecv_test.h b/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRrecv_test.h rename to lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h diff --git a/lib/IRremoteESP8266-2.7.11/test/IRsend_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRsend_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/IRsend_test.h b/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRsend_test.h rename to lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h diff --git a/lib/IRremoteESP8266-2.7.11/test/IRutils_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/IRutils_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/Makefile b/lib_basic/IRremoteESP8266-2.7.11/test/Makefile similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/Makefile rename to lib_basic/IRremoteESP8266-2.7.11/test/Makefile diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp b/lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp rename to lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp diff --git a/lib/IRremoteESP8266-2.7.11/tools/Makefile b/lib_basic/IRremoteESP8266-2.7.11/tools/Makefile similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/Makefile rename to lib_basic/IRremoteESP8266-2.7.11/tools/Makefile diff --git a/lib/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh b/lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh rename to lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh diff --git a/lib/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py b/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py rename to lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py diff --git a/lib/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py b/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py rename to lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py diff --git a/lib/IRremoteESP8266-2.7.11/tools/gc_decode.cpp b/lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/gc_decode.cpp rename to lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp diff --git a/lib/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh b/lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh rename to lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh diff --git a/lib/IRremoteESP8266-2.7.11/tools/mkkeywords b/lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/mkkeywords rename to lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords diff --git a/lib/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp b/lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp rename to lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp diff --git a/lib/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py b/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py rename to lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py diff --git a/lib/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py b/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py rename to lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py diff --git a/lib/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py b/lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py similarity index 100% rename from lib/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py rename to lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py diff --git a/lib/NeoPixelBus-2.6.0/.gitattributes b/lib_basic/NeoPixelBus-2.6.0/.gitattributes similarity index 100% rename from lib/NeoPixelBus-2.6.0/.gitattributes rename to lib_basic/NeoPixelBus-2.6.0/.gitattributes diff --git a/lib/NeoPixelBus-2.6.0/.github/FUNDING.yml b/lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml similarity index 100% rename from lib/NeoPixelBus-2.6.0/.github/FUNDING.yml rename to lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml diff --git a/lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md b/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md similarity index 100% rename from lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md rename to lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md diff --git a/lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md b/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md rename to lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md b/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md similarity index 100% rename from lib/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md rename to lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md diff --git a/lib/NeoPixelBus-2.6.0/.gitignore b/lib_basic/NeoPixelBus-2.6.0/.gitignore similarity index 100% rename from lib/NeoPixelBus-2.6.0/.gitignore rename to lib_basic/NeoPixelBus-2.6.0/.gitignore diff --git a/lib/NeoPixelBus-2.6.0/COPYING b/lib_basic/NeoPixelBus-2.6.0/COPYING similarity index 100% rename from lib/NeoPixelBus-2.6.0/COPYING rename to lib_basic/NeoPixelBus-2.6.0/COPYING diff --git a/lib/NeoPixelBus-2.6.0/ReadMe.md b/lib_basic/NeoPixelBus-2.6.0/ReadMe.md similarity index 100% rename from lib/NeoPixelBus-2.6.0/ReadMe.md rename to lib_basic/NeoPixelBus-2.6.0/ReadMe.md diff --git a/lib/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino b/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino b/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino b/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino b/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino diff --git a/lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino b/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino similarity index 100% rename from lib/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino rename to lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/circular.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/circular.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/cubic.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/cubic.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/different.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/different.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/exponential.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/exponential.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/gamma.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/gamma.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/pronounced.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/pronounced.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/quadratic.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/quadratic.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/quintic.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/quintic.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png diff --git a/lib/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png b/lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png similarity index 100% rename from lib/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png rename to lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png diff --git a/lib/NeoPixelBus-2.6.0/keywords.txt b/lib_basic/NeoPixelBus-2.6.0/keywords.txt similarity index 100% rename from lib/NeoPixelBus-2.6.0/keywords.txt rename to lib_basic/NeoPixelBus-2.6.0/keywords.txt diff --git a/lib/NeoPixelBus-2.6.0/library.json b/lib_basic/NeoPixelBus-2.6.0/library.json similarity index 100% rename from lib/NeoPixelBus-2.6.0/library.json rename to lib_basic/NeoPixelBus-2.6.0/library.json diff --git a/lib/NeoPixelBus-2.6.0/library.properties b/lib_basic/NeoPixelBus-2.6.0/library.properties similarity index 100% rename from lib/NeoPixelBus-2.6.0/library.properties rename to lib_basic/NeoPixelBus-2.6.0/library.properties diff --git a/lib/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h b/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h rename to lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h diff --git a/lib/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h b/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h rename to lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h diff --git a/lib/NeoPixelBus-2.6.0/src/NeoPixelBus.h b/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/NeoPixelBus.h rename to lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h diff --git a/lib/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h b/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h rename to lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c b/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HsbColor.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HsbColor.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HslColor.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HslColor.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HslColor.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HslColor.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColor.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColor.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Layouts.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Layouts.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoDib.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoDib.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEase.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEase.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoGamma.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoGamma.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoSettings.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoSettings.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoTiles.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoTiles.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/NeoTopology.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/NeoTopology.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/RgbColor.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/RgbColor.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/RgbwColor.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/RgbwColor.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp b/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp rename to lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp diff --git a/lib/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h diff --git a/lib/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h b/lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h similarity index 100% rename from lib/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h rename to lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp b/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/OneWire.h b/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/OneWire.h rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/README.md b/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/README.md rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde b/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde b/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/keywords.txt b/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/keywords.txt rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/library.json b/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/library.json rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json diff --git a/lib/OneWire-Stickbreaker-20190506-1.1/library.properties b/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties similarity index 100% rename from lib/OneWire-Stickbreaker-20190506-1.1/library.properties rename to lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties diff --git a/lib/TasmotaModbus-1.2.0/README.md b/lib_basic/TasmotaModbus-1.2.0/README.md similarity index 100% rename from lib/TasmotaModbus-1.2.0/README.md rename to lib_basic/TasmotaModbus-1.2.0/README.md diff --git a/lib/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino b/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino similarity index 100% rename from lib/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino rename to lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino diff --git a/lib/TasmotaModbus-1.2.0/keywords.txt b/lib_basic/TasmotaModbus-1.2.0/keywords.txt similarity index 100% rename from lib/TasmotaModbus-1.2.0/keywords.txt rename to lib_basic/TasmotaModbus-1.2.0/keywords.txt diff --git a/lib/TasmotaModbus-1.2.0/library.json b/lib_basic/TasmotaModbus-1.2.0/library.json similarity index 100% rename from lib/TasmotaModbus-1.2.0/library.json rename to lib_basic/TasmotaModbus-1.2.0/library.json diff --git a/lib/TasmotaModbus-1.2.0/library.properties b/lib_basic/TasmotaModbus-1.2.0/library.properties similarity index 100% rename from lib/TasmotaModbus-1.2.0/library.properties rename to lib_basic/TasmotaModbus-1.2.0/library.properties diff --git a/lib/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp b/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp similarity index 100% rename from lib/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp rename to lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp diff --git a/lib/TasmotaModbus-1.2.0/src/TasmotaModbus.h b/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h similarity index 100% rename from lib/TasmotaModbus-1.2.0/src/TasmotaModbus.h rename to lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h diff --git a/lib/UdpListener/library.properties b/lib_basic/UdpListener/library.properties similarity index 100% rename from lib/UdpListener/library.properties rename to lib_basic/UdpListener/library.properties diff --git a/lib/UdpListener/src/UdpListener.h b/lib_basic/UdpListener/src/UdpListener.h similarity index 100% rename from lib/UdpListener/src/UdpListener.h rename to lib_basic/UdpListener/src/UdpListener.h diff --git a/lib/Unishox-1.0-shadinger/generator/generator.c b/lib_basic/Unishox-1.0-shadinger/generator/generator.c similarity index 100% rename from lib/Unishox-1.0-shadinger/generator/generator.c rename to lib_basic/Unishox-1.0-shadinger/generator/generator.c diff --git a/lib/Unishox-1.0-shadinger/generator/remapping.xlsx b/lib_basic/Unishox-1.0-shadinger/generator/remapping.xlsx similarity index 100% rename from lib/Unishox-1.0-shadinger/generator/remapping.xlsx rename to lib_basic/Unishox-1.0-shadinger/generator/remapping.xlsx diff --git a/lib/Unishox-1.0-shadinger/library.properties b/lib_basic/Unishox-1.0-shadinger/library.properties similarity index 100% rename from lib/Unishox-1.0-shadinger/library.properties rename to lib_basic/Unishox-1.0-shadinger/library.properties diff --git a/lib/Unishox-1.0-shadinger/python/unishox.py b/lib_basic/Unishox-1.0-shadinger/python/unishox.py similarity index 100% rename from lib/Unishox-1.0-shadinger/python/unishox.py rename to lib_basic/Unishox-1.0-shadinger/python/unishox.py diff --git a/lib/Unishox-1.0-shadinger/src/unishox.cpp b/lib_basic/Unishox-1.0-shadinger/src/unishox.cpp similarity index 100% rename from lib/Unishox-1.0-shadinger/src/unishox.cpp rename to lib_basic/Unishox-1.0-shadinger/src/unishox.cpp diff --git a/lib/Unishox-1.0-shadinger/src/unishox.h b/lib_basic/Unishox-1.0-shadinger/src/unishox.h similarity index 100% rename from lib/Unishox-1.0-shadinger/src/unishox.h rename to lib_basic/Unishox-1.0-shadinger/src/unishox.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties diff --git a/lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt b/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt similarity index 100% rename from lib/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt rename to lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino diff --git a/lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties b/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties similarity index 100% rename from lib/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties rename to lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties diff --git a/lib/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp b/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp rename to lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp diff --git a/lib/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h b/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h rename to lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h diff --git a/lib/Adafruit_LED_Backpack-1.1.6/README.md b/lib_display/Adafruit_LED_Backpack-1.1.6/README.md similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/README.md rename to lib_display/Adafruit_LED_Backpack-1.1.6/README.md diff --git a/lib/Adafruit_LED_Backpack-1.1.6/README.txt b/lib_display/Adafruit_LED_Backpack-1.1.6/README.txt similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/README.txt rename to lib_display/Adafruit_LED_Backpack-1.1.6/README.txt diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav diff --git a/lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav b/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav rename to lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav diff --git a/lib/Adafruit_LED_Backpack-1.1.6/library.properties b/lib_display/Adafruit_LED_Backpack-1.1.6/library.properties similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/library.properties rename to lib_display/Adafruit_LED_Backpack-1.1.6/library.properties diff --git a/lib/Adafruit_LED_Backpack-1.1.6/license.txt b/lib_display/Adafruit_LED_Backpack-1.1.6/license.txt similarity index 100% rename from lib/Adafruit_LED_Backpack-1.1.6/license.txt rename to lib_display/Adafruit_LED_Backpack-1.1.6/license.txt diff --git a/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp b/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp rename to lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp diff --git a/lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h b/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h rename to lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h diff --git a/lib/Adafruit_SH1106-gemu-1.0/LICENSE.txt b/lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/LICENSE.txt rename to lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt diff --git a/lib/Adafruit_SH1106-gemu-1.0/README.md b/lib_display/Adafruit_SH1106-gemu-1.0/README.md similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/README.md rename to lib_display/Adafruit_SH1106-gemu-1.0/README.md diff --git a/lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino b/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino rename to lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino diff --git a/lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino b/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino rename to lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino diff --git a/lib/Adafruit_SH1106-gemu-1.0/library.properties b/lib_display/Adafruit_SH1106-gemu-1.0/library.properties similarity index 100% rename from lib/Adafruit_SH1106-gemu-1.0/library.properties rename to lib_display/Adafruit_SH1106-gemu-1.0/library.properties diff --git a/lib/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md diff --git a/lib/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties diff --git a/lib/Adafruit_MCP9808_Tasmota/license.txt b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/license.txt rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h b/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h rename to lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h diff --git a/lib/Adafruit_SSD1351-gemu-1.0/README.md b/lib_display/Adafruit_SSD1351-gemu-1.0/README.md similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/README.md rename to lib_display/Adafruit_SSD1351-gemu-1.0/README.md diff --git a/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp b/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp rename to lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp diff --git a/lib/Adafruit_SSD1351-gemu-1.0/SSD1351.h b/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/SSD1351.h rename to lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h diff --git a/lib/Adafruit_SSD1351-gemu-1.0/Tiger.c b/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/Tiger.c rename to lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c diff --git a/lib/Adafruit_SSD1351-gemu-1.0/Tiger.rgb b/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/Tiger.rgb rename to lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb diff --git a/lib/Adafruit_SSD1351-gemu-1.0/keywords.txt b/lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/keywords.txt rename to lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt diff --git a/lib/Adafruit_SSD1351-gemu-1.0/library.properties b/lib_display/Adafruit_SSD1351-gemu-1.0/library.properties similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/library.properties rename to lib_display/Adafruit_SSD1351-gemu-1.0/library.properties diff --git a/lib/Adafruit_SSD1351-gemu-1.0/spi_register.h b/lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h similarity index 100% rename from lib/Adafruit_SSD1351-gemu-1.0/spi_register.h rename to lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h diff --git a/lib/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp b/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp old mode 100755 new mode 100644 similarity index 100% rename from lib/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp rename to lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp diff --git a/lib/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h b/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h old mode 100755 new mode 100644 similarity index 100% rename from lib/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h rename to lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h diff --git a/lib/Arduino_ST7789-gemu-1.0/README.txt b/lib_display/Arduino_ST7789-gemu-1.0/README.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/Arduino_ST7789-gemu-1.0/README.txt rename to lib_display/Arduino_ST7789-gemu-1.0/README.txt diff --git a/lib/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino b/lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino old mode 100755 new mode 100644 similarity index 99% rename from lib/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino rename to lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino index 3f24d027a..baed077ab --- a/lib/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino +++ b/lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino @@ -275,4 +275,4 @@ void mediabuttons() { tft.fillRoundRect(69, 98, 20, 45, 5, RED); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, GREEN); -} +} diff --git a/lib/Arduino_ST7789-gemu-1.0/keywords.txt b/lib_display/Arduino_ST7789-gemu-1.0/keywords.txt similarity index 100% rename from lib/Arduino_ST7789-gemu-1.0/keywords.txt rename to lib_display/Arduino_ST7789-gemu-1.0/keywords.txt diff --git a/lib/Arduino_ST7789-gemu-1.0/library.properties b/lib_display/Arduino_ST7789-gemu-1.0/library.properties old mode 100755 new mode 100644 similarity index 100% rename from lib/Arduino_ST7789-gemu-1.0/library.properties rename to lib_display/Arduino_ST7789-gemu-1.0/library.properties diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp b/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h b/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/README.md b/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/README.md rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino b/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/keywords.txt b/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/keywords.txt rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/library.properties b/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/library.properties rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties diff --git a/lib/JaretBurkett_ILI9488-gemu-1.0/spi_register.h b/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h similarity index 100% rename from lib/JaretBurkett_ILI9488-gemu-1.0/spi_register.h rename to lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h diff --git a/lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp b/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp rename to lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp diff --git a/lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h b/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h rename to lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h diff --git a/lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o b/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o rename to lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o diff --git a/lib/LiquidCrystal_I2C-1.1.3/README.md b/lib_display/LiquidCrystal_I2C-1.1.3/README.md similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/README.md rename to lib_display/LiquidCrystal_I2C-1.1.3/README.md diff --git a/lib/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde b/lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde rename to lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde diff --git a/lib/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde b/lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde rename to lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde diff --git a/lib/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde b/lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde rename to lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde diff --git a/lib/LiquidCrystal_I2C-1.1.3/keywords.txt b/lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/keywords.txt rename to lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt diff --git a/lib/LiquidCrystal_I2C-1.1.3/library.json b/lib_display/LiquidCrystal_I2C-1.1.3/library.json similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/library.json rename to lib_display/LiquidCrystal_I2C-1.1.3/library.json diff --git a/lib/LiquidCrystal_I2C-1.1.3/library.properties b/lib_display/LiquidCrystal_I2C-1.1.3/library.properties similarity index 100% rename from lib/LiquidCrystal_I2C-1.1.3/library.properties rename to lib_display/LiquidCrystal_I2C-1.1.3/library.properties diff --git a/lib/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/RA8876.cpp rename to lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp diff --git a/lib/Xlatb_RA8876-gemu-1.0/RA8876.h b/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/RA8876.h rename to lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h diff --git a/lib/Xlatb_RA8876-gemu-1.0/README.md b/lib_display/Xlatb_RA8876-gemu-1.0/README.md similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/README.md rename to lib_display/Xlatb_RA8876-gemu-1.0/README.md diff --git a/lib/Xlatb_RA8876-gemu-1.0/keywords.txt b/lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/keywords.txt rename to lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt diff --git a/lib/Xlatb_RA8876-gemu-1.0/library.properties b/lib_display/Xlatb_RA8876-gemu-1.0/library.properties similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/library.properties rename to lib_display/Xlatb_RA8876-gemu-1.0/library.properties diff --git a/lib/Xlatb_RA8876-gemu-1.0/spi_register.h b/lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h similarity index 100% rename from lib/Xlatb_RA8876-gemu-1.0/spi_register.h rename to lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/Makefile b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/Makefile rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/README.md b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/README.md rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/library.properties b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/library.properties rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h b/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h similarity index 100% rename from lib/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h rename to lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h diff --git a/lib/A4988_Stepper/README.adoc b/lib_div/A4988_Stepper/README.adoc similarity index 100% rename from lib/A4988_Stepper/README.adoc rename to lib_div/A4988_Stepper/README.adoc diff --git a/lib/A4988_Stepper/keywords.txt b/lib_div/A4988_Stepper/keywords.txt old mode 100755 new mode 100644 similarity index 100% rename from lib/A4988_Stepper/keywords.txt rename to lib_div/A4988_Stepper/keywords.txt diff --git a/lib/A4988_Stepper/library.properties b/lib_div/A4988_Stepper/library.properties similarity index 100% rename from lib/A4988_Stepper/library.properties rename to lib_div/A4988_Stepper/library.properties diff --git a/lib/A4988_Stepper/src/A4988_Stepper.cpp b/lib_div/A4988_Stepper/src/A4988_Stepper.cpp similarity index 100% rename from lib/A4988_Stepper/src/A4988_Stepper.cpp rename to lib_div/A4988_Stepper/src/A4988_Stepper.cpp diff --git a/lib/A4988_Stepper/src/A4988_Stepper.h b/lib_div/A4988_Stepper/src/A4988_Stepper.h similarity index 100% rename from lib/A4988_Stepper/src/A4988_Stepper.h rename to lib_div/A4988_Stepper/src/A4988_Stepper.h diff --git a/lib/AT24C256/Eeprom24C128_256.cpp b/lib_div/AT24C256/Eeprom24C128_256.cpp similarity index 100% rename from lib/AT24C256/Eeprom24C128_256.cpp rename to lib_div/AT24C256/Eeprom24C128_256.cpp diff --git a/lib/AT24C256/Eeprom24C128_256.h b/lib_div/AT24C256/Eeprom24C128_256.h similarity index 100% rename from lib/AT24C256/Eeprom24C128_256.h rename to lib_div/AT24C256/Eeprom24C128_256.h diff --git a/lib/AT24C256/library.properties b/lib_div/AT24C256/library.properties similarity index 100% rename from lib/AT24C256/library.properties rename to lib_div/AT24C256/library.properties diff --git a/lib/ArduinoNTPd/NTPPacket.cpp b/lib_div/ArduinoNTPd/NTPPacket.cpp similarity index 100% rename from lib/ArduinoNTPd/NTPPacket.cpp rename to lib_div/ArduinoNTPd/NTPPacket.cpp diff --git a/lib/ArduinoNTPd/NTPPacket.h b/lib_div/ArduinoNTPd/NTPPacket.h similarity index 100% rename from lib/ArduinoNTPd/NTPPacket.h rename to lib_div/ArduinoNTPd/NTPPacket.h diff --git a/lib/ArduinoNTPd/NTPServer.cpp b/lib_div/ArduinoNTPd/NTPServer.cpp similarity index 100% rename from lib/ArduinoNTPd/NTPServer.cpp rename to lib_div/ArduinoNTPd/NTPServer.cpp diff --git a/lib/ArduinoNTPd/NTPServer.h b/lib_div/ArduinoNTPd/NTPServer.h similarity index 100% rename from lib/ArduinoNTPd/NTPServer.h rename to lib_div/ArduinoNTPd/NTPServer.h diff --git a/lib/ArduinoNTPd/library.properties b/lib_div/ArduinoNTPd/library.properties similarity index 100% rename from lib/ArduinoNTPd/library.properties rename to lib_div/ArduinoNTPd/library.properties diff --git a/lib/LibTeleinfo/README.md b/lib_div/LibTeleinfo/README.md old mode 100755 new mode 100644 similarity index 100% rename from lib/LibTeleinfo/README.md rename to lib_div/LibTeleinfo/README.md diff --git a/lib/LibTeleinfo/library.json b/lib_div/LibTeleinfo/library.json old mode 100755 new mode 100644 similarity index 95% rename from lib/LibTeleinfo/library.json rename to lib_div/LibTeleinfo/library.json index 721266bef..b2e0684b8 --- a/lib/LibTeleinfo/library.json +++ b/lib_div/LibTeleinfo/library.json @@ -1,19 +1,19 @@ -{ - "name": "LibTeleinfo", - "version": "1.1.3", - "keywords": "teleinfo, french, meter, power, erdf, linky, tic", - "description": "Decoder for Teleinfo (aka TIC) from French smart power meters", - "repository": - { - "type": "git", - "url": "https://github.com/hallard/LibTeleinfo.git" - }, - "authors": - { - "name": "Charles-Henri Hallard", - "url": "http://hallard.me" - }, - "frameworks": "arduino", - "platforms": "*" -} - +{ + "name": "LibTeleinfo", + "version": "1.1.3", + "keywords": "teleinfo, french, meter, power, erdf, linky, tic", + "description": "Decoder for Teleinfo (aka TIC) from French smart power meters", + "repository": + { + "type": "git", + "url": "https://github.com/hallard/LibTeleinfo.git" + }, + "authors": + { + "name": "Charles-Henri Hallard", + "url": "http://hallard.me" + }, + "frameworks": "arduino", + "platforms": "*" +} + diff --git a/lib/LibTeleinfo/library.properties b/lib_div/LibTeleinfo/library.properties old mode 100755 new mode 100644 similarity index 95% rename from lib/LibTeleinfo/library.properties rename to lib_div/LibTeleinfo/library.properties index 89fce0969..ad488ca08 --- a/lib/LibTeleinfo/library.properties +++ b/lib_div/LibTeleinfo/library.properties @@ -1,9 +1,9 @@ -name=LibTeleinfo -version=1.1.3 -author=Charles-Henri Hallard -maintainer=Charles-Henri Hallard -sentence=Decoder for Teleinfo (aka TIC) from French smart power meters -paragraph=This is a generic Teleinfo (aka TIC) French Meter Measure Library, it can be used on Arduino, Particle, ESP8266, Raspberry PI or anywhere you can do Cpp coding. -category=Communication -url=https://github.com/hallard/LibTeleinfo +name=LibTeleinfo +version=1.1.3 +author=Charles-Henri Hallard +maintainer=Charles-Henri Hallard +sentence=Decoder for Teleinfo (aka TIC) from French smart power meters +paragraph=This is a generic Teleinfo (aka TIC) French Meter Measure Library, it can be used on Arduino, Particle, ESP8266, Raspberry PI or anywhere you can do Cpp coding. +category=Communication +url=https://github.com/hallard/LibTeleinfo architectures=* \ No newline at end of file diff --git a/lib/LibTeleinfo/src/LibTeleinfo.cpp b/lib_div/LibTeleinfo/src/LibTeleinfo.cpp similarity index 100% rename from lib/LibTeleinfo/src/LibTeleinfo.cpp rename to lib_div/LibTeleinfo/src/LibTeleinfo.cpp diff --git a/lib/LibTeleinfo/src/LibTeleinfo.h b/lib_div/LibTeleinfo/src/LibTeleinfo.h old mode 100755 new mode 100644 similarity index 97% rename from lib/LibTeleinfo/src/LibTeleinfo.h rename to lib_div/LibTeleinfo/src/LibTeleinfo.h index 01c603c83..60dc0228b --- a/lib/LibTeleinfo/src/LibTeleinfo.h +++ b/lib_div/LibTeleinfo/src/LibTeleinfo.h @@ -1,185 +1,185 @@ -// ********************************************************************************** -// Driver definition for French Teleinfo -// ********************************************************************************** -// Creative Commons Attrib Share-Alike License -// You are free to use/extend this library but please abide with the CC-BY-SA license: -// http://creativecommons.org/licenses/by-sa/4.0/ -// -// For any explanation about teleinfo ou use , see my blog -// http://hallard.me/category/tinfo -// -// Code based on following datasheet -// http://www.erdf.fr/sites/default/files/ERDF-NOI-CPT_02E.pdf -// -// Written by Charles-Henri Hallard (http://hallard.me) -// -// History : V1.00 2015-06-14 - First release -// V2.00 2020-06-11 - Integration into Tasmota -// V2.01 2020-08-11 - Merged LibTeleinfo official and Tasmota version -// Added support for new standard mode of linky smart meter -// -// All text above must be included in any redistribution. -// -// Edit : Tab size set to 2 but I converted tab to sapces -// -// ********************************************************************************** - -#ifndef LibTeleinfo_h -#define LibTeleinfo_h - -#ifdef __arm__ -#include -#include -#include -#include -#define boolean bool -#endif - -#ifdef ARDUINO -#include -#endif - -// Define this if you want library to be verbose -//#define TI_DEBUG - -// I prefix debug macro to be sure to use specific for THIS library -// debugging, this should not interfere with main sketch or other -// libraries -#ifdef TI_DEBUG - // Tasmota build - #ifdef CODE_IMAGE_STR - #define TI_Debug(x) AddLog_P2(LOG_LEVEL_DEBUG, x); - #define TI_Debugln(x) AddLog_P2(LOG_LEVEL_DEBUG, x); - #define TI_Debugf(...) AddLog_P2(LOG_LEVEL_DEBUG, __VA_ARGS__); - #define TI_Debugflush {} - #else - #ifdef ESP8266 - #define TI_Debug(x) Serial1.print(x) - #define TI_Debugln(x) Serial1.println(x) - #define TI_Debugf(...) Serial1.printf(__VA_ARGS__) - #define TI_Debugflush Serial1.flush - #else - #define TI_Debug(x) Serial.print(x) - #define TI_Debugln(x) Serial.println(x) - #define TI_Debugf(...) Serial.printf(__VA_ARGS__) - #define TI_Debugflush Serial.flush - #endif - #endif -#else - #define TI_Debug(x) {} - #define TI_Debugln(x) {} - #define TI_Debugf(...) {} - #define TI_Debugflush {} -#endif - -// For 4 bytes Aligment boundaries -#if defined (ESP8266) || defined (ESP32) -#define ESP_allocAlign(size) ((size + 3) & ~((size_t) 3)) -#endif - -#pragma pack(push) // push current alignment to stack -#pragma pack(1) // set alignment to 1 byte boundary - -// Linked list structure containing all values received -typedef struct _ValueList ValueList; -struct _ValueList -{ - ValueList *next; // next element -//#ifdef USE_TELEINFO_STANDARD - time_t ts; // TimeStamp of data if any -//#endif - uint8_t checksum;// checksum - uint8_t flags; // specific flags - char * name; // LABEL of value name - char * value; // value -}; - -#pragma pack(pop) - -// Library state machine -enum _Mode_e { - TINFO_MODE_HISTORIQUE, // Legacy mode (1200) - TINFO_MODE_STANDARD // Standard mode (9600) -}; - -// Library state machine -enum _State_e { - TINFO_INIT, // We're in init - TINFO_WAIT_STX, // We're waiting for STX - TINFO_WAIT_ETX, // We had STX, We're waiting for ETX - TINFO_READY // We had STX AND ETX, So we're OK -}; - -// what we done with received value (also for callback flags) -#define TINFO_FLAGS_NONE 0x00 -#define TINFO_FLAGS_NOTHING 0x01 -#define TINFO_FLAGS_ADDED 0x02 -#define TINFO_FLAGS_EXIST 0x04 -#define TINFO_FLAGS_UPDATED 0x08 -#define TINFO_FLAGS_ALERT 0x80 /* This will generate an alert */ - -// Local buffer for one line of teleinfo -// maximum size, I think it should be enought -#ifdef USE_TELEINFO_STANDARD -// Linky and standard mode may have longer lines -#define TINFO_BUFSIZE 128 -#else -#define TINFO_BUFSIZE 64 -#endif - -// Teleinfo start and end of frame characters -#define TINFO_STX 0x02 -#define TINFO_ETX 0x03 -#define TINFO_HT 0x09 -#define TINFO_SGR '\n' // start of group -#define TINFO_EGR '\r' // End of group - -typedef void (*_fn_ADPS) (uint8_t); -typedef void (*_fn_data) (ValueList *, uint8_t); -typedef void (*_fn_new_frame) (ValueList *); -typedef void (*_fn_updated_frame) (ValueList *); - -class TInfo -{ - public: - TInfo(); - void init(_Mode_e mode = TINFO_MODE_HISTORIQUE); - _State_e process (char c); - void attachADPS(void (*_fn_ADPS)(uint8_t phase)); - void attachData(void (*_fn_data)(ValueList * valueslist, uint8_t state)); - void attachNewFrame(void (*_fn_new_frame)(ValueList * valueslist)); - void attachUpdatedFrame(void (*_fn_updated_frame)(ValueList * valueslist)); - ValueList * addCustomValue(char * name, char * value, uint8_t * flags); - ValueList * getList(void); - uint8_t valuesDump(void); - char * valueGet(char * name, char * value); - char * valueGet_P(const char * name, char * value); - boolean listDelete(); - unsigned char calcChecksum(char *etiquette, char *valeur, char *horodate=NULL) ; - - private: - void clearBuffer(); - ValueList * valueAdd (char * name, char * value, uint8_t checksum, uint8_t * flags, char * horodate=NULL); - boolean valueRemove (char * name); - boolean valueRemoveFlagged(uint8_t flags); - int labelCount(); - uint32_t horodate2Timestamp( char * pdate) ; - void customLabel( char * plabel, char * pvalue, uint8_t * pflags) ; - ValueList * checkLine(char * pline) ; - - _State_e _state; // Teleinfo machine state - ValueList _valueslist; // Linked list of teleinfo values - char _recv_buff[TINFO_BUFSIZE]; // line receive buffer - char _separator; - uint8_t _recv_idx; // index in receive buffer - boolean _frame_updated; // Data on the frame has been updated - void (*_fn_ADPS)(uint8_t phase); - void (*_fn_data)(ValueList * valueslist, uint8_t state); - void (*_fn_new_frame)(ValueList * valueslist); - void (*_fn_updated_frame)(ValueList * valueslist); - - //volatile uint8_t *dcport; - //uint8_t dcpinmask; -}; - -#endif +// ********************************************************************************** +// Driver definition for French Teleinfo +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// http://creativecommons.org/licenses/by-sa/4.0/ +// +// For any explanation about teleinfo ou use , see my blog +// http://hallard.me/category/tinfo +// +// Code based on following datasheet +// http://www.erdf.fr/sites/default/files/ERDF-NOI-CPT_02E.pdf +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2015-06-14 - First release +// V2.00 2020-06-11 - Integration into Tasmota +// V2.01 2020-08-11 - Merged LibTeleinfo official and Tasmota version +// Added support for new standard mode of linky smart meter +// +// All text above must be included in any redistribution. +// +// Edit : Tab size set to 2 but I converted tab to sapces +// +// ********************************************************************************** + +#ifndef LibTeleinfo_h +#define LibTeleinfo_h + +#ifdef __arm__ +#include +#include +#include +#include +#define boolean bool +#endif + +#ifdef ARDUINO +#include +#endif + +// Define this if you want library to be verbose +//#define TI_DEBUG + +// I prefix debug macro to be sure to use specific for THIS library +// debugging, this should not interfere with main sketch or other +// libraries +#ifdef TI_DEBUG + // Tasmota build + #ifdef CODE_IMAGE_STR + #define TI_Debug(x) AddLog_P2(LOG_LEVEL_DEBUG, x); + #define TI_Debugln(x) AddLog_P2(LOG_LEVEL_DEBUG, x); + #define TI_Debugf(...) AddLog_P2(LOG_LEVEL_DEBUG, __VA_ARGS__); + #define TI_Debugflush {} + #else + #ifdef ESP8266 + #define TI_Debug(x) Serial1.print(x) + #define TI_Debugln(x) Serial1.println(x) + #define TI_Debugf(...) Serial1.printf(__VA_ARGS__) + #define TI_Debugflush Serial1.flush + #else + #define TI_Debug(x) Serial.print(x) + #define TI_Debugln(x) Serial.println(x) + #define TI_Debugf(...) Serial.printf(__VA_ARGS__) + #define TI_Debugflush Serial.flush + #endif + #endif +#else + #define TI_Debug(x) {} + #define TI_Debugln(x) {} + #define TI_Debugf(...) {} + #define TI_Debugflush {} +#endif + +// For 4 bytes Aligment boundaries +#if defined (ESP8266) || defined (ESP32) +#define ESP_allocAlign(size) ((size + 3) & ~((size_t) 3)) +#endif + +#pragma pack(push) // push current alignment to stack +#pragma pack(1) // set alignment to 1 byte boundary + +// Linked list structure containing all values received +typedef struct _ValueList ValueList; +struct _ValueList +{ + ValueList *next; // next element +//#ifdef USE_TELEINFO_STANDARD + time_t ts; // TimeStamp of data if any +//#endif + uint8_t checksum;// checksum + uint8_t flags; // specific flags + char * name; // LABEL of value name + char * value; // value +}; + +#pragma pack(pop) + +// Library state machine +enum _Mode_e { + TINFO_MODE_HISTORIQUE, // Legacy mode (1200) + TINFO_MODE_STANDARD // Standard mode (9600) +}; + +// Library state machine +enum _State_e { + TINFO_INIT, // We're in init + TINFO_WAIT_STX, // We're waiting for STX + TINFO_WAIT_ETX, // We had STX, We're waiting for ETX + TINFO_READY // We had STX AND ETX, So we're OK +}; + +// what we done with received value (also for callback flags) +#define TINFO_FLAGS_NONE 0x00 +#define TINFO_FLAGS_NOTHING 0x01 +#define TINFO_FLAGS_ADDED 0x02 +#define TINFO_FLAGS_EXIST 0x04 +#define TINFO_FLAGS_UPDATED 0x08 +#define TINFO_FLAGS_ALERT 0x80 /* This will generate an alert */ + +// Local buffer for one line of teleinfo +// maximum size, I think it should be enought +#ifdef USE_TELEINFO_STANDARD +// Linky and standard mode may have longer lines +#define TINFO_BUFSIZE 128 +#else +#define TINFO_BUFSIZE 64 +#endif + +// Teleinfo start and end of frame characters +#define TINFO_STX 0x02 +#define TINFO_ETX 0x03 +#define TINFO_HT 0x09 +#define TINFO_SGR '\n' // start of group +#define TINFO_EGR '\r' // End of group + +typedef void (*_fn_ADPS) (uint8_t); +typedef void (*_fn_data) (ValueList *, uint8_t); +typedef void (*_fn_new_frame) (ValueList *); +typedef void (*_fn_updated_frame) (ValueList *); + +class TInfo +{ + public: + TInfo(); + void init(_Mode_e mode = TINFO_MODE_HISTORIQUE); + _State_e process (char c); + void attachADPS(void (*_fn_ADPS)(uint8_t phase)); + void attachData(void (*_fn_data)(ValueList * valueslist, uint8_t state)); + void attachNewFrame(void (*_fn_new_frame)(ValueList * valueslist)); + void attachUpdatedFrame(void (*_fn_updated_frame)(ValueList * valueslist)); + ValueList * addCustomValue(char * name, char * value, uint8_t * flags); + ValueList * getList(void); + uint8_t valuesDump(void); + char * valueGet(char * name, char * value); + char * valueGet_P(const char * name, char * value); + boolean listDelete(); + unsigned char calcChecksum(char *etiquette, char *valeur, char *horodate=NULL) ; + + private: + void clearBuffer(); + ValueList * valueAdd (char * name, char * value, uint8_t checksum, uint8_t * flags, char * horodate=NULL); + boolean valueRemove (char * name); + boolean valueRemoveFlagged(uint8_t flags); + int labelCount(); + uint32_t horodate2Timestamp( char * pdate) ; + void customLabel( char * plabel, char * pvalue, uint8_t * pflags) ; + ValueList * checkLine(char * pline) ; + + _State_e _state; // Teleinfo machine state + ValueList _valueslist; // Linked list of teleinfo values + char _recv_buff[TINFO_BUFSIZE]; // line receive buffer + char _separator; + uint8_t _recv_idx; // index in receive buffer + boolean _frame_updated; // Data on the frame has been updated + void (*_fn_ADPS)(uint8_t phase); + void (*_fn_data)(ValueList * valueslist, uint8_t state); + void (*_fn_new_frame)(ValueList * valueslist); + void (*_fn_updated_frame)(ValueList * valueslist); + + //volatile uint8_t *dcport; + //uint8_t dcpinmask; +}; + +#endif diff --git a/lib/NewPing-1.9.1/README.md b/lib_div/NewPing-1.9.1/README.md similarity index 100% rename from lib/NewPing-1.9.1/README.md rename to lib_div/NewPing-1.9.1/README.md diff --git a/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde b/lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde rename to lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde diff --git a/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde b/lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde rename to lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde diff --git a/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde b/lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde rename to lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde diff --git a/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde b/lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde rename to lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde diff --git a/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde b/lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde rename to lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde diff --git a/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde b/lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde similarity index 100% rename from lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde rename to lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde diff --git a/lib/NewPing-1.9.1/keywords.txt b/lib_div/NewPing-1.9.1/keywords.txt similarity index 100% rename from lib/NewPing-1.9.1/keywords.txt rename to lib_div/NewPing-1.9.1/keywords.txt diff --git a/lib/NewPing-1.9.1/library.properties b/lib_div/NewPing-1.9.1/library.properties similarity index 100% rename from lib/NewPing-1.9.1/library.properties rename to lib_div/NewPing-1.9.1/library.properties diff --git a/lib/NewPing-1.9.1/src/NewPing.cpp b/lib_div/NewPing-1.9.1/src/NewPing.cpp similarity index 100% rename from lib/NewPing-1.9.1/src/NewPing.cpp rename to lib_div/NewPing-1.9.1/src/NewPing.cpp diff --git a/lib/NewPing-1.9.1/src/NewPing.h b/lib_div/NewPing-1.9.1/src/NewPing.h similarity index 100% rename from lib/NewPing-1.9.1/src/NewPing.h rename to lib_div/NewPing-1.9.1/src/NewPing.h diff --git a/lib/OpenTherm-0.9.0/LICENSE b/lib_div/OpenTherm-0.9.0/LICENSE similarity index 100% rename from lib/OpenTherm-0.9.0/LICENSE rename to lib_div/OpenTherm-0.9.0/LICENSE diff --git a/lib/OpenTherm-0.9.0/README.md b/lib_div/OpenTherm-0.9.0/README.md similarity index 100% rename from lib/OpenTherm-0.9.0/README.md rename to lib_div/OpenTherm-0.9.0/README.md diff --git a/lib/OpenTherm-0.9.0/keywords.txt b/lib_div/OpenTherm-0.9.0/keywords.txt similarity index 100% rename from lib/OpenTherm-0.9.0/keywords.txt rename to lib_div/OpenTherm-0.9.0/keywords.txt diff --git a/lib/OpenTherm-0.9.0/library.properties b/lib_div/OpenTherm-0.9.0/library.properties similarity index 100% rename from lib/OpenTherm-0.9.0/library.properties rename to lib_div/OpenTherm-0.9.0/library.properties diff --git a/lib/OpenTherm-0.9.0/src/OpenTherm.cpp b/lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp similarity index 100% rename from lib/OpenTherm-0.9.0/src/OpenTherm.cpp rename to lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp diff --git a/lib/OpenTherm-0.9.0/src/OpenTherm.h b/lib_div/OpenTherm-0.9.0/src/OpenTherm.h similarity index 100% rename from lib/OpenTherm-0.9.0/src/OpenTherm.h rename to lib_div/OpenTherm-0.9.0/src/OpenTherm.h diff --git a/lib/Adafruit_BusIO/.travis.yml b/lib_i2c/Adafruit_BusIO/.travis.yml similarity index 100% rename from lib/Adafruit_BusIO/.travis.yml rename to lib_i2c/Adafruit_BusIO/.travis.yml diff --git a/lib/Adafruit_BusIO/Adafruit_BusIO_Register.cpp b/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_BusIO_Register.cpp rename to lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp diff --git a/lib/Adafruit_BusIO/Adafruit_BusIO_Register.h b/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_BusIO_Register.h rename to lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h diff --git a/lib/Adafruit_BusIO/Adafruit_I2CDevice.cpp b/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_I2CDevice.cpp rename to lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp diff --git a/lib/Adafruit_BusIO/Adafruit_I2CDevice.h b/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_I2CDevice.h rename to lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h diff --git a/lib/Adafruit_BusIO/Adafruit_I2CRegister.h b/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_I2CRegister.h rename to lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h diff --git a/lib/Adafruit_BusIO/Adafruit_SPIDevice.cpp b/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_SPIDevice.cpp rename to lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp diff --git a/lib/Adafruit_BusIO/Adafruit_SPIDevice.h b/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h similarity index 100% rename from lib/Adafruit_BusIO/Adafruit_SPIDevice.h rename to lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h diff --git a/lib/Adafruit_BusIO/LICENSE b/lib_i2c/Adafruit_BusIO/LICENSE similarity index 100% rename from lib/Adafruit_BusIO/LICENSE rename to lib_i2c/Adafruit_BusIO/LICENSE diff --git a/lib/Adafruit_BusIO/README.md b/lib_i2c/Adafruit_BusIO/README.md similarity index 100% rename from lib/Adafruit_BusIO/README.md rename to lib_i2c/Adafruit_BusIO/README.md diff --git a/lib/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino b/lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino rename to lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino diff --git a/lib/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino b/lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino rename to lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino diff --git a/lib/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino b/lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino rename to lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino diff --git a/lib/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino b/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino rename to lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino diff --git a/lib/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino b/lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino rename to lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino diff --git a/lib/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino b/lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino rename to lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino diff --git a/lib/Adafruit_BusIO/examples/spi_registers/spi_registers.ino b/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino similarity index 100% rename from lib/Adafruit_BusIO/examples/spi_registers/spi_registers.ino rename to lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino diff --git a/lib/Adafruit_BusIO/library.properties b/lib_i2c/Adafruit_BusIO/library.properties similarity index 100% rename from lib/Adafruit_BusIO/library.properties rename to lib_i2c/Adafruit_BusIO/library.properties diff --git a/lib/Adafruit_CCS811-1.0.0.14/.travis.yml b/lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/.travis.yml rename to lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml diff --git a/lib/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp b/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp rename to lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp diff --git a/lib/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h b/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h rename to lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h diff --git a/lib/Adafruit_CCS811-1.0.0.14/LICENSE b/lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/LICENSE rename to lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE diff --git a/lib/Adafruit_CCS811-1.0.0.14/README.md b/lib_i2c/Adafruit_CCS811-1.0.0.14/README.md similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/README.md rename to lib_i2c/Adafruit_CCS811-1.0.0.14/README.md diff --git a/lib/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino b/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino rename to lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino diff --git a/lib/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino b/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino rename to lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino diff --git a/lib/Adafruit_CCS811-1.0.0.14/library.properties b/lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties similarity index 100% rename from lib/Adafruit_CCS811-1.0.0.14/library.properties rename to lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/README.md b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/README.md rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/README.txt b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/README.txt rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino diff --git a/lib/Adafruit_MAX31865-1.1.0-custom/library.properties b/lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties similarity index 100% rename from lib/Adafruit_MAX31865-1.1.0-custom/library.properties rename to lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md b/lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md rename to lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md b/lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md rename to lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml b/lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml rename to lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml diff --git a/lib/Adafruit_MCP9808_Tasmota/.gitignore b/lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/.gitignore rename to lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore diff --git a/lib/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp b/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp rename to lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp diff --git a/lib/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h b/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h rename to lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h diff --git a/lib/Adafruit_MCP9808_Tasmota/README.md b/lib_i2c/Adafruit_MCP9808_Tasmota/README.md similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/README.md rename to lib_i2c/Adafruit_MCP9808_Tasmota/README.md diff --git a/lib/Adafruit_MCP9808_Tasmota/assets/board.jpg b/lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/assets/board.jpg rename to lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg diff --git a/lib/Adafruit_MCP9808_Tasmota/code-of-conduct.md b/lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/code-of-conduct.md rename to lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md diff --git a/lib/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino b/lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino rename to lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino diff --git a/lib/Adafruit_MCP9808_Tasmota/library.properties b/lib_i2c/Adafruit_MCP9808_Tasmota/library.properties similarity index 100% rename from lib/Adafruit_MCP9808_Tasmota/library.properties rename to lib_i2c/Adafruit_MCP9808_Tasmota/library.properties diff --git a/lib/Adafruit_SGP30-1.2.0/license.txt b/lib_i2c/Adafruit_MCP9808_Tasmota/license.txt similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/license.txt rename to lib_i2c/Adafruit_MCP9808_Tasmota/license.txt diff --git a/lib/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp b/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp rename to lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp diff --git a/lib/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h b/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h rename to lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h diff --git a/lib/Adafruit_SGP30-1.2.0/README.md b/lib_i2c/Adafruit_SGP30-1.2.0/README.md similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/README.md rename to lib_i2c/Adafruit_SGP30-1.2.0/README.md diff --git a/lib/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino b/lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino rename to lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino diff --git a/lib/Adafruit_SGP30-1.2.0/library.properties b/lib_i2c/Adafruit_SGP30-1.2.0/library.properties similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/library.properties rename to lib_i2c/Adafruit_SGP30-1.2.0/library.properties diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt b/lib_i2c/Adafruit_SGP30-1.2.0/license.txt similarity index 100% rename from lib/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt rename to lib_i2c/Adafruit_SGP30-1.2.0/license.txt diff --git a/lib/Adafruit_SGP30-1.2.0/travis.yml b/lib_i2c/Adafruit_SGP30-1.2.0/travis.yml similarity index 100% rename from lib/Adafruit_SGP30-1.2.0/travis.yml rename to lib_i2c/Adafruit_SGP30-1.2.0/travis.yml diff --git a/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp b/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp similarity index 100% rename from lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp rename to lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp diff --git a/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.h b/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h similarity index 100% rename from lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.h rename to lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h diff --git a/lib/Adafruit_TSL2591_Library/library.properties b/lib_i2c/Adafruit_TSL2591_Library/library.properties similarity index 100% rename from lib/Adafruit_TSL2591_Library/library.properties rename to lib_i2c/Adafruit_TSL2591_Library/library.properties diff --git a/lib/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md b/lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md rename to lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md diff --git a/lib/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md b/lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md rename to lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib/Adafruit_VEML7700/.gitignore b/lib_i2c/Adafruit_VEML7700/.gitignore similarity index 100% rename from lib/Adafruit_VEML7700/.gitignore rename to lib_i2c/Adafruit_VEML7700/.gitignore diff --git a/lib/Adafruit_VEML7700/.travis.yml b/lib_i2c/Adafruit_VEML7700/.travis.yml similarity index 100% rename from lib/Adafruit_VEML7700/.travis.yml rename to lib_i2c/Adafruit_VEML7700/.travis.yml diff --git a/lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp b/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp similarity index 100% rename from lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp rename to lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp diff --git a/lib/Adafruit_VEML7700/Adafruit_VEML7700.h b/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h similarity index 100% rename from lib/Adafruit_VEML7700/Adafruit_VEML7700.h rename to lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h diff --git a/lib/Adafruit_VEML7700/README.md b/lib_i2c/Adafruit_VEML7700/README.md similarity index 100% rename from lib/Adafruit_VEML7700/README.md rename to lib_i2c/Adafruit_VEML7700/README.md diff --git a/lib/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino b/lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino similarity index 100% rename from lib/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino rename to lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino diff --git a/lib/Adafruit_VEML7700/library.properties b/lib_i2c/Adafruit_VEML7700/library.properties similarity index 100% rename from lib/Adafruit_VEML7700/library.properties rename to lib_i2c/Adafruit_VEML7700/library.properties diff --git a/lib/Adafruit_VEML7700/license.txt b/lib_i2c/Adafruit_VEML7700/license.txt similarity index 100% rename from lib/Adafruit_VEML7700/license.txt rename to lib_i2c/Adafruit_VEML7700/license.txt diff --git a/lib/BME680_driver-bme680_v3.5.9/LICENSE b/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/LICENSE rename to lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE diff --git a/lib/BME680_driver-bme680_v3.5.9/README.md b/lib_i2c/BME680_driver-bme680_v3.5.9/README.md similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/README.md rename to lib_i2c/BME680_driver-bme680_v3.5.9/README.md diff --git a/lib/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c b/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c rename to lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c diff --git a/lib/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h b/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h rename to lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h diff --git a/lib/BME680_driver-bme680_v3.5.9/bme680.c b/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/bme680.c rename to lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c diff --git a/lib/BME680_driver-bme680_v3.5.9/bme680.h b/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/bme680.h rename to lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h diff --git a/lib/BME680_driver-bme680_v3.5.9/bme680_defs.h b/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/bme680_defs.h rename to lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h diff --git a/lib/BME680_driver-bme680_v3.5.9/library.properties b/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties similarity index 100% rename from lib/BME680_driver-bme680_v3.5.9/library.properties rename to lib_i2c/BME680_driver-bme680_v3.5.9/library.properties diff --git a/lib_i2c/FT5206_Library/.gitignore b/lib_i2c/FT5206_Library/.gitignore new file mode 100644 index 000000000..6d0ee45db --- /dev/null +++ b/lib_i2c/FT5206_Library/.gitignore @@ -0,0 +1,2 @@ +.vscode +.DS_Store \ No newline at end of file diff --git a/lib/FT5206_Library/LICENSE b/lib_i2c/FT5206_Library/LICENSE old mode 100755 new mode 100644 similarity index 98% rename from lib/FT5206_Library/LICENSE rename to lib_i2c/FT5206_Library/LICENSE index 0b0f6fd2c..3b7bfa9f2 --- a/lib/FT5206_Library/LICENSE +++ b/lib_i2c/FT5206_Library/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2019 lewis he - -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. +MIT License + +Copyright (c) 2019 lewis he + +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_i2c/FT5206_Library/README.md b/lib_i2c/FT5206_Library/README.md new file mode 100644 index 000000000..212a4efcd --- /dev/null +++ b/lib_i2c/FT5206_Library/README.md @@ -0,0 +1,2 @@ +FT5206 Library +===================================== \ No newline at end of file diff --git a/lib/FT5206_Library/keywords.txt b/lib_i2c/FT5206_Library/keywords.txt old mode 100755 new mode 100644 similarity index 96% rename from lib/FT5206_Library/keywords.txt rename to lib_i2c/FT5206_Library/keywords.txt index 3fd9024be..2cf7d1013 --- a/lib/FT5206_Library/keywords.txt +++ b/lib_i2c/FT5206_Library/keywords.txt @@ -1,29 +1,29 @@ -####################################### -# Syntax Coloring Map For FT5206 Library By lewis He -# github:https://github.com/lewisxhe -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### -TP_Point KEYWORD1 -FT5206_Class KEYWORD1 -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -adjustTheshold KEYWORD2 -getPoint KEYWORD2 -enterSleepMode KEYWORD2 -enterMonitorMode KEYWORD2 - - -####################################### -# Instances (KEYWORD2) -####################################### - - -####################################### -# Constants (LITERAL1) -####################################### +####################################### +# Syntax Coloring Map For FT5206 Library By lewis He +# github:https://github.com/lewisxhe +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +TP_Point KEYWORD1 +FT5206_Class KEYWORD1 +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +adjustTheshold KEYWORD2 +getPoint KEYWORD2 +enterSleepMode KEYWORD2 +enterMonitorMode KEYWORD2 + + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/FT5206_Library/library.properties b/lib_i2c/FT5206_Library/library.properties old mode 100755 new mode 100644 similarity index 90% rename from lib/FT5206_Library/library.properties rename to lib_i2c/FT5206_Library/library.properties index 5a99dca9b..e28709e5c --- a/lib/FT5206_Library/library.properties +++ b/lib_i2c/FT5206_Library/library.properties @@ -1,10 +1,10 @@ -name=FT5206_Library -version=1.0.0 -author=Lewis He -maintainer=Lewis He -sentence=Arduino library for FT5206 chip. -paragraph=Arduino library for FT5206 chip. Tested with ESP32 -category=Communication -url=https://github.com/lewisxhe/FT5206_Library -architectures=* +name=FT5206_Library +version=1.0.0 +author=Lewis He +maintainer=Lewis He +sentence=Arduino library for FT5206 chip. +paragraph=Arduino library for FT5206 chip. Tested with ESP32 +category=Communication +url=https://github.com/lewisxhe/FT5206_Library +architectures=* architectures=esp32 \ No newline at end of file diff --git a/lib/FT5206_Library/src/FT5206.cpp b/lib_i2c/FT5206_Library/src/FT5206.cpp old mode 100755 new mode 100644 similarity index 96% rename from lib/FT5206_Library/src/FT5206.cpp rename to lib_i2c/FT5206_Library/src/FT5206.cpp index f0b106174..a8bea8621 --- a/lib/FT5206_Library/src/FT5206.cpp +++ b/lib_i2c/FT5206_Library/src/FT5206.cpp @@ -1,108 +1,108 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -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. - -FT5206.cpp - Arduino library for FT5206 chip. -Created by Lewis on April 17, 2019. -github:https://github.com/lewisxhe/FT5206_Library -*/ -///////////////////////////////////////////////////////////////// -#include "FT5206.h" - -int FT5206_Class::begin(TwoWire &port, uint8_t addr) -{ - _i2cPort = &port; - _address = addr; - uint8_t val; - _readByte(FT5206_VENDID_REG, 1, &val); - //Serial.printf("vend id %d\n",val ); - if (val != FT5206_VENDID) { - // return false; - } - _readByte(FT5206_CHIPID_REG, 1, &val); - //Serial.printf("chip id %d\n",val ); - if ((val != FT6206_CHIPID) && (val != FT6236_CHIPID) && (val != FT6236U_CHIPID) && (val != FT5206U_CHIPID) && (val != FT5316_CHIPID) ) { - return false; - } - _init = true; - return true; -} - -// valid touching detect threshold. -void FT5206_Class::adjustTheshold(uint8_t thresh) -{ - if (!_init)return; - _writeByte(FT5206_THRESHHOLD_REG, 1, &thresh); -} - -TP_Point FT5206_Class::getPoint(uint8_t num) -{ - if (!_init) return TP_Point(0, 0); - _readRegister(); - if ((_touches == 0) || (num > 1)) { - return TP_Point(0, 0); - } else { - return TP_Point(_x[num], _y[num]); - } -} - -uint8_t FT5206_Class::touched() -{ - if (!_init)return 0; - uint8_t val = 0; - _readByte(FT5206_TOUCHES_REG,1,&val); - return val > 2 ? 0: val; -} - -void FT5206_Class::enterSleepMode() -{ - if (!_init)return; - uint8_t val = FT5206_SLEEP_IN; - _writeByte(FT5206_POWER_REG, 1, &val); -} - -void FT5206_Class::enterMonitorMode() -{ - if (!_init)return; - uint8_t val = FT5206_MONITOR; - _writeByte(FT5206_POWER_REG, 1, &val); -} - -void FT5206_Class::_readRegister() -{ - _readByte(DEVIDE_MODE, 16, _data); - _touches = _data[TD_STATUS]; - if ((_touches > 2) || (_touches == 0)) { - _touches = 0; - return; - } - for (uint8_t i = 0; i < 2; i++) { - _x[i] = _data[TOUCH1_XH + i * 6] & 0x0F; - _x[i] <<= 8; - _x[i] |= _data[TOUCH1_XL + i * 6]; - _y[i] = _data[TOUCH1_YH + i * 6] & 0x0F; - _y[i] <<= 8; - _y[i] |= _data[TOUCH1_YL + i * 6]; - _id[i] = _data[TOUCH1_YH + i * 6] >> 4; - } -} +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +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. + +FT5206.cpp - Arduino library for FT5206 chip. +Created by Lewis on April 17, 2019. +github:https://github.com/lewisxhe/FT5206_Library +*/ +///////////////////////////////////////////////////////////////// +#include "FT5206.h" + +int FT5206_Class::begin(TwoWire &port, uint8_t addr) +{ + _i2cPort = &port; + _address = addr; + uint8_t val; + _readByte(FT5206_VENDID_REG, 1, &val); + //Serial.printf("vend id %d\n",val ); + if (val != FT5206_VENDID) { + // return false; + } + _readByte(FT5206_CHIPID_REG, 1, &val); + //Serial.printf("chip id %d\n",val ); + if ((val != FT6206_CHIPID) && (val != FT6236_CHIPID) && (val != FT6236U_CHIPID) && (val != FT5206U_CHIPID) && (val != FT5316_CHIPID) ) { + return false; + } + _init = true; + return true; +} + +// valid touching detect threshold. +void FT5206_Class::adjustTheshold(uint8_t thresh) +{ + if (!_init)return; + _writeByte(FT5206_THRESHHOLD_REG, 1, &thresh); +} + +TP_Point FT5206_Class::getPoint(uint8_t num) +{ + if (!_init) return TP_Point(0, 0); + _readRegister(); + if ((_touches == 0) || (num > 1)) { + return TP_Point(0, 0); + } else { + return TP_Point(_x[num], _y[num]); + } +} + +uint8_t FT5206_Class::touched() +{ + if (!_init)return 0; + uint8_t val = 0; + _readByte(FT5206_TOUCHES_REG,1,&val); + return val > 2 ? 0: val; +} + +void FT5206_Class::enterSleepMode() +{ + if (!_init)return; + uint8_t val = FT5206_SLEEP_IN; + _writeByte(FT5206_POWER_REG, 1, &val); +} + +void FT5206_Class::enterMonitorMode() +{ + if (!_init)return; + uint8_t val = FT5206_MONITOR; + _writeByte(FT5206_POWER_REG, 1, &val); +} + +void FT5206_Class::_readRegister() +{ + _readByte(DEVIDE_MODE, 16, _data); + _touches = _data[TD_STATUS]; + if ((_touches > 2) || (_touches == 0)) { + _touches = 0; + return; + } + for (uint8_t i = 0; i < 2; i++) { + _x[i] = _data[TOUCH1_XH + i * 6] & 0x0F; + _x[i] <<= 8; + _x[i] |= _data[TOUCH1_XL + i * 6]; + _y[i] = _data[TOUCH1_YH + i * 6] & 0x0F; + _y[i] <<= 8; + _y[i] |= _data[TOUCH1_YL + i * 6]; + _id[i] = _data[TOUCH1_YH + i * 6] >> 4; + } +} diff --git a/lib/FT5206_Library/src/FT5206.h b/lib_i2c/FT5206_Library/src/FT5206.h old mode 100755 new mode 100644 similarity index 96% rename from lib/FT5206_Library/src/FT5206.h rename to lib_i2c/FT5206_Library/src/FT5206.h index d8b6a8e3a..d4c07db5c --- a/lib/FT5206_Library/src/FT5206.h +++ b/lib_i2c/FT5206_Library/src/FT5206.h @@ -1,123 +1,123 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -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. - -FT5206.h - Arduino library for FT5206 chip. -Created by Lewis on April 17, 2019. -github:https://github.com/lewisxhe/FT5206_Library -*/ -///////////////////////////////////////////////////////////////// -#pragma once - -#include -#include - -#define FT5206_SLAVE_ADDRESS (0x38) -#define FT5206_MODE_REG (0x00) -#define FT5206_TOUCHES_REG (0x02) -#define FT5206_VENDID_REG (0xA8) -#define FT5206_CHIPID_REG (0xA3) -#define FT5206_THRESHHOLD_REG (0x80) -#define FT5206_POWER_REG (0x87) - -#define FT5206_MONITOR (0x01) -#define FT5206_SLEEP_IN (0x03) - -#define FT5206_VENDID 0x11 -#define FT6206_CHIPID 0x06 -#define FT6236_CHIPID 0x36 -#define FT6236U_CHIPID 0x64 -#define FT5206U_CHIPID 0x64 - -#define FT5316_CHIPID 0x0a - -#define DEVIDE_MODE 0x00 -#define TD_STATUS 0x02 -#define TOUCH1_XH 0x03 -#define TOUCH1_XL 0x04 -#define TOUCH1_YH 0x05 -#define TOUCH1_YL 0x06 - -class TP_Point -{ -public: - TP_Point(void) - { - x = 0; - y = 0; - } - TP_Point(int16_t _x, int16_t _y) - { - x = _x; - y = _y; - } - int16_t x; - int16_t y; -}; - - -class FT5206_Class -{ -public: - FT5206_Class() {}; - int begin(TwoWire &port = Wire, uint8_t addr = FT5206_SLAVE_ADDRESS); - // valid touching detect threshold. - void adjustTheshold(uint8_t thresh); - TP_Point getPoint(uint8_t num = 0); - uint8_t touched(); - void enterSleepMode(); - void enterMonitorMode(); -private: - void _readRegister(); - int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - _i2cPort->endTransmission(); - _i2cPort->requestFrom(_address, nbytes); - uint8_t index = 0; - while (_i2cPort->available()) - data[index++] = _i2cPort->read(); - return 0; - } - - int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - for (uint8_t i = 0; i < nbytes; i++) { - _i2cPort->write(data[i]); - } - _i2cPort->endTransmission(); - return 0; - } - - uint8_t _address; - uint8_t _data[16]; - uint16_t _x[2]; - uint16_t _y[2]; - uint16_t _id[2]; - uint8_t _touches = 0; - bool _init = false; - TwoWire *_i2cPort; -}; +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +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. + +FT5206.h - Arduino library for FT5206 chip. +Created by Lewis on April 17, 2019. +github:https://github.com/lewisxhe/FT5206_Library +*/ +///////////////////////////////////////////////////////////////// +#pragma once + +#include +#include + +#define FT5206_SLAVE_ADDRESS (0x38) +#define FT5206_MODE_REG (0x00) +#define FT5206_TOUCHES_REG (0x02) +#define FT5206_VENDID_REG (0xA8) +#define FT5206_CHIPID_REG (0xA3) +#define FT5206_THRESHHOLD_REG (0x80) +#define FT5206_POWER_REG (0x87) + +#define FT5206_MONITOR (0x01) +#define FT5206_SLEEP_IN (0x03) + +#define FT5206_VENDID 0x11 +#define FT6206_CHIPID 0x06 +#define FT6236_CHIPID 0x36 +#define FT6236U_CHIPID 0x64 +#define FT5206U_CHIPID 0x64 + +#define FT5316_CHIPID 0x0a + +#define DEVIDE_MODE 0x00 +#define TD_STATUS 0x02 +#define TOUCH1_XH 0x03 +#define TOUCH1_XL 0x04 +#define TOUCH1_YH 0x05 +#define TOUCH1_YL 0x06 + +class TP_Point +{ +public: + TP_Point(void) + { + x = 0; + y = 0; + } + TP_Point(int16_t _x, int16_t _y) + { + x = _x; + y = _y; + } + int16_t x; + int16_t y; +}; + + +class FT5206_Class +{ +public: + FT5206_Class() {}; + int begin(TwoWire &port = Wire, uint8_t addr = FT5206_SLAVE_ADDRESS); + // valid touching detect threshold. + void adjustTheshold(uint8_t thresh); + TP_Point getPoint(uint8_t num = 0); + uint8_t touched(); + void enterSleepMode(); + void enterMonitorMode(); +private: + void _readRegister(); + int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + _i2cPort->endTransmission(); + _i2cPort->requestFrom(_address, nbytes); + uint8_t index = 0; + while (_i2cPort->available()) + data[index++] = _i2cPort->read(); + return 0; + } + + int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + for (uint8_t i = 0; i < nbytes; i++) { + _i2cPort->write(data[i]); + } + _i2cPort->endTransmission(); + return 0; + } + + uint8_t _address; + uint8_t _data[16]; + uint16_t _x[2]; + uint16_t _y[2]; + uint16_t _id[2]; + uint8_t _touches = 0; + bool _init = false; + TwoWire *_i2cPort; +}; diff --git a/lib/FrogmoreScd30/FrogmoreScd30.cpp b/lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp similarity index 100% rename from lib/FrogmoreScd30/FrogmoreScd30.cpp rename to lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp diff --git a/lib/FrogmoreScd30/FrogmoreScd30.h b/lib_i2c/FrogmoreScd30/FrogmoreScd30.h similarity index 100% rename from lib/FrogmoreScd30/FrogmoreScd30.h rename to lib_i2c/FrogmoreScd30/FrogmoreScd30.h diff --git a/lib/FrogmoreScd30/library.properties b/lib_i2c/FrogmoreScd30/library.properties similarity index 100% rename from lib/FrogmoreScd30/library.properties rename to lib_i2c/FrogmoreScd30/library.properties diff --git a/lib/HPMA115S0/LICENSE.md b/lib_i2c/HPMA115S0/LICENSE.md similarity index 100% rename from lib/HPMA115S0/LICENSE.md rename to lib_i2c/HPMA115S0/LICENSE.md diff --git a/lib/HPMA115S0/README.md b/lib_i2c/HPMA115S0/README.md similarity index 100% rename from lib/HPMA115S0/README.md rename to lib_i2c/HPMA115S0/README.md diff --git a/lib/HPMA115S0/example/example.ino b/lib_i2c/HPMA115S0/example/example.ino similarity index 100% rename from lib/HPMA115S0/example/example.ino rename to lib_i2c/HPMA115S0/example/example.ino diff --git a/lib/HPMA115S0/library.properties b/lib_i2c/HPMA115S0/library.properties similarity index 100% rename from lib/HPMA115S0/library.properties rename to lib_i2c/HPMA115S0/library.properties diff --git a/lib/HPMA115S0/src/hpma115S0.cpp b/lib_i2c/HPMA115S0/src/hpma115S0.cpp similarity index 100% rename from lib/HPMA115S0/src/hpma115S0.cpp rename to lib_i2c/HPMA115S0/src/hpma115S0.cpp diff --git a/lib/HPMA115S0/src/hpma115S0.h b/lib_i2c/HPMA115S0/src/hpma115S0.h similarity index 100% rename from lib/HPMA115S0/src/hpma115S0.h rename to lib_i2c/HPMA115S0/src/hpma115S0.h diff --git a/lib/I2Cdevlib-Core/.library.json b/lib_i2c/I2Cdevlib-Core/.library.json similarity index 100% rename from lib/I2Cdevlib-Core/.library.json rename to lib_i2c/I2Cdevlib-Core/.library.json diff --git a/lib/I2Cdevlib-Core/I2Cdev.cpp b/lib_i2c/I2Cdevlib-Core/I2Cdev.cpp similarity index 100% rename from lib/I2Cdevlib-Core/I2Cdev.cpp rename to lib_i2c/I2Cdevlib-Core/I2Cdev.cpp diff --git a/lib/I2Cdevlib-Core/I2Cdev.h b/lib_i2c/I2Cdevlib-Core/I2Cdev.h similarity index 100% rename from lib/I2Cdevlib-Core/I2Cdev.h rename to lib_i2c/I2Cdevlib-Core/I2Cdev.h diff --git a/lib/I2Cdevlib-Core/keywords.txt b/lib_i2c/I2Cdevlib-Core/keywords.txt similarity index 100% rename from lib/I2Cdevlib-Core/keywords.txt rename to lib_i2c/I2Cdevlib-Core/keywords.txt diff --git a/lib/I2Cdevlib-Core/library.json b/lib_i2c/I2Cdevlib-Core/library.json similarity index 100% rename from lib/I2Cdevlib-Core/library.json rename to lib_i2c/I2Cdevlib-Core/library.json diff --git a/lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino similarity index 100% rename from lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino rename to lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino diff --git a/lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde similarity index 100% rename from lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde rename to lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde diff --git a/lib/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino b/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino similarity index 100% rename from lib/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino rename to lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino diff --git a/lib/I2Cdevlib-MPU6050/MPU6050.cpp b/lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp similarity index 100% rename from lib/I2Cdevlib-MPU6050/MPU6050.cpp rename to lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp diff --git a/lib/I2Cdevlib-MPU6050/MPU6050.h b/lib_i2c/I2Cdevlib-MPU6050/MPU6050.h similarity index 100% rename from lib/I2Cdevlib-MPU6050/MPU6050.h rename to lib_i2c/I2Cdevlib-MPU6050/MPU6050.h diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h similarity index 100% rename from lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h rename to lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h b/lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h similarity index 100% rename from lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h rename to lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h diff --git a/lib/I2Cdevlib-MPU6050/helper_3dmath.h b/lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h similarity index 100% rename from lib/I2Cdevlib-MPU6050/helper_3dmath.h rename to lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h diff --git a/lib/I2Cdevlib-MPU6050/library.properties b/lib_i2c/I2Cdevlib-MPU6050/library.properties similarity index 100% rename from lib/I2Cdevlib-MPU6050/library.properties rename to lib_i2c/I2Cdevlib-MPU6050/library.properties diff --git a/lib/Joba_Tsl2561-2.0.10/.gitignore b/lib_i2c/Joba_Tsl2561-2.0.10/.gitignore similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/.gitignore rename to lib_i2c/Joba_Tsl2561-2.0.10/.gitignore diff --git a/lib/Joba_Tsl2561-2.0.10/.hgignore b/lib_i2c/Joba_Tsl2561-2.0.10/.hgignore similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/.hgignore rename to lib_i2c/Joba_Tsl2561-2.0.10/.hgignore diff --git a/lib/Joba_Tsl2561-2.0.10/.travis.yml b/lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/.travis.yml rename to lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml diff --git a/lib/Joba_Tsl2561-2.0.10/COPYING b/lib_i2c/Joba_Tsl2561-2.0.10/COPYING similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/COPYING rename to lib_i2c/Joba_Tsl2561-2.0.10/COPYING diff --git a/lib/Joba_Tsl2561-2.0.10/COPYING.LESSER b/lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/COPYING.LESSER rename to lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER diff --git a/lib/Joba_Tsl2561-2.0.10/README b/lib_i2c/Joba_Tsl2561-2.0.10/README similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/README rename to lib_i2c/Joba_Tsl2561-2.0.10/README diff --git a/lib/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino b/lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino diff --git a/lib/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino b/lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino diff --git a/lib/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino b/lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino diff --git a/lib/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino b/lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino diff --git a/lib/Joba_Tsl2561-2.0.10/examples/platformio.ini b/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/platformio.ini rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini diff --git a/lib/Joba_Tsl2561-2.0.10/examples/platformio.sh b/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/examples/platformio.sh rename to lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh diff --git a/lib/Joba_Tsl2561-2.0.10/lib/readme.txt b/lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/lib/readme.txt rename to lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt diff --git a/lib/Joba_Tsl2561-2.0.10/library.json b/lib_i2c/Joba_Tsl2561-2.0.10/library.json similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/library.json rename to lib_i2c/Joba_Tsl2561-2.0.10/library.json diff --git a/lib/Joba_Tsl2561-2.0.10/library.properties b/lib_i2c/Joba_Tsl2561-2.0.10/library.properties similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/library.properties rename to lib_i2c/Joba_Tsl2561-2.0.10/library.properties diff --git a/lib/Joba_Tsl2561-2.0.10/platformio.ini b/lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/platformio.ini rename to lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini diff --git a/lib/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp b/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp rename to lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp diff --git a/lib/Joba_Tsl2561-2.0.10/src/Tsl2561.h b/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/src/Tsl2561.h rename to lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h diff --git a/lib/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp b/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp rename to lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp diff --git a/lib/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h b/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h similarity index 100% rename from lib/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h rename to lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h diff --git a/lib/LOLIN_HP303B/README.md b/lib_i2c/LOLIN_HP303B/README.md similarity index 100% rename from lib/LOLIN_HP303B/README.md rename to lib_i2c/LOLIN_HP303B/README.md diff --git a/lib/LOLIN_HP303B/examples/i2c_background/i2c_background.ino b/lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino similarity index 100% rename from lib/LOLIN_HP303B/examples/i2c_background/i2c_background.ino rename to lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino diff --git a/lib/LOLIN_HP303B/examples/i2c_command/i2c_command.ino b/lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino similarity index 100% rename from lib/LOLIN_HP303B/examples/i2c_command/i2c_command.ino rename to lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino diff --git a/lib/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino b/lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino similarity index 100% rename from lib/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino rename to lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino diff --git a/lib/LOLIN_HP303B/examples/library.properties b/lib_i2c/LOLIN_HP303B/examples/library.properties similarity index 100% rename from lib/LOLIN_HP303B/examples/library.properties rename to lib_i2c/LOLIN_HP303B/examples/library.properties diff --git a/lib/LOLIN_HP303B/keywords.txt b/lib_i2c/LOLIN_HP303B/keywords.txt similarity index 100% rename from lib/LOLIN_HP303B/keywords.txt rename to lib_i2c/LOLIN_HP303B/keywords.txt diff --git a/lib/LOLIN_HP303B/library.properties b/lib_i2c/LOLIN_HP303B/library.properties similarity index 100% rename from lib/LOLIN_HP303B/library.properties rename to lib_i2c/LOLIN_HP303B/library.properties diff --git a/lib/LOLIN_HP303B/src/LOLIN_HP303B.cpp b/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp similarity index 100% rename from lib/LOLIN_HP303B/src/LOLIN_HP303B.cpp rename to lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp diff --git a/lib/LOLIN_HP303B/src/LOLIN_HP303B.h b/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h similarity index 100% rename from lib/LOLIN_HP303B/src/LOLIN_HP303B.h rename to lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h diff --git a/lib/LOLIN_HP303B/src/util/hp303b_consts.h b/lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h similarity index 100% rename from lib/LOLIN_HP303B/src/util/hp303b_consts.h rename to lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h diff --git a/lib/LinkedList-1.2.3/LICENSE.txt b/lib_i2c/LinkedList-1.2.3/LICENSE.txt similarity index 100% rename from lib/LinkedList-1.2.3/LICENSE.txt rename to lib_i2c/LinkedList-1.2.3/LICENSE.txt diff --git a/lib/LinkedList-1.2.3/LinkedList.h b/lib_i2c/LinkedList-1.2.3/LinkedList.h old mode 100755 new mode 100644 similarity index 100% rename from lib/LinkedList-1.2.3/LinkedList.h rename to lib_i2c/LinkedList-1.2.3/LinkedList.h diff --git a/lib/LinkedList-1.2.3/README.md b/lib_i2c/LinkedList-1.2.3/README.md similarity index 100% rename from lib/LinkedList-1.2.3/README.md rename to lib_i2c/LinkedList-1.2.3/README.md diff --git a/lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde b/lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde similarity index 100% rename from lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde rename to lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde diff --git a/lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde b/lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde similarity index 100% rename from lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde rename to lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde diff --git a/lib/LinkedList-1.2.3/keywords.txt b/lib_i2c/LinkedList-1.2.3/keywords.txt similarity index 100% rename from lib/LinkedList-1.2.3/keywords.txt rename to lib_i2c/LinkedList-1.2.3/keywords.txt diff --git a/lib/LinkedList-1.2.3/library.json b/lib_i2c/LinkedList-1.2.3/library.json similarity index 100% rename from lib/LinkedList-1.2.3/library.json rename to lib_i2c/LinkedList-1.2.3/library.json diff --git a/lib/LinkedList-1.2.3/library.properties b/lib_i2c/LinkedList-1.2.3/library.properties similarity index 100% rename from lib/LinkedList-1.2.3/library.properties rename to lib_i2c/LinkedList-1.2.3/library.properties diff --git a/lib/Mutichannel_Gas_Sensor/License.txt b/lib_i2c/Mutichannel_Gas_Sensor/License.txt similarity index 100% rename from lib/Mutichannel_Gas_Sensor/License.txt rename to lib_i2c/Mutichannel_Gas_Sensor/License.txt diff --git a/lib/Mutichannel_Gas_Sensor/README.md b/lib_i2c/Mutichannel_Gas_Sensor/README.md similarity index 100% rename from lib/Mutichannel_Gas_Sensor/README.md rename to lib_i2c/Mutichannel_Gas_Sensor/README.md diff --git a/lib/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h b/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h rename to lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h diff --git a/lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt b/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt rename to lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt diff --git a/lib/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino diff --git a/lib/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino b/lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino similarity index 100% rename from lib/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino rename to lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino diff --git a/lib/Mutichannel_Gas_Sensor/library.json b/lib_i2c/Mutichannel_Gas_Sensor/library.json similarity index 100% rename from lib/Mutichannel_Gas_Sensor/library.json rename to lib_i2c/Mutichannel_Gas_Sensor/library.json diff --git a/lib/Mutichannel_Gas_Sensor/library.properties b/lib_i2c/Mutichannel_Gas_Sensor/library.properties similarity index 100% rename from lib/Mutichannel_Gas_Sensor/library.properties rename to lib_i2c/Mutichannel_Gas_Sensor/library.properties diff --git a/lib/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp b/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp similarity index 100% rename from lib/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp rename to lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp diff --git a/lib/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h b/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h similarity index 100% rename from lib/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h rename to lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h diff --git a/lib/mlx90640-library/MLX90640_API.cpp b/lib_i2c/mlx90640-library/MLX90640_API.cpp similarity index 96% rename from lib/mlx90640-library/MLX90640_API.cpp rename to lib_i2c/mlx90640-library/MLX90640_API.cpp index 87d871530..8b1822bf4 100644 --- a/lib/mlx90640-library/MLX90640_API.cpp +++ b/lib_i2c/mlx90640-library/MLX90640_API.cpp @@ -1,1640 +1,1640 @@ -/** - * @copyright (C) 2017 Melexis N.V. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include - -void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); -int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640); -int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2); -float GetMedian(float *values, int n); -int IsPixelBad(uint16_t pixel,paramsMLX90640 *params); -int ValidateFrameData(uint16_t *frameData); -int ValidateAuxData(uint16_t *auxData); -int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data); -int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data); - -// I2C -#define I2C_BUFFER_LENGTH 128 - -int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data){ - int bytesRemaining = len * 2; - int dataSpot = 0; //Start at beginning of array - while (bytesRemaining > 0) - { - Wire.beginTransmission(addr); - Wire.write(reg >> 8); //MSB - Wire.write(reg & 0xFF); //LSB - if (Wire.endTransmission(false) != 0) //Do not release bus - { - return (0); //Sensor did not ACK - } - int numberOfBytesToRead = bytesRemaining; - if (numberOfBytesToRead > I2C_BUFFER_LENGTH) numberOfBytesToRead = I2C_BUFFER_LENGTH; - Wire.requestFrom((int)addr, numberOfBytesToRead); - if (Wire.available()) - { - for (uint32_t x = 0 ; x < numberOfBytesToRead / 2; x++) - { - reg_data[dataSpot] = Wire.read() << 8; //MSB - reg_data[dataSpot] |= Wire.read(); //LSB - dataSpot++; - } - } - bytesRemaining -= numberOfBytesToRead; - reg += numberOfBytesToRead / 2; - } - return (0); //Success -} - -int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data) -{ - Wire.beginTransmission((uint8_t)_deviceAddress); - Wire.write(writeAddress >> 8); //MSB - Wire.write(writeAddress & 0xFF); //LSB - Wire.write(data >> 8); //MSB - Wire.write(data & 0xFF); //LSB - if (Wire.endTransmission() != 0) - { - //Sensor did not ACK - return (-1); - } - uint16_t dataCheck; - MLX90640_I2CRead(_deviceAddress, writeAddress, 1, &dataCheck); - if (dataCheck != data) - { - return -2; - } - return (0); //Success -} - -int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData) -{ - return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData); -} - -int MLX90640_SynchFrame(uint8_t slaveAddr) -{ - uint16_t dataReady = 0; - uint16_t statusRegister; - int error = 1; - - error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); - if(error == -1) - { - return error; - } - - while(dataReady == 0) - { - error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); - if(error != 0) - { - return error; - } - dataReady = statusRegister & 0x0008; - } - - return 0; -} - -// int MLX90640_TriggerMeasurement(uint8_t slaveAddr) // ATM not used in Tasmota -// { -// int error = 1; -// uint16_t ctrlReg; - -// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); - -// if ( error != 0) -// { -// return error; -// } - -// ctrlReg |= 0x8000; -// error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg); - -// if ( error != 0) -// { -// return error; -// } - -// // error = MLX90640_I2CGeneralReset(); - -// // if ( error != 0) -// // { -// // return error; -// // } - -// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); - -// if ( error != 0) -// { -// return error; -// } - -// if ((ctrlReg & 0x8000) != 0) -// { -// return -9; -// } - -// return 0; -// } - -int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) -{ - uint16_t dataReady = 0; - uint16_t controlRegister1; - uint16_t statusRegister; - int error = 1; - uint16_t data[64]; - uint8_t cnt = 0; - - while(dataReady == 0) - { - error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); - if(error != 0) - { - return error; - } - dataReady = statusRegister & 0x0008; - } - - error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); - if(error == -1) - { - return error; - } - - error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData); - if(error != 0) - { - return error; - } - - error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data); - if(error != 0) - { - return error; - } - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - frameData[832] = controlRegister1; - frameData[833] = statusRegister & 0x0001; - - if(error != 0) - { - return error; - } - - error = ValidateAuxData(data); - if(error == 0) - { - for(cnt=0; cnt<64; cnt++) - { - frameData[cnt+768] = data[cnt]; - } - } - - error = ValidateFrameData(frameData); - if (error != 0) - { - return error; - } - - return frameData[833]; -} - -int ValidateFrameData(uint16_t *frameData) -{ - uint8_t line = 0; - - for(int i=0; i<768; i+=32) - { - if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8; - line = line + 1; - } - - return 0; -} - -int ValidateAuxData(uint16_t *auxData) -{ - - if(auxData[0] == 0x7FFF) return -8; - - for(int i=8; i<19; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - for(int i=20; i<23; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - for(int i=24; i<33; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - for(int i=40; i<51; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - for(int i=52; i<55; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - for(int i=56; i<64; i++) - { - if(auxData[i] == 0x7FFF) return -8; - } - - return 0; - -} - -int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640, int _chunk) // Tasmota -{ - int error = 0; - switch(_chunk){ - case 0: - ExtractVDDParameters(eeData, mlx90640); - ExtractPTATParameters(eeData, mlx90640); - ExtractGainParameters(eeData, mlx90640); - ExtractTgcParameters(eeData, mlx90640); - ExtractResolutionParameters(eeData, mlx90640); - ExtractKsTaParameters(eeData, mlx90640); - ExtractKsToParameters(eeData, mlx90640); - break; - case 1: - ExtractCPParameters(eeData, mlx90640); - ExtractAlphaParameters(eeData, mlx90640); - break; - case 2: - ExtractOffsetParameters(eeData, mlx90640); - break; - case 3: - ExtractKtaPixelParameters(eeData, mlx90640); - break; - case 4: - ExtractKvPixelParameters(eeData, mlx90640); - break; - case 5: - ExtractCILCParameters(eeData, mlx90640); - error = ExtractDeviatingPixels(eeData, mlx90640); - break; - } - return error; -} - -//------------------------------------------------------------------------------ - -int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution) -{ - uint16_t controlRegister1; - int value; - int error; - - value = (resolution & 0x03) << 10; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - - if(error == 0) - { - value = (controlRegister1 & 0xF3FF) | value; - error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); - } - - return error; -} - -//------------------------------------------------------------------------------ - -int MLX90640_GetCurResolution(uint8_t slaveAddr) -{ - uint16_t controlRegister1; - int resolutionRAM; - int error; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - if(error != 0) - { - return error; - } - resolutionRAM = (controlRegister1 & 0x0C00) >> 10; - - return resolutionRAM; -} - -//------------------------------------------------------------------------------ - -int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate) -{ - uint16_t controlRegister1; - int value; - int error; - - value = (refreshRate & 0x07)<<7; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - if(error == 0) - { - value = (controlRegister1 & 0xFC7F) | value; - error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); - } - - return error; -} - -//------------------------------------------------------------------------------ - -int MLX90640_GetRefreshRate(uint8_t slaveAddr) -{ - uint16_t controlRegister1; - int refreshRate; - int error; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - if(error != 0) - { - return error; - } - refreshRate = (controlRegister1 & 0x0380) >> 7; - - return refreshRate; -} - -//------------------------------------------------------------------------------ - -int MLX90640_SetInterleavedMode(uint8_t slaveAddr) -{ - uint16_t controlRegister1; - int value; - int error; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - - if(error == 0) - { - value = (controlRegister1 & 0xEFFF); - error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); - } - - return error; -} - -//------------------------------------------------------------------------------ - -int MLX90640_SetChessMode(uint8_t slaveAddr) -{ - uint16_t controlRegister1; - int value; - int error; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - - if(error == 0) - { - value = (controlRegister1 | 0x1000); - error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); - } - - return error; -} - -//------------------------------------------------------------------------------ - -int MLX90640_GetCurMode(uint8_t slaveAddr) -{ - uint16_t controlRegister1; - int modeRAM; - int error; - - error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); - if(error != 0) - { - return error; - } - modeRAM = (controlRegister1 & 0x1000) >> 12; - - return modeRAM; -} - -//------------------------------------------------------------------------------ -void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part) -{ - float vdd; - float ta; - float ta4; - float tr4; - float taTr; - float gain; - float irDataCP[2]; - float irData; - float alphaCompensated; - uint8_t mode; - int8_t ilPattern; - int8_t chessPattern; - int8_t pattern; - int8_t conversionPattern; - float Sx; - float To; - float alphaCorrR[4]; - int8_t range; - uint16_t subPage; - float ktaScale; - float kvScale; - float alphaScale; - float kta; - float kv; - - subPage = frameData[833]; - vdd = MLX90640_GetVdd(frameData, params); - ta = MLX90640_GetTa(frameData, params); - - ta4 = (ta + 273.15); - ta4 = ta4 * ta4; - ta4 = ta4 * ta4; - tr4 = (tr + 273.15); - tr4 = tr4 * tr4; - tr4 = tr4 * tr4; - taTr = tr4 - (tr4-ta4)/emissivity; - - ktaScale = pow(2,(double)params->ktaScale); - kvScale = pow(2,(double)params->kvScale); - alphaScale = pow(2,(double)params->alphaScale); - - alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40); - alphaCorrR[1] = 1 ; - alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]); - alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2])); - -//------------------------- Gain calculation ----------------------------------- - gain = frameData[778]; - if(gain > 32767) - { - gain = gain - 65536; - } - - gain = params->gainEE / gain; - -//------------------------- To calculation ------------------------------------- - mode = (frameData[832] & 0x1000) >> 5; - - irDataCP[0] = frameData[776]; - irDataCP[1] = frameData[808]; - for( int i = 0; i < 2; i++) - { - if(irDataCP[i] > 32767) - { - irDataCP[i] = irDataCP[i] - 65536; - } - irDataCP[i] = irDataCP[i] * gain; - } - irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); - if( mode == params->calibrationModeEE) - { - irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); - } - else - { - irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); - } - - uint32_t _offset = _part*(768/2); - for( int pixelNumber = _offset; pixelNumber < (_offset+(768/2)); pixelNumber++) - { - ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; - chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); - conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); - - if(mode == 0) - { - pattern = ilPattern; - } - else - { - pattern = chessPattern; - } - - if(pattern == frameData[833]) - { - irData = frameData[pixelNumber]; - if(irData > 32767) - { - irData = irData - 65536; - } - irData = irData * gain; - - kta = params->kta[pixelNumber]/ktaScale; - kv = params->kv[pixelNumber]/kvScale; - irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); - - if(mode != params->calibrationModeEE) - { - irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; - } - - irData = irData - params->tgc * irDataCP[subPage]; - irData = irData / emissivity; - - alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber]; - alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25)); - - Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr); - Sx = sqrt(sqrt(Sx)) * params->ksTo[1]; - - To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15; - - if(To < params->ct[1]) - { - range = 0; - } - else if(To < params->ct[2]) - { - range = 1; - } - else if(To < params->ct[3]) - { - range = 2; - } - else - { - range = 3; - } - - To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15; - - result[pixelNumber] = To; - } - } -} - -//------------------------------------------------------------------------------ - -// void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result) -// { -// float vdd; -// float ta; -// float gain; -// float irDataCP[2]; -// float irData; -// float alphaCompensated; -// uint8_t mode; -// int8_t ilPattern; -// int8_t chessPattern; -// int8_t pattern; -// int8_t conversionPattern; -// float image; -// uint16_t subPage; -// float ktaScale; -// float kvScale; -// float kta; -// float kv; - -// subPage = frameData[833]; -// vdd = MLX90640_GetVdd(frameData, params); -// ta = MLX90640_GetTa(frameData, params); - -// ktaScale = pow(2,(double)params->ktaScale); -// kvScale = pow(2,(double)params->kvScale); - -// //------------------------- Gain calculation ----------------------------------- -// gain = frameData[778]; -// if(gain > 32767) -// { -// gain = gain - 65536; -// } - -// gain = params->gainEE / gain; - -// //------------------------- Image calculation ------------------------------------- -// mode = (frameData[832] & 0x1000) >> 5; - -// irDataCP[0] = frameData[776]; -// irDataCP[1] = frameData[808]; -// for( int i = 0; i < 2; i++) -// { -// if(irDataCP[i] > 32767) -// { -// irDataCP[i] = irDataCP[i] - 65536; -// } -// irDataCP[i] = irDataCP[i] * gain; -// } -// irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); -// if( mode == params->calibrationModeEE) -// { -// irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); -// } -// else -// { -// irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); -// } - -// for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++) -// { -// ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; -// chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); -// conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); - -// if(mode == 0) -// { -// pattern = ilPattern; -// } -// else -// { -// pattern = chessPattern; -// } - -// if(pattern == frameData[833]) -// { -// irData = frameData[pixelNumber]; -// if(irData > 32767) -// { -// irData = irData - 65536; -// } -// irData = irData * gain; - -// kta = params->kta[pixelNumber]/ktaScale; -// kv = params->kv[pixelNumber]/kvScale; -// irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); - -// if(mode != params->calibrationModeEE) -// { -// irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; -// } - -// irData = irData - params->tgc * irDataCP[subPage]; - -// alphaCompensated = params->alpha[pixelNumber]; - -// image = irData*alphaCompensated; - -// result[pixelNumber] = image; -// } -// } -// } - -//------------------------------------------------------------------------------ - -float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params) -{ - float vdd; - float resolutionCorrection; - - int resolutionRAM; - - vdd = frameData[810]; - if(vdd > 32767) - { - vdd = vdd - 65536; - } - resolutionRAM = (frameData[832] & 0x0C00) >> 10; - resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM); - vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3; - - return vdd; -} - -//------------------------------------------------------------------------------ - -float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params) -{ - float ptat; - float ptatArt; - float vdd; - float ta; - - vdd = MLX90640_GetVdd(frameData, params); - - ptat = frameData[800]; - if(ptat > 32767) - { - ptat = ptat - 65536; - } - - ptatArt = frameData[768]; - if(ptatArt > 32767) - { - ptatArt = ptatArt - 65536; - } - ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18); - - ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25); - ta = ta / params->KtPTAT + 25; - - return ta; -} - -//------------------------------------------------------------------------------ - -int MLX90640_GetSubPageNumber(uint16_t *frameData) -{ - return frameData[833]; - -} - -//------------------------------------------------------------------------------ -void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params) -{ - float ap[4]; - uint8_t pix; - uint8_t line; - uint8_t column; - - pix = 0; - while(pixels[pix] != 0xFFFF) - { - line = pixels[pix]>>5; - column = pixels[pix] - (line<<5); - - if(mode == 1) - { - if(line == 0) - { - if(column == 0) - { - to[pixels[pix]] = to[33]; - } - else if(column == 31) - { - to[pixels[pix]] = to[62]; - } - else - { - to[pixels[pix]] = (to[pixels[pix]+31] + to[pixels[pix]+33])/2.0; - } - } - else if(line == 23) - { - if(column == 0) - { - to[pixels[pix]] = to[705]; - } - else if(column == 31) - { - to[pixels[pix]] = to[734]; - } - else - { - to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]-31])/2.0; - } - } - else if(column == 0) - { - to[pixels[pix]] = (to[pixels[pix]-31] + to[pixels[pix]+33])/2.0; - } - else if(column == 31) - { - to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]+31])/2.0; - } - else - { - ap[0] = to[pixels[pix]-33]; - ap[1] = to[pixels[pix]-31]; - ap[2] = to[pixels[pix]+31]; - ap[3] = to[pixels[pix]+33]; - to[pixels[pix]] = GetMedian(ap,4); - } - } - else - { - if(column == 0) - { - to[pixels[pix]] = to[pixels[pix]+1]; - } - else if(column == 1 || column == 30) - { - to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; - } - else if(column == 31) - { - to[pixels[pix]] = to[pixels[pix]-1]; - } - else - { - if(IsPixelBad(pixels[pix]-2,params) == 0 && IsPixelBad(pixels[pix]+2,params) == 0) - { - ap[0] = to[pixels[pix]+1] - to[pixels[pix]+2]; - ap[1] = to[pixels[pix]-1] - to[pixels[pix]-2]; - if(fabs(ap[0]) > fabs(ap[1])) - { - to[pixels[pix]] = to[pixels[pix]-1] + ap[1]; - } - else - { - to[pixels[pix]] = to[pixels[pix]+1] + ap[0]; - } - } - else - { - to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; - } - } - } - pix = pix + 1; - } -} - -//------------------------------------------------------------------------------ - -void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int16_t kVdd; - int16_t vdd25; - - kVdd = eeData[51]; - - kVdd = (eeData[51] & 0xFF00) >> 8; - if(kVdd > 127) - { - kVdd = kVdd - 256; - } - kVdd = 32 * kVdd; - vdd25 = eeData[51] & 0x00FF; - vdd25 = ((vdd25 - 256) << 5) - 8192; - - mlx90640->kVdd = kVdd; - mlx90640->vdd25 = vdd25; -} - -//------------------------------------------------------------------------------ - -void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - float KvPTAT; - float KtPTAT; - int16_t vPTAT25; - float alphaPTAT; - - KvPTAT = (eeData[50] & 0xFC00) >> 10; - if(KvPTAT > 31) - { - KvPTAT = KvPTAT - 64; - } - KvPTAT = KvPTAT/4096; - - KtPTAT = eeData[50] & 0x03FF; - if(KtPTAT > 511) - { - KtPTAT = KtPTAT - 1024; - } - KtPTAT = KtPTAT/8; - - vPTAT25 = eeData[49]; - - alphaPTAT = (eeData[16] & 0xF000) / pow(2, (double)14) + 8.0f; - - mlx90640->KvPTAT = KvPTAT; - mlx90640->KtPTAT = KtPTAT; - mlx90640->vPTAT25 = vPTAT25; - mlx90640->alphaPTAT = alphaPTAT; -} - -//------------------------------------------------------------------------------ - -void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int16_t gainEE; - - gainEE = eeData[48]; - if(gainEE > 32767) - { - gainEE = gainEE -65536; - } - - mlx90640->gainEE = gainEE; -} - -//------------------------------------------------------------------------------ - -void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - float tgc; - tgc = eeData[60] & 0x00FF; - if(tgc > 127) - { - tgc = tgc - 256; - } - tgc = tgc / 32.0f; - - mlx90640->tgc = tgc; -} - -//------------------------------------------------------------------------------ - -void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - uint8_t resolutionEE; - resolutionEE = (eeData[56] & 0x3000) >> 12; - - mlx90640->resolutionEE = resolutionEE; -} - -//------------------------------------------------------------------------------ - -void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - float KsTa; - KsTa = (eeData[60] & 0xFF00) >> 8; - if(KsTa > 127) - { - KsTa = KsTa -256; - } - KsTa = KsTa / 8192.0f; - - mlx90640->KsTa = KsTa; -} - -//------------------------------------------------------------------------------ - -void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int KsToScale; - int8_t step; - - step = ((eeData[63] & 0x3000) >> 12) * 10; - - mlx90640->ct[0] = -40; - mlx90640->ct[1] = 0; - mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4; - mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8; - - mlx90640->ct[2] = mlx90640->ct[2]*step; - mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step; - mlx90640->ct[4] = 400; - - KsToScale = (eeData[63] & 0x000F) + 8; - KsToScale = 1 << KsToScale; - - mlx90640->ksTo[0] = eeData[61] & 0x00FF; - mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8; - mlx90640->ksTo[2] = eeData[62] & 0x00FF; - mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8; - - for(int i = 0; i < 4; i++) - { - if(mlx90640->ksTo[i] > 127) - { - mlx90640->ksTo[i] = mlx90640->ksTo[i] - 256; - } - mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale; - } - - mlx90640->ksTo[4] = -0.0002; -} - -//------------------------------------------------------------------------------ - -void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int accRow[24]; - int accColumn[32]; - int p = 0; - int alphaRef; - uint8_t alphaScale; - uint8_t accRowScale; - uint8_t accColumnScale; - uint8_t accRemScale; - float alphaTemp[768]; - float temp; - - - accRemScale = eeData[32] & 0x000F; - accColumnScale = (eeData[32] & 0x00F0) >> 4; - accRowScale = (eeData[32] & 0x0F00) >> 8; - alphaScale = ((eeData[32] & 0xF000) >> 12) + 30; - alphaRef = eeData[33]; - - for(int i = 0; i < 6; i++) - { - p = i * 4; - accRow[p + 0] = (eeData[34 + i] & 0x000F); - accRow[p + 1] = (eeData[34 + i] & 0x00F0) >> 4; - accRow[p + 2] = (eeData[34 + i] & 0x0F00) >> 8; - accRow[p + 3] = (eeData[34 + i] & 0xF000) >> 12; - } - - for(int i = 0; i < 24; i++) - { - if (accRow[i] > 7) - { - accRow[i] = accRow[i] - 16; - } - } - - for(int i = 0; i < 8; i++) - { - p = i * 4; - accColumn[p + 0] = (eeData[40 + i] & 0x000F); - accColumn[p + 1] = (eeData[40 + i] & 0x00F0) >> 4; - accColumn[p + 2] = (eeData[40 + i] & 0x0F00) >> 8; - accColumn[p + 3] = (eeData[40 + i] & 0xF000) >> 12; - } - - for(int i = 0; i < 32; i ++) - { - if (accColumn[i] > 7) - { - accColumn[i] = accColumn[i] - 16; - } - } - - for(int i = 0; i < 24; i++) - { - for(int j = 0; j < 32; j ++) - { - p = 32 * i +j; - alphaTemp[p] = (eeData[64 + p] & 0x03F0) >> 4; - if (alphaTemp[p] > 31) - { - alphaTemp[p] = alphaTemp[p] - 64; - } - alphaTemp[p] = alphaTemp[p]*(1 << accRemScale); - alphaTemp[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + alphaTemp[p]); - alphaTemp[p] = alphaTemp[p] / pow(2,(double)alphaScale); - alphaTemp[p] = alphaTemp[p] - mlx90640->tgc * (mlx90640->cpAlpha[0] + mlx90640->cpAlpha[1])/2; - alphaTemp[p] = SCALEALPHA/alphaTemp[p]; - } - } - - temp = alphaTemp[0]; - for(int i = 1; i < 768; i++) - { - if (alphaTemp[i] > temp) - { - temp = alphaTemp[i]; - } - } - - alphaScale = 0; - while(temp < 32767.4) - { - temp = temp*2; - alphaScale = alphaScale + 1; - } - - for(int i = 0; i < 768; i++) - { - temp = alphaTemp[i] * pow(2,(double)alphaScale); - mlx90640->alpha[i] = (temp + 0.5); - - } - - mlx90640->alphaScale = alphaScale; - -} - -//------------------------------------------------------------------------------ - -void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int occRow[24]; - int occColumn[32]; - int p = 0; - int16_t offsetRef; - uint8_t occRowScale; - uint8_t occColumnScale; - uint8_t occRemScale; - - - occRemScale = (eeData[16] & 0x000F); - occColumnScale = (eeData[16] & 0x00F0) >> 4; - occRowScale = (eeData[16] & 0x0F00) >> 8; - offsetRef = eeData[17]; - if (offsetRef > 32767) - { - offsetRef = offsetRef - 65536; - } - - for(int i = 0; i < 6; i++) - { - p = i * 4; - occRow[p + 0] = (eeData[18 + i] & 0x000F); - occRow[p + 1] = (eeData[18 + i] & 0x00F0) >> 4; - occRow[p + 2] = (eeData[18 + i] & 0x0F00) >> 8; - occRow[p + 3] = (eeData[18 + i] & 0xF000) >> 12; - } - - for(int i = 0; i < 24; i++) - { - if (occRow[i] > 7) - { - occRow[i] = occRow[i] - 16; - } - } - - for(int i = 0; i < 8; i++) - { - p = i * 4; - occColumn[p + 0] = (eeData[24 + i] & 0x000F); - occColumn[p + 1] = (eeData[24 + i] & 0x00F0) >> 4; - occColumn[p + 2] = (eeData[24 + i] & 0x0F00) >> 8; - occColumn[p + 3] = (eeData[24 + i] & 0xF000) >> 12; - } - - for(int i = 0; i < 32; i ++) - { - if (occColumn[i] > 7) - { - occColumn[i] = occColumn[i] - 16; - } - } - - for(int i = 0; i < 24; i++) - { - for(int j = 0; j < 32; j ++) - { - p = 32 * i +j; - mlx90640->offset[p] = (eeData[64 + p] & 0xFC00) >> 10; - if (mlx90640->offset[p] > 31) - { - mlx90640->offset[p] = mlx90640->offset[p] - 64; - } - mlx90640->offset[p] = mlx90640->offset[p]*(1 << occRemScale); - mlx90640->offset[p] = (offsetRef + (occRow[i] << occRowScale) + (occColumn[j] << occColumnScale) + mlx90640->offset[p]); - } - } -} - -//------------------------------------------------------------------------------ - -void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int p = 0; - int8_t KtaRC[4]; - int8_t KtaRoCo; - int8_t KtaRoCe; - int8_t KtaReCo; - int8_t KtaReCe; - uint8_t ktaScale1; - uint8_t ktaScale2; - uint8_t split; - float ktaTemp[768]; - float temp; - - KtaRoCo = (eeData[54] & 0xFF00) >> 8; - if (KtaRoCo > 127) - { - KtaRoCo = KtaRoCo - 256; - } - KtaRC[0] = KtaRoCo; - - KtaReCo = (eeData[54] & 0x00FF); - if (KtaReCo > 127) - { - KtaReCo = KtaReCo - 256; - } - KtaRC[2] = KtaReCo; - - KtaRoCe = (eeData[55] & 0xFF00) >> 8; - if (KtaRoCe > 127) - { - KtaRoCe = KtaRoCe - 256; - } - KtaRC[1] = KtaRoCe; - - KtaReCe = (eeData[55] & 0x00FF); - if (KtaReCe > 127) - { - KtaReCe = KtaReCe - 256; - } - KtaRC[3] = KtaReCe; - - ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; - ktaScale2 = (eeData[56] & 0x000F); - - for(int i = 0; i < 24; i++) - { - for(int j = 0; j < 32; j ++) - { - p = 32 * i +j; - split = 2*(p/32 - (p/64)*2) + p%2; - ktaTemp[p] = (eeData[64 + p] & 0x000E) >> 1; - if (ktaTemp[p] > 3) - { - ktaTemp[p] = ktaTemp[p] - 8; - } - ktaTemp[p] = ktaTemp[p] * (1 << ktaScale2); - ktaTemp[p] = KtaRC[split] + ktaTemp[p]; - ktaTemp[p] = ktaTemp[p] / pow(2,(double)ktaScale1); - //ktaTemp[p] = ktaTemp[p] * mlx90640->offset[p]; - } - } - - temp = fabs(ktaTemp[0]); - for(int i = 1; i < 768; i++) - { - if (fabs(ktaTemp[i]) > temp) - { - temp = fabs(ktaTemp[i]); - } - } - - ktaScale1 = 0; - while(temp < 63.4) - { - temp = temp*2; - ktaScale1 = ktaScale1 + 1; - } - - for(int i = 0; i < 768; i++) - { - temp = ktaTemp[i] * pow(2,(double)ktaScale1); - if (temp < 0) - { - mlx90640->kta[i] = (temp - 0.5); - } - else - { - mlx90640->kta[i] = (temp + 0.5); - } - - } - - mlx90640->ktaScale = ktaScale1; -} - - -//------------------------------------------------------------------------------ - -void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - int p = 0; - int8_t KvT[4]; - int8_t KvRoCo; - int8_t KvRoCe; - int8_t KvReCo; - int8_t KvReCe; - uint8_t kvScale; - uint8_t split; - float kvTemp[768]; - float temp; - - KvRoCo = (eeData[52] & 0xF000) >> 12; - if (KvRoCo > 7) - { - KvRoCo = KvRoCo - 16; - } - KvT[0] = KvRoCo; - - KvReCo = (eeData[52] & 0x0F00) >> 8; - if (KvReCo > 7) - { - KvReCo = KvReCo - 16; - } - KvT[2] = KvReCo; - - KvRoCe = (eeData[52] & 0x00F0) >> 4; - if (KvRoCe > 7) - { - KvRoCe = KvRoCe - 16; - } - KvT[1] = KvRoCe; - - KvReCe = (eeData[52] & 0x000F); - if (KvReCe > 7) - { - KvReCe = KvReCe - 16; - } - KvT[3] = KvReCe; - - kvScale = (eeData[56] & 0x0F00) >> 8; - - - for(int i = 0; i < 24; i++) - { - for(int j = 0; j < 32; j ++) - { - p = 32 * i +j; - split = 2*(p/32 - (p/64)*2) + p%2; - kvTemp[p] = KvT[split]; - kvTemp[p] = kvTemp[p] / pow(2,(double)kvScale); - //kvTemp[p] = kvTemp[p] * mlx90640->offset[p]; - } - } - - temp = fabs(kvTemp[0]); - for(int i = 1; i < 768; i++) - { - if (fabs(kvTemp[i]) > temp) - { - temp = fabs(kvTemp[i]); - } - } - - kvScale = 0; - while(temp < 63.4) - { - temp = temp*2; - kvScale = kvScale + 1; - } - - for(int i = 0; i < 768; i++) - { - temp = kvTemp[i] * pow(2,(double)kvScale); - if (temp < 0) - { - mlx90640->kv[i] = (temp - 0.5); - } - else - { - mlx90640->kv[i] = (temp + 0.5); - } - - } - - mlx90640->kvScale = kvScale; -} - -//------------------------------------------------------------------------------ - -void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - float alphaSP[2]; - int16_t offsetSP[2]; - float cpKv; - float cpKta; - uint8_t alphaScale; - uint8_t ktaScale1; - uint8_t kvScale; - - alphaScale = ((eeData[32] & 0xF000) >> 12) + 27; - - offsetSP[0] = (eeData[58] & 0x03FF); - if (offsetSP[0] > 511) - { - offsetSP[0] = offsetSP[0] - 1024; - } - - offsetSP[1] = (eeData[58] & 0xFC00) >> 10; - if (offsetSP[1] > 31) - { - offsetSP[1] = offsetSP[1] - 64; - } - offsetSP[1] = offsetSP[1] + offsetSP[0]; - - alphaSP[0] = (eeData[57] & 0x03FF); - if (alphaSP[0] > 511) - { - alphaSP[0] = alphaSP[0] - 1024; - } - alphaSP[0] = alphaSP[0] / pow(2,(double)alphaScale); - - alphaSP[1] = (eeData[57] & 0xFC00) >> 10; - if (alphaSP[1] > 31) - { - alphaSP[1] = alphaSP[1] - 64; - } - alphaSP[1] = (1 + alphaSP[1]/128) * alphaSP[0]; - - cpKta = (eeData[59] & 0x00FF); - if (cpKta > 127) - { - cpKta = cpKta - 256; - } - ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; - mlx90640->cpKta = cpKta / pow(2,(double)ktaScale1); - - cpKv = (eeData[59] & 0xFF00) >> 8; - if (cpKv > 127) - { - cpKv = cpKv - 256; - } - kvScale = (eeData[56] & 0x0F00) >> 8; - mlx90640->cpKv = cpKv / pow(2,(double)kvScale); - - mlx90640->cpAlpha[0] = alphaSP[0]; - mlx90640->cpAlpha[1] = alphaSP[1]; - mlx90640->cpOffset[0] = offsetSP[0]; - mlx90640->cpOffset[1] = offsetSP[1]; -} - -//------------------------------------------------------------------------------ - -void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - float ilChessC[3]; - uint8_t calibrationModeEE; - - calibrationModeEE = (eeData[10] & 0x0800) >> 4; - calibrationModeEE = calibrationModeEE ^ 0x80; - - ilChessC[0] = (eeData[53] & 0x003F); - if (ilChessC[0] > 31) - { - ilChessC[0] = ilChessC[0] - 64; - } - ilChessC[0] = ilChessC[0] / 16.0f; - - ilChessC[1] = (eeData[53] & 0x07C0) >> 6; - if (ilChessC[1] > 15) - { - ilChessC[1] = ilChessC[1] - 32; - } - ilChessC[1] = ilChessC[1] / 2.0f; - - ilChessC[2] = (eeData[53] & 0xF800) >> 11; - if (ilChessC[2] > 15) - { - ilChessC[2] = ilChessC[2] - 32; - } - ilChessC[2] = ilChessC[2] / 8.0f; - - mlx90640->calibrationModeEE = calibrationModeEE; - mlx90640->ilChessC[0] = ilChessC[0]; - mlx90640->ilChessC[1] = ilChessC[1]; - mlx90640->ilChessC[2] = ilChessC[2]; -} - -//------------------------------------------------------------------------------ - -int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640) -{ - uint16_t pixCnt = 0; - uint16_t brokenPixCnt = 0; - uint16_t outlierPixCnt = 0; - int warn = 0; - int i; - - for(pixCnt = 0; pixCnt<5; pixCnt++) - { - mlx90640->brokenPixels[pixCnt] = 0xFFFF; - mlx90640->outlierPixels[pixCnt] = 0xFFFF; - } - - pixCnt = 0; - while (pixCnt < 768 && brokenPixCnt < 5 && outlierPixCnt < 5) - { - if(eeData[pixCnt+64] == 0) - { - mlx90640->brokenPixels[brokenPixCnt] = pixCnt; - brokenPixCnt = brokenPixCnt + 1; - } - else if((eeData[pixCnt+64] & 0x0001) != 0) - { - mlx90640->outlierPixels[outlierPixCnt] = pixCnt; - outlierPixCnt = outlierPixCnt + 1; - } - - pixCnt = pixCnt + 1; - - } - - if(brokenPixCnt > 4) - { - warn = -3; - } - else if(outlierPixCnt > 4) - { - warn = -4; - } - else if((brokenPixCnt + outlierPixCnt) > 4) - { - warn = -5; - } - else - { - for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->brokenPixels[i]); - if(warn != 0) - { - return warn; - } - } - } - - for(pixCnt=0; pixCntoutlierPixels[pixCnt],mlx90640->outlierPixels[i]); - if(warn != 0) - { - return warn; - } - } - } - - for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->outlierPixels[i]); - if(warn != 0) - { - return warn; - } - } - } - - } - - - return warn; - -} - -//------------------------------------------------------------------------------ - - int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2) - { - int pixPosDif; - - pixPosDif = pix1 - pix2; - if(pixPosDif > -34 && pixPosDif < -30) - { - return -6; - } - if(pixPosDif > -2 && pixPosDif < 2) - { - return -6; - } - if(pixPosDif > 30 && pixPosDif < 34) - { - return -6; - } - - return 0; - } - -//------------------------------------------------------------------------------ - -float GetMedian(float *values, int n) - { - float temp; - - for(int i=0; ioutlierPixels[i] || pixel == params->brokenPixels[i]) - { - return 1; - } - } - - return 0; -} - -//------------------------------------------------------------------------------ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); +int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640); +int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2); +float GetMedian(float *values, int n); +int IsPixelBad(uint16_t pixel,paramsMLX90640 *params); +int ValidateFrameData(uint16_t *frameData); +int ValidateAuxData(uint16_t *auxData); +int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data); +int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data); + +// I2C +#define I2C_BUFFER_LENGTH 128 + +int MLX90640_I2CRead(uint8_t addr, uint32_t reg, uint16_t len, uint16_t *reg_data){ + int bytesRemaining = len * 2; + int dataSpot = 0; //Start at beginning of array + while (bytesRemaining > 0) + { + Wire.beginTransmission(addr); + Wire.write(reg >> 8); //MSB + Wire.write(reg & 0xFF); //LSB + if (Wire.endTransmission(false) != 0) //Do not release bus + { + return (0); //Sensor did not ACK + } + int numberOfBytesToRead = bytesRemaining; + if (numberOfBytesToRead > I2C_BUFFER_LENGTH) numberOfBytesToRead = I2C_BUFFER_LENGTH; + Wire.requestFrom((int)addr, numberOfBytesToRead); + if (Wire.available()) + { + for (uint32_t x = 0 ; x < numberOfBytesToRead / 2; x++) + { + reg_data[dataSpot] = Wire.read() << 8; //MSB + reg_data[dataSpot] |= Wire.read(); //LSB + dataSpot++; + } + } + bytesRemaining -= numberOfBytesToRead; + reg += numberOfBytesToRead / 2; + } + return (0); //Success +} + +int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data) +{ + Wire.beginTransmission((uint8_t)_deviceAddress); + Wire.write(writeAddress >> 8); //MSB + Wire.write(writeAddress & 0xFF); //LSB + Wire.write(data >> 8); //MSB + Wire.write(data & 0xFF); //LSB + if (Wire.endTransmission() != 0) + { + //Sensor did not ACK + return (-1); + } + uint16_t dataCheck; + MLX90640_I2CRead(_deviceAddress, writeAddress, 1, &dataCheck); + if (dataCheck != data) + { + return -2; + } + return (0); //Success +} + +int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData) +{ + return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData); +} + +int MLX90640_SynchFrame(uint8_t slaveAddr) +{ + uint16_t dataReady = 0; + uint16_t statusRegister; + int error = 1; + + error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); + if(error == -1) + { + return error; + } + + while(dataReady == 0) + { + error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); + if(error != 0) + { + return error; + } + dataReady = statusRegister & 0x0008; + } + + return 0; +} + +// int MLX90640_TriggerMeasurement(uint8_t slaveAddr) // ATM not used in Tasmota +// { +// int error = 1; +// uint16_t ctrlReg; + +// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// ctrlReg |= 0x8000; +// error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// // error = MLX90640_I2CGeneralReset(); + +// // if ( error != 0) +// // { +// // return error; +// // } + +// error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); + +// if ( error != 0) +// { +// return error; +// } + +// if ((ctrlReg & 0x8000) != 0) +// { +// return -9; +// } + +// return 0; +// } + +int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) +{ + uint16_t dataReady = 0; + uint16_t controlRegister1; + uint16_t statusRegister; + int error = 1; + uint16_t data[64]; + uint8_t cnt = 0; + + while(dataReady == 0) + { + error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); + if(error != 0) + { + return error; + } + dataReady = statusRegister & 0x0008; + } + + error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); + if(error == -1) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData); + if(error != 0) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data); + if(error != 0) + { + return error; + } + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + frameData[832] = controlRegister1; + frameData[833] = statusRegister & 0x0001; + + if(error != 0) + { + return error; + } + + error = ValidateAuxData(data); + if(error == 0) + { + for(cnt=0; cnt<64; cnt++) + { + frameData[cnt+768] = data[cnt]; + } + } + + error = ValidateFrameData(frameData); + if (error != 0) + { + return error; + } + + return frameData[833]; +} + +int ValidateFrameData(uint16_t *frameData) +{ + uint8_t line = 0; + + for(int i=0; i<768; i+=32) + { + if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8; + line = line + 1; + } + + return 0; +} + +int ValidateAuxData(uint16_t *auxData) +{ + + if(auxData[0] == 0x7FFF) return -8; + + for(int i=8; i<19; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=20; i<23; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=24; i<33; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=40; i<51; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=52; i<55; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + for(int i=56; i<64; i++) + { + if(auxData[i] == 0x7FFF) return -8; + } + + return 0; + +} + +int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640, int _chunk) // Tasmota +{ + int error = 0; + switch(_chunk){ + case 0: + ExtractVDDParameters(eeData, mlx90640); + ExtractPTATParameters(eeData, mlx90640); + ExtractGainParameters(eeData, mlx90640); + ExtractTgcParameters(eeData, mlx90640); + ExtractResolutionParameters(eeData, mlx90640); + ExtractKsTaParameters(eeData, mlx90640); + ExtractKsToParameters(eeData, mlx90640); + break; + case 1: + ExtractCPParameters(eeData, mlx90640); + ExtractAlphaParameters(eeData, mlx90640); + break; + case 2: + ExtractOffsetParameters(eeData, mlx90640); + break; + case 3: + ExtractKtaPixelParameters(eeData, mlx90640); + break; + case 4: + ExtractKvPixelParameters(eeData, mlx90640); + break; + case 5: + ExtractCILCParameters(eeData, mlx90640); + error = ExtractDeviatingPixels(eeData, mlx90640); + break; + } + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution) +{ + uint16_t controlRegister1; + int value; + int error; + + value = (resolution & 0x03) << 10; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 & 0xF3FF) | value; + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetCurResolution(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int resolutionRAM; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + resolutionRAM = (controlRegister1 & 0x0C00) >> 10; + + return resolutionRAM; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate) +{ + uint16_t controlRegister1; + int value; + int error; + + value = (refreshRate & 0x07)<<7; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error == 0) + { + value = (controlRegister1 & 0xFC7F) | value; + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetRefreshRate(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int refreshRate; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + refreshRate = (controlRegister1 & 0x0380) >> 7; + + return refreshRate; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetInterleavedMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int value; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 & 0xEFFF); + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_SetChessMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int value; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + + if(error == 0) + { + value = (controlRegister1 | 0x1000); + error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetCurMode(uint8_t slaveAddr) +{ + uint16_t controlRegister1; + int modeRAM; + int error; + + error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); + if(error != 0) + { + return error; + } + modeRAM = (controlRegister1 & 0x1000) >> 12; + + return modeRAM; +} + +//------------------------------------------------------------------------------ +void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part) +{ + float vdd; + float ta; + float ta4; + float tr4; + float taTr; + float gain; + float irDataCP[2]; + float irData; + float alphaCompensated; + uint8_t mode; + int8_t ilPattern; + int8_t chessPattern; + int8_t pattern; + int8_t conversionPattern; + float Sx; + float To; + float alphaCorrR[4]; + int8_t range; + uint16_t subPage; + float ktaScale; + float kvScale; + float alphaScale; + float kta; + float kv; + + subPage = frameData[833]; + vdd = MLX90640_GetVdd(frameData, params); + ta = MLX90640_GetTa(frameData, params); + + ta4 = (ta + 273.15); + ta4 = ta4 * ta4; + ta4 = ta4 * ta4; + tr4 = (tr + 273.15); + tr4 = tr4 * tr4; + tr4 = tr4 * tr4; + taTr = tr4 - (tr4-ta4)/emissivity; + + ktaScale = pow(2,(double)params->ktaScale); + kvScale = pow(2,(double)params->kvScale); + alphaScale = pow(2,(double)params->alphaScale); + + alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40); + alphaCorrR[1] = 1 ; + alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]); + alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2])); + +//------------------------- Gain calculation ----------------------------------- + gain = frameData[778]; + if(gain > 32767) + { + gain = gain - 65536; + } + + gain = params->gainEE / gain; + +//------------------------- To calculation ------------------------------------- + mode = (frameData[832] & 0x1000) >> 5; + + irDataCP[0] = frameData[776]; + irDataCP[1] = frameData[808]; + for( int i = 0; i < 2; i++) + { + if(irDataCP[i] > 32767) + { + irDataCP[i] = irDataCP[i] - 65536; + } + irDataCP[i] = irDataCP[i] * gain; + } + irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + if( mode == params->calibrationModeEE) + { + irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + } + else + { + irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); + } + + uint32_t _offset = _part*(768/2); + for( int pixelNumber = _offset; pixelNumber < (_offset+(768/2)); pixelNumber++) + { + ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; + chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); + conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); + + if(mode == 0) + { + pattern = ilPattern; + } + else + { + pattern = chessPattern; + } + + if(pattern == frameData[833]) + { + irData = frameData[pixelNumber]; + if(irData > 32767) + { + irData = irData - 65536; + } + irData = irData * gain; + + kta = params->kta[pixelNumber]/ktaScale; + kv = params->kv[pixelNumber]/kvScale; + irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); + + if(mode != params->calibrationModeEE) + { + irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; + } + + irData = irData - params->tgc * irDataCP[subPage]; + irData = irData / emissivity; + + alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber]; + alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25)); + + Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr); + Sx = sqrt(sqrt(Sx)) * params->ksTo[1]; + + To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15; + + if(To < params->ct[1]) + { + range = 0; + } + else if(To < params->ct[2]) + { + range = 1; + } + else if(To < params->ct[3]) + { + range = 2; + } + else + { + range = 3; + } + + To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15; + + result[pixelNumber] = To; + } + } +} + +//------------------------------------------------------------------------------ + +// void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result) +// { +// float vdd; +// float ta; +// float gain; +// float irDataCP[2]; +// float irData; +// float alphaCompensated; +// uint8_t mode; +// int8_t ilPattern; +// int8_t chessPattern; +// int8_t pattern; +// int8_t conversionPattern; +// float image; +// uint16_t subPage; +// float ktaScale; +// float kvScale; +// float kta; +// float kv; + +// subPage = frameData[833]; +// vdd = MLX90640_GetVdd(frameData, params); +// ta = MLX90640_GetTa(frameData, params); + +// ktaScale = pow(2,(double)params->ktaScale); +// kvScale = pow(2,(double)params->kvScale); + +// //------------------------- Gain calculation ----------------------------------- +// gain = frameData[778]; +// if(gain > 32767) +// { +// gain = gain - 65536; +// } + +// gain = params->gainEE / gain; + +// //------------------------- Image calculation ------------------------------------- +// mode = (frameData[832] & 0x1000) >> 5; + +// irDataCP[0] = frameData[776]; +// irDataCP[1] = frameData[808]; +// for( int i = 0; i < 2; i++) +// { +// if(irDataCP[i] > 32767) +// { +// irDataCP[i] = irDataCP[i] - 65536; +// } +// irDataCP[i] = irDataCP[i] * gain; +// } +// irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// if( mode == params->calibrationModeEE) +// { +// irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// } +// else +// { +// irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); +// } + +// for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++) +// { +// ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; +// chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); +// conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); + +// if(mode == 0) +// { +// pattern = ilPattern; +// } +// else +// { +// pattern = chessPattern; +// } + +// if(pattern == frameData[833]) +// { +// irData = frameData[pixelNumber]; +// if(irData > 32767) +// { +// irData = irData - 65536; +// } +// irData = irData * gain; + +// kta = params->kta[pixelNumber]/ktaScale; +// kv = params->kv[pixelNumber]/kvScale; +// irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); + +// if(mode != params->calibrationModeEE) +// { +// irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; +// } + +// irData = irData - params->tgc * irDataCP[subPage]; + +// alphaCompensated = params->alpha[pixelNumber]; + +// image = irData*alphaCompensated; + +// result[pixelNumber] = image; +// } +// } +// } + +//------------------------------------------------------------------------------ + +float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params) +{ + float vdd; + float resolutionCorrection; + + int resolutionRAM; + + vdd = frameData[810]; + if(vdd > 32767) + { + vdd = vdd - 65536; + } + resolutionRAM = (frameData[832] & 0x0C00) >> 10; + resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM); + vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3; + + return vdd; +} + +//------------------------------------------------------------------------------ + +float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params) +{ + float ptat; + float ptatArt; + float vdd; + float ta; + + vdd = MLX90640_GetVdd(frameData, params); + + ptat = frameData[800]; + if(ptat > 32767) + { + ptat = ptat - 65536; + } + + ptatArt = frameData[768]; + if(ptatArt > 32767) + { + ptatArt = ptatArt - 65536; + } + ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18); + + ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25); + ta = ta / params->KtPTAT + 25; + + return ta; +} + +//------------------------------------------------------------------------------ + +int MLX90640_GetSubPageNumber(uint16_t *frameData) +{ + return frameData[833]; + +} + +//------------------------------------------------------------------------------ +void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params) +{ + float ap[4]; + uint8_t pix; + uint8_t line; + uint8_t column; + + pix = 0; + while(pixels[pix] != 0xFFFF) + { + line = pixels[pix]>>5; + column = pixels[pix] - (line<<5); + + if(mode == 1) + { + if(line == 0) + { + if(column == 0) + { + to[pixels[pix]] = to[33]; + } + else if(column == 31) + { + to[pixels[pix]] = to[62]; + } + else + { + to[pixels[pix]] = (to[pixels[pix]+31] + to[pixels[pix]+33])/2.0; + } + } + else if(line == 23) + { + if(column == 0) + { + to[pixels[pix]] = to[705]; + } + else if(column == 31) + { + to[pixels[pix]] = to[734]; + } + else + { + to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]-31])/2.0; + } + } + else if(column == 0) + { + to[pixels[pix]] = (to[pixels[pix]-31] + to[pixels[pix]+33])/2.0; + } + else if(column == 31) + { + to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]+31])/2.0; + } + else + { + ap[0] = to[pixels[pix]-33]; + ap[1] = to[pixels[pix]-31]; + ap[2] = to[pixels[pix]+31]; + ap[3] = to[pixels[pix]+33]; + to[pixels[pix]] = GetMedian(ap,4); + } + } + else + { + if(column == 0) + { + to[pixels[pix]] = to[pixels[pix]+1]; + } + else if(column == 1 || column == 30) + { + to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; + } + else if(column == 31) + { + to[pixels[pix]] = to[pixels[pix]-1]; + } + else + { + if(IsPixelBad(pixels[pix]-2,params) == 0 && IsPixelBad(pixels[pix]+2,params) == 0) + { + ap[0] = to[pixels[pix]+1] - to[pixels[pix]+2]; + ap[1] = to[pixels[pix]-1] - to[pixels[pix]-2]; + if(fabs(ap[0]) > fabs(ap[1])) + { + to[pixels[pix]] = to[pixels[pix]-1] + ap[1]; + } + else + { + to[pixels[pix]] = to[pixels[pix]+1] + ap[0]; + } + } + else + { + to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0; + } + } + } + pix = pix + 1; + } +} + +//------------------------------------------------------------------------------ + +void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int16_t kVdd; + int16_t vdd25; + + kVdd = eeData[51]; + + kVdd = (eeData[51] & 0xFF00) >> 8; + if(kVdd > 127) + { + kVdd = kVdd - 256; + } + kVdd = 32 * kVdd; + vdd25 = eeData[51] & 0x00FF; + vdd25 = ((vdd25 - 256) << 5) - 8192; + + mlx90640->kVdd = kVdd; + mlx90640->vdd25 = vdd25; +} + +//------------------------------------------------------------------------------ + +void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float KvPTAT; + float KtPTAT; + int16_t vPTAT25; + float alphaPTAT; + + KvPTAT = (eeData[50] & 0xFC00) >> 10; + if(KvPTAT > 31) + { + KvPTAT = KvPTAT - 64; + } + KvPTAT = KvPTAT/4096; + + KtPTAT = eeData[50] & 0x03FF; + if(KtPTAT > 511) + { + KtPTAT = KtPTAT - 1024; + } + KtPTAT = KtPTAT/8; + + vPTAT25 = eeData[49]; + + alphaPTAT = (eeData[16] & 0xF000) / pow(2, (double)14) + 8.0f; + + mlx90640->KvPTAT = KvPTAT; + mlx90640->KtPTAT = KtPTAT; + mlx90640->vPTAT25 = vPTAT25; + mlx90640->alphaPTAT = alphaPTAT; +} + +//------------------------------------------------------------------------------ + +void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int16_t gainEE; + + gainEE = eeData[48]; + if(gainEE > 32767) + { + gainEE = gainEE -65536; + } + + mlx90640->gainEE = gainEE; +} + +//------------------------------------------------------------------------------ + +void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float tgc; + tgc = eeData[60] & 0x00FF; + if(tgc > 127) + { + tgc = tgc - 256; + } + tgc = tgc / 32.0f; + + mlx90640->tgc = tgc; +} + +//------------------------------------------------------------------------------ + +void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + uint8_t resolutionEE; + resolutionEE = (eeData[56] & 0x3000) >> 12; + + mlx90640->resolutionEE = resolutionEE; +} + +//------------------------------------------------------------------------------ + +void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float KsTa; + KsTa = (eeData[60] & 0xFF00) >> 8; + if(KsTa > 127) + { + KsTa = KsTa -256; + } + KsTa = KsTa / 8192.0f; + + mlx90640->KsTa = KsTa; +} + +//------------------------------------------------------------------------------ + +void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int KsToScale; + int8_t step; + + step = ((eeData[63] & 0x3000) >> 12) * 10; + + mlx90640->ct[0] = -40; + mlx90640->ct[1] = 0; + mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4; + mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8; + + mlx90640->ct[2] = mlx90640->ct[2]*step; + mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step; + mlx90640->ct[4] = 400; + + KsToScale = (eeData[63] & 0x000F) + 8; + KsToScale = 1 << KsToScale; + + mlx90640->ksTo[0] = eeData[61] & 0x00FF; + mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8; + mlx90640->ksTo[2] = eeData[62] & 0x00FF; + mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8; + + for(int i = 0; i < 4; i++) + { + if(mlx90640->ksTo[i] > 127) + { + mlx90640->ksTo[i] = mlx90640->ksTo[i] - 256; + } + mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale; + } + + mlx90640->ksTo[4] = -0.0002; +} + +//------------------------------------------------------------------------------ + +void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int accRow[24]; + int accColumn[32]; + int p = 0; + int alphaRef; + uint8_t alphaScale; + uint8_t accRowScale; + uint8_t accColumnScale; + uint8_t accRemScale; + float alphaTemp[768]; + float temp; + + + accRemScale = eeData[32] & 0x000F; + accColumnScale = (eeData[32] & 0x00F0) >> 4; + accRowScale = (eeData[32] & 0x0F00) >> 8; + alphaScale = ((eeData[32] & 0xF000) >> 12) + 30; + alphaRef = eeData[33]; + + for(int i = 0; i < 6; i++) + { + p = i * 4; + accRow[p + 0] = (eeData[34 + i] & 0x000F); + accRow[p + 1] = (eeData[34 + i] & 0x00F0) >> 4; + accRow[p + 2] = (eeData[34 + i] & 0x0F00) >> 8; + accRow[p + 3] = (eeData[34 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 24; i++) + { + if (accRow[i] > 7) + { + accRow[i] = accRow[i] - 16; + } + } + + for(int i = 0; i < 8; i++) + { + p = i * 4; + accColumn[p + 0] = (eeData[40 + i] & 0x000F); + accColumn[p + 1] = (eeData[40 + i] & 0x00F0) >> 4; + accColumn[p + 2] = (eeData[40 + i] & 0x0F00) >> 8; + accColumn[p + 3] = (eeData[40 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 32; i ++) + { + if (accColumn[i] > 7) + { + accColumn[i] = accColumn[i] - 16; + } + } + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + alphaTemp[p] = (eeData[64 + p] & 0x03F0) >> 4; + if (alphaTemp[p] > 31) + { + alphaTemp[p] = alphaTemp[p] - 64; + } + alphaTemp[p] = alphaTemp[p]*(1 << accRemScale); + alphaTemp[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + alphaTemp[p]); + alphaTemp[p] = alphaTemp[p] / pow(2,(double)alphaScale); + alphaTemp[p] = alphaTemp[p] - mlx90640->tgc * (mlx90640->cpAlpha[0] + mlx90640->cpAlpha[1])/2; + alphaTemp[p] = SCALEALPHA/alphaTemp[p]; + } + } + + temp = alphaTemp[0]; + for(int i = 1; i < 768; i++) + { + if (alphaTemp[i] > temp) + { + temp = alphaTemp[i]; + } + } + + alphaScale = 0; + while(temp < 32767.4) + { + temp = temp*2; + alphaScale = alphaScale + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = alphaTemp[i] * pow(2,(double)alphaScale); + mlx90640->alpha[i] = (temp + 0.5); + + } + + mlx90640->alphaScale = alphaScale; + +} + +//------------------------------------------------------------------------------ + +void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int occRow[24]; + int occColumn[32]; + int p = 0; + int16_t offsetRef; + uint8_t occRowScale; + uint8_t occColumnScale; + uint8_t occRemScale; + + + occRemScale = (eeData[16] & 0x000F); + occColumnScale = (eeData[16] & 0x00F0) >> 4; + occRowScale = (eeData[16] & 0x0F00) >> 8; + offsetRef = eeData[17]; + if (offsetRef > 32767) + { + offsetRef = offsetRef - 65536; + } + + for(int i = 0; i < 6; i++) + { + p = i * 4; + occRow[p + 0] = (eeData[18 + i] & 0x000F); + occRow[p + 1] = (eeData[18 + i] & 0x00F0) >> 4; + occRow[p + 2] = (eeData[18 + i] & 0x0F00) >> 8; + occRow[p + 3] = (eeData[18 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 24; i++) + { + if (occRow[i] > 7) + { + occRow[i] = occRow[i] - 16; + } + } + + for(int i = 0; i < 8; i++) + { + p = i * 4; + occColumn[p + 0] = (eeData[24 + i] & 0x000F); + occColumn[p + 1] = (eeData[24 + i] & 0x00F0) >> 4; + occColumn[p + 2] = (eeData[24 + i] & 0x0F00) >> 8; + occColumn[p + 3] = (eeData[24 + i] & 0xF000) >> 12; + } + + for(int i = 0; i < 32; i ++) + { + if (occColumn[i] > 7) + { + occColumn[i] = occColumn[i] - 16; + } + } + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + mlx90640->offset[p] = (eeData[64 + p] & 0xFC00) >> 10; + if (mlx90640->offset[p] > 31) + { + mlx90640->offset[p] = mlx90640->offset[p] - 64; + } + mlx90640->offset[p] = mlx90640->offset[p]*(1 << occRemScale); + mlx90640->offset[p] = (offsetRef + (occRow[i] << occRowScale) + (occColumn[j] << occColumnScale) + mlx90640->offset[p]); + } + } +} + +//------------------------------------------------------------------------------ + +void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int p = 0; + int8_t KtaRC[4]; + int8_t KtaRoCo; + int8_t KtaRoCe; + int8_t KtaReCo; + int8_t KtaReCe; + uint8_t ktaScale1; + uint8_t ktaScale2; + uint8_t split; + float ktaTemp[768]; + float temp; + + KtaRoCo = (eeData[54] & 0xFF00) >> 8; + if (KtaRoCo > 127) + { + KtaRoCo = KtaRoCo - 256; + } + KtaRC[0] = KtaRoCo; + + KtaReCo = (eeData[54] & 0x00FF); + if (KtaReCo > 127) + { + KtaReCo = KtaReCo - 256; + } + KtaRC[2] = KtaReCo; + + KtaRoCe = (eeData[55] & 0xFF00) >> 8; + if (KtaRoCe > 127) + { + KtaRoCe = KtaRoCe - 256; + } + KtaRC[1] = KtaRoCe; + + KtaReCe = (eeData[55] & 0x00FF); + if (KtaReCe > 127) + { + KtaReCe = KtaReCe - 256; + } + KtaRC[3] = KtaReCe; + + ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; + ktaScale2 = (eeData[56] & 0x000F); + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + split = 2*(p/32 - (p/64)*2) + p%2; + ktaTemp[p] = (eeData[64 + p] & 0x000E) >> 1; + if (ktaTemp[p] > 3) + { + ktaTemp[p] = ktaTemp[p] - 8; + } + ktaTemp[p] = ktaTemp[p] * (1 << ktaScale2); + ktaTemp[p] = KtaRC[split] + ktaTemp[p]; + ktaTemp[p] = ktaTemp[p] / pow(2,(double)ktaScale1); + //ktaTemp[p] = ktaTemp[p] * mlx90640->offset[p]; + } + } + + temp = fabs(ktaTemp[0]); + for(int i = 1; i < 768; i++) + { + if (fabs(ktaTemp[i]) > temp) + { + temp = fabs(ktaTemp[i]); + } + } + + ktaScale1 = 0; + while(temp < 63.4) + { + temp = temp*2; + ktaScale1 = ktaScale1 + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = ktaTemp[i] * pow(2,(double)ktaScale1); + if (temp < 0) + { + mlx90640->kta[i] = (temp - 0.5); + } + else + { + mlx90640->kta[i] = (temp + 0.5); + } + + } + + mlx90640->ktaScale = ktaScale1; +} + + +//------------------------------------------------------------------------------ + +void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + int p = 0; + int8_t KvT[4]; + int8_t KvRoCo; + int8_t KvRoCe; + int8_t KvReCo; + int8_t KvReCe; + uint8_t kvScale; + uint8_t split; + float kvTemp[768]; + float temp; + + KvRoCo = (eeData[52] & 0xF000) >> 12; + if (KvRoCo > 7) + { + KvRoCo = KvRoCo - 16; + } + KvT[0] = KvRoCo; + + KvReCo = (eeData[52] & 0x0F00) >> 8; + if (KvReCo > 7) + { + KvReCo = KvReCo - 16; + } + KvT[2] = KvReCo; + + KvRoCe = (eeData[52] & 0x00F0) >> 4; + if (KvRoCe > 7) + { + KvRoCe = KvRoCe - 16; + } + KvT[1] = KvRoCe; + + KvReCe = (eeData[52] & 0x000F); + if (KvReCe > 7) + { + KvReCe = KvReCe - 16; + } + KvT[3] = KvReCe; + + kvScale = (eeData[56] & 0x0F00) >> 8; + + + for(int i = 0; i < 24; i++) + { + for(int j = 0; j < 32; j ++) + { + p = 32 * i +j; + split = 2*(p/32 - (p/64)*2) + p%2; + kvTemp[p] = KvT[split]; + kvTemp[p] = kvTemp[p] / pow(2,(double)kvScale); + //kvTemp[p] = kvTemp[p] * mlx90640->offset[p]; + } + } + + temp = fabs(kvTemp[0]); + for(int i = 1; i < 768; i++) + { + if (fabs(kvTemp[i]) > temp) + { + temp = fabs(kvTemp[i]); + } + } + + kvScale = 0; + while(temp < 63.4) + { + temp = temp*2; + kvScale = kvScale + 1; + } + + for(int i = 0; i < 768; i++) + { + temp = kvTemp[i] * pow(2,(double)kvScale); + if (temp < 0) + { + mlx90640->kv[i] = (temp - 0.5); + } + else + { + mlx90640->kv[i] = (temp + 0.5); + } + + } + + mlx90640->kvScale = kvScale; +} + +//------------------------------------------------------------------------------ + +void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float alphaSP[2]; + int16_t offsetSP[2]; + float cpKv; + float cpKta; + uint8_t alphaScale; + uint8_t ktaScale1; + uint8_t kvScale; + + alphaScale = ((eeData[32] & 0xF000) >> 12) + 27; + + offsetSP[0] = (eeData[58] & 0x03FF); + if (offsetSP[0] > 511) + { + offsetSP[0] = offsetSP[0] - 1024; + } + + offsetSP[1] = (eeData[58] & 0xFC00) >> 10; + if (offsetSP[1] > 31) + { + offsetSP[1] = offsetSP[1] - 64; + } + offsetSP[1] = offsetSP[1] + offsetSP[0]; + + alphaSP[0] = (eeData[57] & 0x03FF); + if (alphaSP[0] > 511) + { + alphaSP[0] = alphaSP[0] - 1024; + } + alphaSP[0] = alphaSP[0] / pow(2,(double)alphaScale); + + alphaSP[1] = (eeData[57] & 0xFC00) >> 10; + if (alphaSP[1] > 31) + { + alphaSP[1] = alphaSP[1] - 64; + } + alphaSP[1] = (1 + alphaSP[1]/128) * alphaSP[0]; + + cpKta = (eeData[59] & 0x00FF); + if (cpKta > 127) + { + cpKta = cpKta - 256; + } + ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8; + mlx90640->cpKta = cpKta / pow(2,(double)ktaScale1); + + cpKv = (eeData[59] & 0xFF00) >> 8; + if (cpKv > 127) + { + cpKv = cpKv - 256; + } + kvScale = (eeData[56] & 0x0F00) >> 8; + mlx90640->cpKv = cpKv / pow(2,(double)kvScale); + + mlx90640->cpAlpha[0] = alphaSP[0]; + mlx90640->cpAlpha[1] = alphaSP[1]; + mlx90640->cpOffset[0] = offsetSP[0]; + mlx90640->cpOffset[1] = offsetSP[1]; +} + +//------------------------------------------------------------------------------ + +void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + float ilChessC[3]; + uint8_t calibrationModeEE; + + calibrationModeEE = (eeData[10] & 0x0800) >> 4; + calibrationModeEE = calibrationModeEE ^ 0x80; + + ilChessC[0] = (eeData[53] & 0x003F); + if (ilChessC[0] > 31) + { + ilChessC[0] = ilChessC[0] - 64; + } + ilChessC[0] = ilChessC[0] / 16.0f; + + ilChessC[1] = (eeData[53] & 0x07C0) >> 6; + if (ilChessC[1] > 15) + { + ilChessC[1] = ilChessC[1] - 32; + } + ilChessC[1] = ilChessC[1] / 2.0f; + + ilChessC[2] = (eeData[53] & 0xF800) >> 11; + if (ilChessC[2] > 15) + { + ilChessC[2] = ilChessC[2] - 32; + } + ilChessC[2] = ilChessC[2] / 8.0f; + + mlx90640->calibrationModeEE = calibrationModeEE; + mlx90640->ilChessC[0] = ilChessC[0]; + mlx90640->ilChessC[1] = ilChessC[1]; + mlx90640->ilChessC[2] = ilChessC[2]; +} + +//------------------------------------------------------------------------------ + +int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640) +{ + uint16_t pixCnt = 0; + uint16_t brokenPixCnt = 0; + uint16_t outlierPixCnt = 0; + int warn = 0; + int i; + + for(pixCnt = 0; pixCnt<5; pixCnt++) + { + mlx90640->brokenPixels[pixCnt] = 0xFFFF; + mlx90640->outlierPixels[pixCnt] = 0xFFFF; + } + + pixCnt = 0; + while (pixCnt < 768 && brokenPixCnt < 5 && outlierPixCnt < 5) + { + if(eeData[pixCnt+64] == 0) + { + mlx90640->brokenPixels[brokenPixCnt] = pixCnt; + brokenPixCnt = brokenPixCnt + 1; + } + else if((eeData[pixCnt+64] & 0x0001) != 0) + { + mlx90640->outlierPixels[outlierPixCnt] = pixCnt; + outlierPixCnt = outlierPixCnt + 1; + } + + pixCnt = pixCnt + 1; + + } + + if(brokenPixCnt > 4) + { + warn = -3; + } + else if(outlierPixCnt > 4) + { + warn = -4; + } + else if((brokenPixCnt + outlierPixCnt) > 4) + { + warn = -5; + } + else + { + for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->brokenPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + for(pixCnt=0; pixCntoutlierPixels[pixCnt],mlx90640->outlierPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + for(pixCnt=0; pixCntbrokenPixels[pixCnt],mlx90640->outlierPixels[i]); + if(warn != 0) + { + return warn; + } + } + } + + } + + + return warn; + +} + +//------------------------------------------------------------------------------ + + int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2) + { + int pixPosDif; + + pixPosDif = pix1 - pix2; + if(pixPosDif > -34 && pixPosDif < -30) + { + return -6; + } + if(pixPosDif > -2 && pixPosDif < 2) + { + return -6; + } + if(pixPosDif > 30 && pixPosDif < 34) + { + return -6; + } + + return 0; + } + +//------------------------------------------------------------------------------ + +float GetMedian(float *values, int n) + { + float temp; + + for(int i=0; ioutlierPixels[i] || pixel == params->brokenPixels[i]) + { + return 1; + } + } + + return 0; +} + +//------------------------------------------------------------------------------ diff --git a/lib/mlx90640-library/MLX90640_API.h b/lib_i2c/mlx90640-library/MLX90640_API.h similarity index 97% rename from lib/mlx90640-library/MLX90640_API.h rename to lib_i2c/mlx90640-library/MLX90640_API.h index efbcdff5b..e820e7ee0 100644 --- a/lib/mlx90640-library/MLX90640_API.h +++ b/lib_i2c/mlx90640-library/MLX90640_API.h @@ -1,74 +1,74 @@ -/** - * @copyright (C) 2017 Melexis N.V. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _MLX90640_API_H_ -#define _MLX90640_API_H_ - -#include - -#define SCALEALPHA 0.000001 - -typedef struct - { - int16_t kVdd; - int16_t vdd25; - float KvPTAT; - float KtPTAT; - uint16_t vPTAT25; - float alphaPTAT; - int16_t gainEE; - float tgc; - float cpKv; - float cpKta; - uint8_t resolutionEE; - uint8_t calibrationModeEE; - float KsTa; - float ksTo[5]; - int16_t ct[5]; - uint16_t alpha[768]; - uint8_t alphaScale; - int16_t offset[768]; - int8_t kta[768]; - uint8_t ktaScale; - int8_t kv[768]; - uint8_t kvScale; - float cpAlpha[2]; - int16_t cpOffset[2]; - float ilChessC[3]; - uint16_t brokenPixels[5]; - uint16_t outlierPixels[5]; - } paramsMLX90640; - - int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData); - int MLX90640_SynchFrame(uint8_t slaveAddr); - // int MLX90640_TriggerMeasurement(uint8_t slaveAddr); - int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData); - int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640,int _chunk); - float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params); - float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params); - // void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result); - void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part); - int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution); - int MLX90640_GetCurResolution(uint8_t slaveAddr); - int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate); - int MLX90640_GetRefreshRate(uint8_t slaveAddr); - int MLX90640_GetSubPageNumber(uint16_t *frameData); - int MLX90640_GetCurMode(uint8_t slaveAddr); - int MLX90640_SetInterleavedMode(uint8_t slaveAddr); - int MLX90640_SetChessMode(uint8_t slaveAddr); - void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params); - -#endif +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _MLX90640_API_H_ +#define _MLX90640_API_H_ + +#include + +#define SCALEALPHA 0.000001 + +typedef struct + { + int16_t kVdd; + int16_t vdd25; + float KvPTAT; + float KtPTAT; + uint16_t vPTAT25; + float alphaPTAT; + int16_t gainEE; + float tgc; + float cpKv; + float cpKta; + uint8_t resolutionEE; + uint8_t calibrationModeEE; + float KsTa; + float ksTo[5]; + int16_t ct[5]; + uint16_t alpha[768]; + uint8_t alphaScale; + int16_t offset[768]; + int8_t kta[768]; + uint8_t ktaScale; + int8_t kv[768]; + uint8_t kvScale; + float cpAlpha[2]; + int16_t cpOffset[2]; + float ilChessC[3]; + uint16_t brokenPixels[5]; + uint16_t outlierPixels[5]; + } paramsMLX90640; + + int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData); + int MLX90640_SynchFrame(uint8_t slaveAddr); + // int MLX90640_TriggerMeasurement(uint8_t slaveAddr); + int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData); + int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640,int _chunk); + float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params); + float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params); + // void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result); + void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result, uint8_t _part); + int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution); + int MLX90640_GetCurResolution(uint8_t slaveAddr); + int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate); + int MLX90640_GetRefreshRate(uint8_t slaveAddr); + int MLX90640_GetSubPageNumber(uint16_t *frameData); + int MLX90640_GetCurMode(uint8_t slaveAddr); + int MLX90640_SetInterleavedMode(uint8_t slaveAddr); + int MLX90640_SetChessMode(uint8_t slaveAddr); + void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params); + +#endif diff --git a/lib/mlx90640-library/library.properties b/lib_i2c/mlx90640-library/library.properties similarity index 100% rename from lib/mlx90640-library/library.properties rename to lib_i2c/mlx90640-library/library.properties diff --git a/lib/vl53l0x-arduino-1.02/.travis.yml b/lib_i2c/vl53l0x-arduino-1.02/.travis.yml similarity index 100% rename from lib/vl53l0x-arduino-1.02/.travis.yml rename to lib_i2c/vl53l0x-arduino-1.02/.travis.yml diff --git a/lib/vl53l0x-arduino-1.02/LICENSE.txt b/lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt similarity index 100% rename from lib/vl53l0x-arduino-1.02/LICENSE.txt rename to lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt diff --git a/lib/vl53l0x-arduino-1.02/README.md b/lib_i2c/vl53l0x-arduino-1.02/README.md similarity index 100% rename from lib/vl53l0x-arduino-1.02/README.md rename to lib_i2c/vl53l0x-arduino-1.02/README.md diff --git a/lib/vl53l0x-arduino-1.02/VL53L0X.cpp b/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp similarity index 100% rename from lib/vl53l0x-arduino-1.02/VL53L0X.cpp rename to lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp diff --git a/lib/vl53l0x-arduino-1.02/VL53L0X.h b/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h similarity index 100% rename from lib/vl53l0x-arduino-1.02/VL53L0X.h rename to lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h diff --git a/lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino b/lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino similarity index 100% rename from lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino rename to lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino diff --git a/lib/vl53l0x-arduino-1.02/examples/Single/Single.ino b/lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino similarity index 100% rename from lib/vl53l0x-arduino-1.02/examples/Single/Single.ino rename to lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino diff --git a/lib/vl53l0x-arduino-1.02/keywords.txt b/lib_i2c/vl53l0x-arduino-1.02/keywords.txt similarity index 100% rename from lib/vl53l0x-arduino-1.02/keywords.txt rename to lib_i2c/vl53l0x-arduino-1.02/keywords.txt diff --git a/lib/vl53l0x-arduino-1.02/library.properties b/lib_i2c/vl53l0x-arduino-1.02/library.properties similarity index 100% rename from lib/vl53l0x-arduino-1.02/library.properties rename to lib_i2c/vl53l0x-arduino-1.02/library.properties diff --git a/lib/vl53l1x-arduino-1.01/LICENSE.txt b/lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt similarity index 100% rename from lib/vl53l1x-arduino-1.01/LICENSE.txt rename to lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt diff --git a/lib/vl53l1x-arduino-1.01/README.md b/lib_i2c/vl53l1x-arduino-1.01/README.md similarity index 100% rename from lib/vl53l1x-arduino-1.01/README.md rename to lib_i2c/vl53l1x-arduino-1.01/README.md diff --git a/lib/vl53l1x-arduino-1.01/VL53L1X.cpp b/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp similarity index 100% rename from lib/vl53l1x-arduino-1.01/VL53L1X.cpp rename to lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp diff --git a/lib/vl53l1x-arduino-1.01/VL53L1X.h b/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h similarity index 100% rename from lib/vl53l1x-arduino-1.01/VL53L1X.h rename to lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h diff --git a/lib/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino b/lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino similarity index 100% rename from lib/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino rename to lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino diff --git a/lib/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino b/lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino similarity index 100% rename from lib/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino rename to lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino diff --git a/lib/vl53l1x-arduino-1.01/keywords.txt b/lib_i2c/vl53l1x-arduino-1.01/keywords.txt similarity index 100% rename from lib/vl53l1x-arduino-1.01/keywords.txt rename to lib_i2c/vl53l1x-arduino-1.01/keywords.txt diff --git a/lib/vl53l1x-arduino-1.01/library.properties b/lib_i2c/vl53l1x-arduino-1.01/library.properties similarity index 100% rename from lib/vl53l1x-arduino-1.01/library.properties rename to lib_i2c/vl53l1x-arduino-1.01/library.properties diff --git a/lib/KeeloqLib/README.md b/lib_rf/KeeloqLib/README.md similarity index 100% rename from lib/KeeloqLib/README.md rename to lib_rf/KeeloqLib/README.md diff --git a/lib/KeeloqLib/keywords.txt b/lib_rf/KeeloqLib/keywords.txt similarity index 100% rename from lib/KeeloqLib/keywords.txt rename to lib_rf/KeeloqLib/keywords.txt diff --git a/lib/KeeloqLib/library.properties b/lib_rf/KeeloqLib/library.properties similarity index 100% rename from lib/KeeloqLib/library.properties rename to lib_rf/KeeloqLib/library.properties diff --git a/lib/KeeloqLib/src/KeeloqLib.cpp b/lib_rf/KeeloqLib/src/KeeloqLib.cpp similarity index 100% rename from lib/KeeloqLib/src/KeeloqLib.cpp rename to lib_rf/KeeloqLib/src/KeeloqLib.cpp diff --git a/lib/KeeloqLib/src/KeeloqLib.h b/lib_rf/KeeloqLib/src/KeeloqLib.h similarity index 100% rename from lib/KeeloqLib/src/KeeloqLib.h rename to lib_rf/KeeloqLib/src/KeeloqLib.h diff --git a/lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino b/lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino similarity index 100% rename from lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino rename to lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino diff --git a/lib/RF24/.gitignore b/lib_rf/RF24/.gitignore similarity index 100% rename from lib/RF24/.gitignore rename to lib_rf/RF24/.gitignore diff --git a/lib/RF24/CONTRIBUTING.md b/lib_rf/RF24/CONTRIBUTING.md similarity index 100% rename from lib/RF24/CONTRIBUTING.md rename to lib_rf/RF24/CONTRIBUTING.md diff --git a/lib/RF24/Doxyfile b/lib_rf/RF24/Doxyfile similarity index 100% rename from lib/RF24/Doxyfile rename to lib_rf/RF24/Doxyfile diff --git a/lib/RF24/LICENSE b/lib_rf/RF24/LICENSE similarity index 100% rename from lib/RF24/LICENSE rename to lib_rf/RF24/LICENSE diff --git a/lib/RF24/Makefile b/lib_rf/RF24/Makefile similarity index 100% rename from lib/RF24/Makefile rename to lib_rf/RF24/Makefile diff --git a/lib/RF24/README.md b/lib_rf/RF24/README.md similarity index 100% rename from lib/RF24/README.md rename to lib_rf/RF24/README.md diff --git a/lib/RF24/RF24.cpp b/lib_rf/RF24/RF24.cpp similarity index 100% rename from lib/RF24/RF24.cpp rename to lib_rf/RF24/RF24.cpp diff --git a/lib/RF24/RF24.h b/lib_rf/RF24/RF24.h similarity index 100% rename from lib/RF24/RF24.h rename to lib_rf/RF24/RF24.h diff --git a/lib/RF24/RF24_config.h b/lib_rf/RF24/RF24_config.h similarity index 100% rename from lib/RF24/RF24_config.h rename to lib_rf/RF24/RF24_config.h diff --git a/lib/RF24/configure b/lib_rf/RF24/configure old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/configure rename to lib_rf/RF24/configure diff --git a/lib/RF24/doxygen-custom.css b/lib_rf/RF24/doxygen-custom.css similarity index 100% rename from lib/RF24/doxygen-custom.css rename to lib_rf/RF24/doxygen-custom.css diff --git a/lib/RF24/examples/GettingStarted/GettingStarted.ino b/lib_rf/RF24/examples/GettingStarted/GettingStarted.ino similarity index 100% rename from lib/RF24/examples/GettingStarted/GettingStarted.ino rename to lib_rf/RF24/examples/GettingStarted/GettingStarted.ino diff --git a/lib/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino b/lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino similarity index 100% rename from lib/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino rename to lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino diff --git a/lib/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino b/lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino rename to lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino diff --git a/lib/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino b/lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino similarity index 100% rename from lib/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino rename to lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino diff --git a/lib/RF24/examples/Transfer/Transfer.ino b/lib_rf/RF24/examples/Transfer/Transfer.ino similarity index 100% rename from lib/RF24/examples/Transfer/Transfer.ino rename to lib_rf/RF24/examples/Transfer/Transfer.ino diff --git a/lib/RF24/examples/TransferTimeouts/TransferTimeouts.ino b/lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino similarity index 100% rename from lib/RF24/examples/TransferTimeouts/TransferTimeouts.ino rename to lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino diff --git a/lib/RF24/examples/Usage/led_remote/Jamfile b/lib_rf/RF24/examples/Usage/led_remote/Jamfile similarity index 100% rename from lib/RF24/examples/Usage/led_remote/Jamfile rename to lib_rf/RF24/examples/Usage/led_remote/Jamfile diff --git a/lib/RF24/examples/Usage/led_remote/led_remote.pde b/lib_rf/RF24/examples/Usage/led_remote/led_remote.pde similarity index 100% rename from lib/RF24/examples/Usage/led_remote/led_remote.pde rename to lib_rf/RF24/examples/Usage/led_remote/led_remote.pde diff --git a/lib/RF24/examples/Usage/nordic_fob/Jamfile b/lib_rf/RF24/examples/Usage/nordic_fob/Jamfile similarity index 100% rename from lib/RF24/examples/Usage/nordic_fob/Jamfile rename to lib_rf/RF24/examples/Usage/nordic_fob/Jamfile diff --git a/lib/RF24/examples/Usage/nordic_fob/nordic_fob.pde b/lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde similarity index 100% rename from lib/RF24/examples/Usage/nordic_fob/nordic_fob.pde rename to lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde diff --git a/lib/RF24/examples/Usage/pingpair_maple/Jamfile b/lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile similarity index 100% rename from lib/RF24/examples/Usage/pingpair_maple/Jamfile rename to lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile diff --git a/lib/RF24/examples/Usage/pingpair_maple/main.cpp b/lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp similarity index 100% rename from lib/RF24/examples/Usage/pingpair_maple/main.cpp rename to lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp diff --git a/lib/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde b/lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde similarity index 100% rename from lib/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde rename to lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde diff --git a/lib/RF24/examples/Usage/readme.md b/lib_rf/RF24/examples/Usage/readme.md similarity index 100% rename from lib/RF24/examples/Usage/readme.md rename to lib_rf/RF24/examples/Usage/readme.md diff --git a/lib/RF24/examples/pingpair_ack/pingpair_ack.ino b/lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino similarity index 100% rename from lib/RF24/examples/pingpair_ack/pingpair_ack.ino rename to lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino diff --git a/lib/RF24/examples/pingpair_dyn/Jamfile b/lib_rf/RF24/examples/pingpair_dyn/Jamfile similarity index 100% rename from lib/RF24/examples/pingpair_dyn/Jamfile rename to lib_rf/RF24/examples/pingpair_dyn/Jamfile diff --git a/lib/RF24/examples/pingpair_dyn/pingpair_dyn.ino b/lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino similarity index 100% rename from lib/RF24/examples/pingpair_dyn/pingpair_dyn.ino rename to lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino diff --git a/lib/RF24/examples/pingpair_irq/pingpair_irq.ino b/lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino similarity index 100% rename from lib/RF24/examples/pingpair_irq/pingpair_irq.ino rename to lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino diff --git a/lib/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino b/lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino similarity index 100% rename from lib/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino rename to lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino diff --git a/lib/RF24/examples/pingpair_multi_dyn/Jamfile b/lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/examples/pingpair_multi_dyn/Jamfile rename to lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile diff --git a/lib/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino b/lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino similarity index 100% rename from lib/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino rename to lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino diff --git a/lib/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino b/lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino similarity index 100% rename from lib/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino rename to lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino diff --git a/lib/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino b/lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino similarity index 100% rename from lib/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino rename to lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino diff --git a/lib/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino b/lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino similarity index 100% rename from lib/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino rename to lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino diff --git a/lib/RF24/examples/scanner/Jamfile b/lib_rf/RF24/examples/scanner/Jamfile similarity index 100% rename from lib/RF24/examples/scanner/Jamfile rename to lib_rf/RF24/examples/scanner/Jamfile diff --git a/lib/RF24/examples/scanner/scanner.ino b/lib_rf/RF24/examples/scanner/scanner.ino similarity index 100% rename from lib/RF24/examples/scanner/scanner.ino rename to lib_rf/RF24/examples/scanner/scanner.ino diff --git a/lib/RF24/examples/starping/Jamfile b/lib_rf/RF24/examples/starping/Jamfile similarity index 100% rename from lib/RF24/examples/starping/Jamfile rename to lib_rf/RF24/examples/starping/Jamfile diff --git a/lib/RF24/examples/starping/starping.pde b/lib_rf/RF24/examples/starping/starping.pde similarity index 100% rename from lib/RF24/examples/starping/starping.pde rename to lib_rf/RF24/examples/starping/starping.pde diff --git a/lib/RF24/examples_linux/Makefile.examples b/lib_rf/RF24/examples_linux/Makefile.examples similarity index 100% rename from lib/RF24/examples_linux/Makefile.examples rename to lib_rf/RF24/examples_linux/Makefile.examples diff --git a/lib/RF24/examples_linux/extra/Makefile b/lib_rf/RF24/examples_linux/extra/Makefile similarity index 100% rename from lib/RF24/examples_linux/extra/Makefile rename to lib_rf/RF24/examples_linux/extra/Makefile diff --git a/lib/RF24/examples_linux/extra/rpi-hub.cpp b/lib_rf/RF24/examples_linux/extra/rpi-hub.cpp similarity index 100% rename from lib/RF24/examples_linux/extra/rpi-hub.cpp rename to lib_rf/RF24/examples_linux/extra/rpi-hub.cpp diff --git a/lib/RF24/examples_linux/extra/scanner.cpp b/lib_rf/RF24/examples_linux/extra/scanner.cpp similarity index 100% rename from lib/RF24/examples_linux/extra/scanner.cpp rename to lib_rf/RF24/examples_linux/extra/scanner.cpp diff --git a/lib/RF24/examples_linux/gettingstarted.cpp b/lib_rf/RF24/examples_linux/gettingstarted.cpp similarity index 100% rename from lib/RF24/examples_linux/gettingstarted.cpp rename to lib_rf/RF24/examples_linux/gettingstarted.cpp diff --git a/lib/RF24/examples_linux/gettingstarted_call_response.cpp b/lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp similarity index 100% rename from lib/RF24/examples_linux/gettingstarted_call_response.cpp rename to lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp diff --git a/lib/RF24/examples_linux/interrupts/Makefile b/lib_rf/RF24/examples_linux/interrupts/Makefile similarity index 100% rename from lib/RF24/examples_linux/interrupts/Makefile rename to lib_rf/RF24/examples_linux/interrupts/Makefile diff --git a/lib/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp b/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp similarity index 100% rename from lib/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp rename to lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp diff --git a/lib/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp b/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp similarity index 100% rename from lib/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp rename to lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp diff --git a/lib/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp b/lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp similarity index 100% rename from lib/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp rename to lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp diff --git a/lib/RF24/examples_linux/interrupts/transfer_interrupt.cpp b/lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp similarity index 100% rename from lib/RF24/examples_linux/interrupts/transfer_interrupt.cpp rename to lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp diff --git a/lib/RF24/examples_linux/pingpair_dyn.cpp b/lib_rf/RF24/examples_linux/pingpair_dyn.cpp similarity index 100% rename from lib/RF24/examples_linux/pingpair_dyn.cpp rename to lib_rf/RF24/examples_linux/pingpair_dyn.cpp diff --git a/lib/RF24/examples_linux/pingpair_dyn.py b/lib_rf/RF24/examples_linux/pingpair_dyn.py old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/examples_linux/pingpair_dyn.py rename to lib_rf/RF24/examples_linux/pingpair_dyn.py diff --git a/lib/RF24/examples_linux/readme.md b/lib_rf/RF24/examples_linux/readme.md similarity index 100% rename from lib/RF24/examples_linux/readme.md rename to lib_rf/RF24/examples_linux/readme.md diff --git a/lib/RF24/examples_linux/transfer.cpp b/lib_rf/RF24/examples_linux/transfer.cpp similarity index 100% rename from lib/RF24/examples_linux/transfer.cpp rename to lib_rf/RF24/examples_linux/transfer.cpp diff --git a/lib/RF24/keywords.txt b/lib_rf/RF24/keywords.txt similarity index 100% rename from lib/RF24/keywords.txt rename to lib_rf/RF24/keywords.txt diff --git a/lib/RF24/library.json b/lib_rf/RF24/library.json similarity index 100% rename from lib/RF24/library.json rename to lib_rf/RF24/library.json diff --git a/lib/RF24/library.properties b/lib_rf/RF24/library.properties similarity index 100% rename from lib/RF24/library.properties rename to lib_rf/RF24/library.properties diff --git a/lib/RF24/nRF24L01.h b/lib_rf/RF24/nRF24L01.h similarity index 100% rename from lib/RF24/nRF24L01.h rename to lib_rf/RF24/nRF24L01.h diff --git a/lib/RF24/printf.h b/lib_rf/RF24/printf.h similarity index 100% rename from lib/RF24/printf.h rename to lib_rf/RF24/printf.h diff --git a/lib/RF24/pyRF24/crossunixccompiler.py b/lib_rf/RF24/pyRF24/crossunixccompiler.py similarity index 100% rename from lib/RF24/pyRF24/crossunixccompiler.py rename to lib_rf/RF24/pyRF24/crossunixccompiler.py diff --git a/lib/RF24/pyRF24/pyRF24.cpp b/lib_rf/RF24/pyRF24/pyRF24.cpp similarity index 100% rename from lib/RF24/pyRF24/pyRF24.cpp rename to lib_rf/RF24/pyRF24/pyRF24.cpp diff --git a/lib/RF24/pyRF24/pyRF24/crossunixccompiler.py b/lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24/crossunixccompiler.py rename to lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py diff --git a/lib/RF24/pyRF24/pyRF24/pyRF24.cpp b/lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp similarity index 100% rename from lib/RF24/pyRF24/pyRF24/pyRF24.cpp rename to lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp diff --git a/lib/RF24/pyRF24/pyRF24/readme.md b/lib_rf/RF24/pyRF24/pyRF24/readme.md similarity index 100% rename from lib/RF24/pyRF24/pyRF24/readme.md rename to lib_rf/RF24/pyRF24/pyRF24/readme.md diff --git a/lib/RF24/pyRF24/pyRF24/setup.py b/lib_rf/RF24/pyRF24/pyRF24/setup.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24/setup.py rename to lib_rf/RF24/pyRF24/pyRF24/setup.py diff --git a/lib/RF24/pyRF24/pyRF24Mesh/example_master.py b/lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24Mesh/example_master.py rename to lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py diff --git a/lib/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp b/lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp similarity index 100% rename from lib/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp rename to lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp diff --git a/lib/RF24/pyRF24/pyRF24Mesh/setup.py b/lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24Mesh/setup.py rename to lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py diff --git a/lib/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py b/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py rename to lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py diff --git a/lib/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py b/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py rename to lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py diff --git a/lib/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp b/lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp similarity index 100% rename from lib/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp rename to lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp diff --git a/lib/RF24/pyRF24/pyRF24Network/setup.py b/lib_rf/RF24/pyRF24/pyRF24Network/setup.py similarity index 100% rename from lib/RF24/pyRF24/pyRF24Network/setup.py rename to lib_rf/RF24/pyRF24/pyRF24Network/setup.py diff --git a/lib/RF24/pyRF24/readme.md b/lib_rf/RF24/pyRF24/readme.md similarity index 100% rename from lib/RF24/pyRF24/readme.md rename to lib_rf/RF24/pyRF24/readme.md diff --git a/lib/RF24/pyRF24/setup.py b/lib_rf/RF24/pyRF24/setup.py similarity index 100% rename from lib/RF24/pyRF24/setup.py rename to lib_rf/RF24/pyRF24/setup.py diff --git a/lib/RF24/tests/README b/lib_rf/RF24/tests/README similarity index 100% rename from lib/RF24/tests/README rename to lib_rf/RF24/tests/README diff --git a/lib/RF24/tests/native/Jamfile b/lib_rf/RF24/tests/native/Jamfile similarity index 100% rename from lib/RF24/tests/native/Jamfile rename to lib_rf/RF24/tests/native/Jamfile diff --git a/lib/RF24/tests/native/pingpair_irq.pde b/lib_rf/RF24/tests/native/pingpair_irq.pde similarity index 100% rename from lib/RF24/tests/native/pingpair_irq.pde rename to lib_rf/RF24/tests/native/pingpair_irq.pde diff --git a/lib/RF24/tests/native/printf.h b/lib_rf/RF24/tests/native/printf.h similarity index 100% rename from lib/RF24/tests/native/printf.h rename to lib_rf/RF24/tests/native/printf.h diff --git a/lib/RF24/tests/pingpair_blocking/Jamfile b/lib_rf/RF24/tests/pingpair_blocking/Jamfile similarity index 100% rename from lib/RF24/tests/pingpair_blocking/Jamfile rename to lib_rf/RF24/tests/pingpair_blocking/Jamfile diff --git a/lib/RF24/tests/pingpair_blocking/pingpair_blocking.pde b/lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde similarity index 100% rename from lib/RF24/tests/pingpair_blocking/pingpair_blocking.pde rename to lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde diff --git a/lib/RF24/tests/pingpair_blocking/printf.h b/lib_rf/RF24/tests/pingpair_blocking/printf.h similarity index 100% rename from lib/RF24/tests/pingpair_blocking/printf.h rename to lib_rf/RF24/tests/pingpair_blocking/printf.h diff --git a/lib/RF24/tests/pingpair_blocking/runtest.py b/lib_rf/RF24/tests/pingpair_blocking/runtest.py old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_blocking/runtest.py rename to lib_rf/RF24/tests/pingpair_blocking/runtest.py diff --git a/lib/RF24/tests/pingpair_blocking/runtests.sh b/lib_rf/RF24/tests/pingpair_blocking/runtests.sh old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_blocking/runtests.sh rename to lib_rf/RF24/tests/pingpair_blocking/runtests.sh diff --git a/lib/RF24/tests/pingpair_blocking/test.ex b/lib_rf/RF24/tests/pingpair_blocking/test.ex old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_blocking/test.ex rename to lib_rf/RF24/tests/pingpair_blocking/test.ex diff --git a/lib/RF24/tests/pingpair_test/Jamfile b/lib_rf/RF24/tests/pingpair_test/Jamfile similarity index 100% rename from lib/RF24/tests/pingpair_test/Jamfile rename to lib_rf/RF24/tests/pingpair_test/Jamfile diff --git a/lib/RF24/tests/pingpair_test/pingpair_test.pde b/lib_rf/RF24/tests/pingpair_test/pingpair_test.pde similarity index 100% rename from lib/RF24/tests/pingpair_test/pingpair_test.pde rename to lib_rf/RF24/tests/pingpair_test/pingpair_test.pde diff --git a/lib/RF24/tests/pingpair_test/printf.h b/lib_rf/RF24/tests/pingpair_test/printf.h similarity index 100% rename from lib/RF24/tests/pingpair_test/printf.h rename to lib_rf/RF24/tests/pingpair_test/printf.h diff --git a/lib/RF24/tests/pingpair_test/runtest.py b/lib_rf/RF24/tests/pingpair_test/runtest.py old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_test/runtest.py rename to lib_rf/RF24/tests/pingpair_test/runtest.py diff --git a/lib/RF24/tests/pingpair_test/runtests.sh b/lib_rf/RF24/tests/pingpair_test/runtests.sh old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_test/runtests.sh rename to lib_rf/RF24/tests/pingpair_test/runtests.sh diff --git a/lib/RF24/tests/pingpair_test/test.ex b/lib_rf/RF24/tests/pingpair_test/test.ex old mode 100755 new mode 100644 similarity index 100% rename from lib/RF24/tests/pingpair_test/test.ex rename to lib_rf/RF24/tests/pingpair_test/test.ex diff --git a/lib/RF24/utility/ATTiny/RF24_arch_config.h b/lib_rf/RF24/utility/ATTiny/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/ATTiny/RF24_arch_config.h rename to lib_rf/RF24/utility/ATTiny/RF24_arch_config.h diff --git a/lib/RF24/utility/ATTiny/spi.h b/lib_rf/RF24/utility/ATTiny/spi.h similarity index 100% rename from lib/RF24/utility/ATTiny/spi.h rename to lib_rf/RF24/utility/ATTiny/spi.h diff --git a/lib/RF24/utility/ATXMegaD3/README.md b/lib_rf/RF24/utility/ATXMegaD3/README.md similarity index 100% rename from lib/RF24/utility/ATXMegaD3/README.md rename to lib_rf/RF24/utility/ATXMegaD3/README.md diff --git a/lib/RF24/utility/ATXMegaD3/RF24_arch_config.h b/lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/RF24_arch_config.h rename to lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h diff --git a/lib/RF24/utility/ATXMegaD3/compatibility.c b/lib_rf/RF24/utility/ATXMegaD3/compatibility.c similarity index 100% rename from lib/RF24/utility/ATXMegaD3/compatibility.c rename to lib_rf/RF24/utility/ATXMegaD3/compatibility.c diff --git a/lib/RF24/utility/ATXMegaD3/compatibility.h b/lib_rf/RF24/utility/ATXMegaD3/compatibility.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/compatibility.h rename to lib_rf/RF24/utility/ATXMegaD3/compatibility.h diff --git a/lib/RF24/utility/ATXMegaD3/gpio.cpp b/lib_rf/RF24/utility/ATXMegaD3/gpio.cpp similarity index 100% rename from lib/RF24/utility/ATXMegaD3/gpio.cpp rename to lib_rf/RF24/utility/ATXMegaD3/gpio.cpp diff --git a/lib/RF24/utility/ATXMegaD3/gpio.h b/lib_rf/RF24/utility/ATXMegaD3/gpio.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/gpio.h rename to lib_rf/RF24/utility/ATXMegaD3/gpio.h diff --git a/lib/RF24/utility/ATXMegaD3/gpio_helper.c b/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c similarity index 100% rename from lib/RF24/utility/ATXMegaD3/gpio_helper.c rename to lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c diff --git a/lib/RF24/utility/ATXMegaD3/gpio_helper.h b/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/gpio_helper.h rename to lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h diff --git a/lib/RF24/utility/ATXMegaD3/includes.h b/lib_rf/RF24/utility/ATXMegaD3/includes.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/includes.h rename to lib_rf/RF24/utility/ATXMegaD3/includes.h diff --git a/lib/RF24/utility/ATXMegaD3/spi.cpp b/lib_rf/RF24/utility/ATXMegaD3/spi.cpp similarity index 100% rename from lib/RF24/utility/ATXMegaD3/spi.cpp rename to lib_rf/RF24/utility/ATXMegaD3/spi.cpp diff --git a/lib/RF24/utility/ATXMegaD3/spi.h b/lib_rf/RF24/utility/ATXMegaD3/spi.h similarity index 100% rename from lib/RF24/utility/ATXMegaD3/spi.h rename to lib_rf/RF24/utility/ATXMegaD3/spi.h diff --git a/lib/RF24/utility/Due/RF24_arch_config.h b/lib_rf/RF24/utility/Due/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/Due/RF24_arch_config.h rename to lib_rf/RF24/utility/Due/RF24_arch_config.h diff --git a/lib/RF24/utility/LittleWire/RF24_arch_config.h b/lib_rf/RF24/utility/LittleWire/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/LittleWire/RF24_arch_config.h rename to lib_rf/RF24/utility/LittleWire/RF24_arch_config.h diff --git a/lib/RF24/utility/LittleWire/includes.h b/lib_rf/RF24/utility/LittleWire/includes.h similarity index 100% rename from lib/RF24/utility/LittleWire/includes.h rename to lib_rf/RF24/utility/LittleWire/includes.h diff --git a/lib/RF24/utility/MRAA/RF24_arch_config.h b/lib_rf/RF24/utility/MRAA/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/MRAA/RF24_arch_config.h rename to lib_rf/RF24/utility/MRAA/RF24_arch_config.h diff --git a/lib/RF24/utility/MRAA/compatibility.c b/lib_rf/RF24/utility/MRAA/compatibility.c similarity index 100% rename from lib/RF24/utility/MRAA/compatibility.c rename to lib_rf/RF24/utility/MRAA/compatibility.c diff --git a/lib/RF24/utility/MRAA/compatibility.h b/lib_rf/RF24/utility/MRAA/compatibility.h similarity index 100% rename from lib/RF24/utility/MRAA/compatibility.h rename to lib_rf/RF24/utility/MRAA/compatibility.h diff --git a/lib/RF24/utility/MRAA/gpio.cpp b/lib_rf/RF24/utility/MRAA/gpio.cpp similarity index 100% rename from lib/RF24/utility/MRAA/gpio.cpp rename to lib_rf/RF24/utility/MRAA/gpio.cpp diff --git a/lib/RF24/utility/MRAA/gpio.h b/lib_rf/RF24/utility/MRAA/gpio.h similarity index 100% rename from lib/RF24/utility/MRAA/gpio.h rename to lib_rf/RF24/utility/MRAA/gpio.h diff --git a/lib/RF24/utility/MRAA/includes.h b/lib_rf/RF24/utility/MRAA/includes.h similarity index 100% rename from lib/RF24/utility/MRAA/includes.h rename to lib_rf/RF24/utility/MRAA/includes.h diff --git a/lib/RF24/utility/MRAA/spi.cpp b/lib_rf/RF24/utility/MRAA/spi.cpp similarity index 100% rename from lib/RF24/utility/MRAA/spi.cpp rename to lib_rf/RF24/utility/MRAA/spi.cpp diff --git a/lib/RF24/utility/MRAA/spi.h b/lib_rf/RF24/utility/MRAA/spi.h similarity index 100% rename from lib/RF24/utility/MRAA/spi.h rename to lib_rf/RF24/utility/MRAA/spi.h diff --git a/lib/RF24/utility/RPi/RF24_arch_config.h b/lib_rf/RF24/utility/RPi/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/RPi/RF24_arch_config.h rename to lib_rf/RF24/utility/RPi/RF24_arch_config.h diff --git a/lib/RF24/utility/RPi/bcm2835.c b/lib_rf/RF24/utility/RPi/bcm2835.c similarity index 100% rename from lib/RF24/utility/RPi/bcm2835.c rename to lib_rf/RF24/utility/RPi/bcm2835.c diff --git a/lib/RF24/utility/RPi/bcm2835.h b/lib_rf/RF24/utility/RPi/bcm2835.h similarity index 100% rename from lib/RF24/utility/RPi/bcm2835.h rename to lib_rf/RF24/utility/RPi/bcm2835.h diff --git a/lib/RF24/utility/RPi/includes.h b/lib_rf/RF24/utility/RPi/includes.h similarity index 100% rename from lib/RF24/utility/RPi/includes.h rename to lib_rf/RF24/utility/RPi/includes.h diff --git a/lib/RF24/utility/RPi/interrupt.c b/lib_rf/RF24/utility/RPi/interrupt.c similarity index 100% rename from lib/RF24/utility/RPi/interrupt.c rename to lib_rf/RF24/utility/RPi/interrupt.c diff --git a/lib/RF24/utility/RPi/interrupt.h b/lib_rf/RF24/utility/RPi/interrupt.h similarity index 100% rename from lib/RF24/utility/RPi/interrupt.h rename to lib_rf/RF24/utility/RPi/interrupt.h diff --git a/lib/RF24/utility/RPi/spi.cpp b/lib_rf/RF24/utility/RPi/spi.cpp similarity index 100% rename from lib/RF24/utility/RPi/spi.cpp rename to lib_rf/RF24/utility/RPi/spi.cpp diff --git a/lib/RF24/utility/RPi/spi.h b/lib_rf/RF24/utility/RPi/spi.h similarity index 100% rename from lib/RF24/utility/RPi/spi.h rename to lib_rf/RF24/utility/RPi/spi.h diff --git a/lib/RF24/utility/SPIDEV/RF24_arch_config.h b/lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/SPIDEV/RF24_arch_config.h rename to lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h diff --git a/lib/RF24/utility/SPIDEV/compatibility.c b/lib_rf/RF24/utility/SPIDEV/compatibility.c similarity index 100% rename from lib/RF24/utility/SPIDEV/compatibility.c rename to lib_rf/RF24/utility/SPIDEV/compatibility.c diff --git a/lib/RF24/utility/SPIDEV/compatibility.h b/lib_rf/RF24/utility/SPIDEV/compatibility.h similarity index 100% rename from lib/RF24/utility/SPIDEV/compatibility.h rename to lib_rf/RF24/utility/SPIDEV/compatibility.h diff --git a/lib/RF24/utility/SPIDEV/gpio.cpp b/lib_rf/RF24/utility/SPIDEV/gpio.cpp similarity index 100% rename from lib/RF24/utility/SPIDEV/gpio.cpp rename to lib_rf/RF24/utility/SPIDEV/gpio.cpp diff --git a/lib/RF24/utility/SPIDEV/gpio.h b/lib_rf/RF24/utility/SPIDEV/gpio.h similarity index 100% rename from lib/RF24/utility/SPIDEV/gpio.h rename to lib_rf/RF24/utility/SPIDEV/gpio.h diff --git a/lib/RF24/utility/SPIDEV/includes.h b/lib_rf/RF24/utility/SPIDEV/includes.h similarity index 100% rename from lib/RF24/utility/SPIDEV/includes.h rename to lib_rf/RF24/utility/SPIDEV/includes.h diff --git a/lib/RF24/utility/SPIDEV/interrupt.c b/lib_rf/RF24/utility/SPIDEV/interrupt.c similarity index 100% rename from lib/RF24/utility/SPIDEV/interrupt.c rename to lib_rf/RF24/utility/SPIDEV/interrupt.c diff --git a/lib/RF24/utility/SPIDEV/interrupt.h b/lib_rf/RF24/utility/SPIDEV/interrupt.h similarity index 100% rename from lib/RF24/utility/SPIDEV/interrupt.h rename to lib_rf/RF24/utility/SPIDEV/interrupt.h diff --git a/lib/RF24/utility/SPIDEV/spi.cpp b/lib_rf/RF24/utility/SPIDEV/spi.cpp similarity index 100% rename from lib/RF24/utility/SPIDEV/spi.cpp rename to lib_rf/RF24/utility/SPIDEV/spi.cpp diff --git a/lib/RF24/utility/SPIDEV/spi.h b/lib_rf/RF24/utility/SPIDEV/spi.h similarity index 100% rename from lib/RF24/utility/SPIDEV/spi.h rename to lib_rf/RF24/utility/SPIDEV/spi.h diff --git a/lib/RF24/utility/Teensy/RF24_arch_config.h b/lib_rf/RF24/utility/Teensy/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/Teensy/RF24_arch_config.h rename to lib_rf/RF24/utility/Teensy/RF24_arch_config.h diff --git a/lib/RF24/utility/Template/RF24_arch_config.h b/lib_rf/RF24/utility/Template/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/Template/RF24_arch_config.h rename to lib_rf/RF24/utility/Template/RF24_arch_config.h diff --git a/lib/RF24/utility/Template/compatibility.h b/lib_rf/RF24/utility/Template/compatibility.h similarity index 100% rename from lib/RF24/utility/Template/compatibility.h rename to lib_rf/RF24/utility/Template/compatibility.h diff --git a/lib/RF24/utility/Template/gpio.h b/lib_rf/RF24/utility/Template/gpio.h similarity index 100% rename from lib/RF24/utility/Template/gpio.h rename to lib_rf/RF24/utility/Template/gpio.h diff --git a/lib/RF24/utility/Template/includes.h b/lib_rf/RF24/utility/Template/includes.h similarity index 100% rename from lib/RF24/utility/Template/includes.h rename to lib_rf/RF24/utility/Template/includes.h diff --git a/lib/RF24/utility/Template/spi.h b/lib_rf/RF24/utility/Template/spi.h similarity index 100% rename from lib/RF24/utility/Template/spi.h rename to lib_rf/RF24/utility/Template/spi.h diff --git a/lib/RF24/utility/wiringPi/RF24_arch_config.h b/lib_rf/RF24/utility/wiringPi/RF24_arch_config.h similarity index 100% rename from lib/RF24/utility/wiringPi/RF24_arch_config.h rename to lib_rf/RF24/utility/wiringPi/RF24_arch_config.h diff --git a/lib/RF24/utility/wiringPi/includes.h b/lib_rf/RF24/utility/wiringPi/includes.h similarity index 100% rename from lib/RF24/utility/wiringPi/includes.h rename to lib_rf/RF24/utility/wiringPi/includes.h diff --git a/lib/RF24/utility/wiringPi/spi.cpp b/lib_rf/RF24/utility/wiringPi/spi.cpp similarity index 100% rename from lib/RF24/utility/wiringPi/spi.cpp rename to lib_rf/RF24/utility/wiringPi/spi.cpp diff --git a/lib/RF24/utility/wiringPi/spi.h b/lib_rf/RF24/utility/wiringPi/spi.h similarity index 100% rename from lib/RF24/utility/wiringPi/spi.h rename to lib_rf/RF24/utility/wiringPi/spi.h diff --git a/lib/RF24/wikidoc.xslt b/lib_rf/RF24/wikidoc.xslt similarity index 100% rename from lib/RF24/wikidoc.xslt rename to lib_rf/RF24/wikidoc.xslt diff --git a/lib/cc1101/README.md b/lib_rf/cc1101/README.md similarity index 100% rename from lib/cc1101/README.md rename to lib_rf/cc1101/README.md diff --git a/lib/cc1101/cc1101.cpp b/lib_rf/cc1101/cc1101.cpp similarity index 100% rename from lib/cc1101/cc1101.cpp rename to lib_rf/cc1101/cc1101.cpp diff --git a/lib/cc1101/cc1101.h b/lib_rf/cc1101/cc1101.h similarity index 100% rename from lib/cc1101/cc1101.h rename to lib_rf/cc1101/cc1101.h diff --git a/lib/cc1101/cc1101.h.txt b/lib_rf/cc1101/cc1101.h.txt similarity index 100% rename from lib/cc1101/cc1101.h.txt rename to lib_rf/cc1101/cc1101.h.txt diff --git a/lib/cc1101/ccpacket.h b/lib_rf/cc1101/ccpacket.h similarity index 100% rename from lib/cc1101/ccpacket.h rename to lib_rf/cc1101/ccpacket.h diff --git a/lib/cc1101/library.properties b/lib_rf/cc1101/library.properties similarity index 100% rename from lib/cc1101/library.properties rename to lib_rf/cc1101/library.properties diff --git a/lib/rc-switch/.gitignore b/lib_rf/rc-switch/.gitignore similarity index 100% rename from lib/rc-switch/.gitignore rename to lib_rf/rc-switch/.gitignore diff --git a/lib/rc-switch/README.md b/lib_rf/rc-switch/README.md similarity index 100% rename from lib/rc-switch/README.md rename to lib_rf/rc-switch/README.md diff --git a/lib/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino b/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino similarity index 100% rename from lib/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino rename to lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino diff --git a/lib/rc-switch/examples/ReceiveDemo_Advanced/output.ino b/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino similarity index 100% rename from lib/rc-switch/examples/ReceiveDemo_Advanced/output.ino rename to lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino diff --git a/lib/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino b/lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino similarity index 100% rename from lib/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino rename to lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino diff --git a/lib/rc-switch/examples/SendDemo/SendDemo.ino b/lib_rf/rc-switch/examples/SendDemo/SendDemo.ino similarity index 100% rename from lib/rc-switch/examples/SendDemo/SendDemo.ino rename to lib_rf/rc-switch/examples/SendDemo/SendDemo.ino diff --git a/lib/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino b/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino similarity index 100% rename from lib/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino rename to lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino diff --git a/lib/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino similarity index 100% rename from lib/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino rename to lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino diff --git a/lib/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino b/lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino similarity index 100% rename from lib/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino rename to lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino diff --git a/lib/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino b/lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino similarity index 100% rename from lib/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino rename to lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino diff --git a/lib/rc-switch/examples/TypeD_REV/TypeD_REV.ino b/lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino similarity index 100% rename from lib/rc-switch/examples/TypeD_REV/TypeD_REV.ino rename to lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino diff --git a/lib/rc-switch/examples/Webserver/Webserver.ino b/lib_rf/rc-switch/examples/Webserver/Webserver.ino similarity index 100% rename from lib/rc-switch/examples/Webserver/Webserver.ino rename to lib_rf/rc-switch/examples/Webserver/Webserver.ino diff --git a/lib/rc-switch/keywords.txt b/lib_rf/rc-switch/keywords.txt similarity index 100% rename from lib/rc-switch/keywords.txt rename to lib_rf/rc-switch/keywords.txt diff --git a/lib/rc-switch/library.json b/lib_rf/rc-switch/library.json similarity index 100% rename from lib/rc-switch/library.json rename to lib_rf/rc-switch/library.json diff --git a/lib/rc-switch/library.properties b/lib_rf/rc-switch/library.properties similarity index 100% rename from lib/rc-switch/library.properties rename to lib_rf/rc-switch/library.properties diff --git a/lib/rc-switch/platformio.ini b/lib_rf/rc-switch/platformio.ini similarity index 100% rename from lib/rc-switch/platformio.ini rename to lib_rf/rc-switch/platformio.ini diff --git a/lib/rc-switch/src/RCSwitch.cpp b/lib_rf/rc-switch/src/RCSwitch.cpp similarity index 100% rename from lib/rc-switch/src/RCSwitch.cpp rename to lib_rf/rc-switch/src/RCSwitch.cpp diff --git a/lib/rc-switch/src/RCSwitch.h b/lib_rf/rc-switch/src/RCSwitch.h similarity index 100% rename from lib/rc-switch/src/RCSwitch.h rename to lib_rf/rc-switch/src/RCSwitch.h diff --git a/lib/base64-1.1.1/LICENSE b/lib_ssl/base64-1.1.1/LICENSE similarity index 100% rename from lib/base64-1.1.1/LICENSE rename to lib_ssl/base64-1.1.1/LICENSE diff --git a/lib/base64-1.1.1/Makefile b/lib_ssl/base64-1.1.1/Makefile similarity index 100% rename from lib/base64-1.1.1/Makefile rename to lib_ssl/base64-1.1.1/Makefile diff --git a/lib/base64-1.1.1/README.md b/lib_ssl/base64-1.1.1/README.md similarity index 100% rename from lib/base64-1.1.1/README.md rename to lib_ssl/base64-1.1.1/README.md diff --git a/lib/base64-1.1.1/catch.cpp b/lib_ssl/base64-1.1.1/catch.cpp similarity index 100% rename from lib/base64-1.1.1/catch.cpp rename to lib_ssl/base64-1.1.1/catch.cpp diff --git a/lib/base64-1.1.1/catch.hpp b/lib_ssl/base64-1.1.1/catch.hpp similarity index 100% rename from lib/base64-1.1.1/catch.hpp rename to lib_ssl/base64-1.1.1/catch.hpp diff --git a/lib/base64-1.1.1/library.properties b/lib_ssl/base64-1.1.1/library.properties similarity index 100% rename from lib/base64-1.1.1/library.properties rename to lib_ssl/base64-1.1.1/library.properties diff --git a/lib/base64-1.1.1/src/base64.hpp b/lib_ssl/base64-1.1.1/src/base64.hpp similarity index 100% rename from lib/base64-1.1.1/src/base64.hpp rename to lib_ssl/base64-1.1.1/src/base64.hpp diff --git a/lib/bearssl-esp8266/bearssl_esp8266-customized.txt b/lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt similarity index 100% rename from lib/bearssl-esp8266/bearssl_esp8266-customized.txt rename to lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt diff --git a/lib/bearssl-esp8266/conf/esp8266.mk b/lib_ssl/bearssl-esp8266/conf/esp8266.mk similarity index 100% rename from lib/bearssl-esp8266/conf/esp8266.mk rename to lib_ssl/bearssl-esp8266/conf/esp8266.mk diff --git a/lib/bearssl-esp8266/library.properties b/lib_ssl/bearssl-esp8266/library.properties similarity index 100% rename from lib/bearssl-esp8266/library.properties rename to lib_ssl/bearssl-esp8266/library.properties diff --git a/lib/bearssl-esp8266/src/aead/ccm.c b/lib_ssl/bearssl-esp8266/src/aead/ccm.c similarity index 100% rename from lib/bearssl-esp8266/src/aead/ccm.c rename to lib_ssl/bearssl-esp8266/src/aead/ccm.c diff --git a/lib/bearssl-esp8266/src/aead/eax.c b/lib_ssl/bearssl-esp8266/src/aead/eax.c similarity index 100% rename from lib/bearssl-esp8266/src/aead/eax.c rename to lib_ssl/bearssl-esp8266/src/aead/eax.c diff --git a/lib/bearssl-esp8266/src/aead/gcm.c b/lib_ssl/bearssl-esp8266/src/aead/gcm.c similarity index 100% rename from lib/bearssl-esp8266/src/aead/gcm.c rename to lib_ssl/bearssl-esp8266/src/aead/gcm.c diff --git a/lib/bearssl-esp8266/src/codec/ccopy.c b/lib_ssl/bearssl-esp8266/src/codec/ccopy.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/ccopy.c rename to lib_ssl/bearssl-esp8266/src/codec/ccopy.c diff --git a/lib/bearssl-esp8266/src/codec/dec16be.c b/lib_ssl/bearssl-esp8266/src/codec/dec16be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec16be.c rename to lib_ssl/bearssl-esp8266/src/codec/dec16be.c diff --git a/lib/bearssl-esp8266/src/codec/dec16le.c b/lib_ssl/bearssl-esp8266/src/codec/dec16le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec16le.c rename to lib_ssl/bearssl-esp8266/src/codec/dec16le.c diff --git a/lib/bearssl-esp8266/src/codec/dec32be.c b/lib_ssl/bearssl-esp8266/src/codec/dec32be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec32be.c rename to lib_ssl/bearssl-esp8266/src/codec/dec32be.c diff --git a/lib/bearssl-esp8266/src/codec/dec32le.c b/lib_ssl/bearssl-esp8266/src/codec/dec32le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec32le.c rename to lib_ssl/bearssl-esp8266/src/codec/dec32le.c diff --git a/lib/bearssl-esp8266/src/codec/dec64be.c b/lib_ssl/bearssl-esp8266/src/codec/dec64be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec64be.c rename to lib_ssl/bearssl-esp8266/src/codec/dec64be.c diff --git a/lib/bearssl-esp8266/src/codec/dec64le.c b/lib_ssl/bearssl-esp8266/src/codec/dec64le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/dec64le.c rename to lib_ssl/bearssl-esp8266/src/codec/dec64le.c diff --git a/lib/bearssl-esp8266/src/codec/enc16be.c b/lib_ssl/bearssl-esp8266/src/codec/enc16be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc16be.c rename to lib_ssl/bearssl-esp8266/src/codec/enc16be.c diff --git a/lib/bearssl-esp8266/src/codec/enc16le.c b/lib_ssl/bearssl-esp8266/src/codec/enc16le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc16le.c rename to lib_ssl/bearssl-esp8266/src/codec/enc16le.c diff --git a/lib/bearssl-esp8266/src/codec/enc32be.c b/lib_ssl/bearssl-esp8266/src/codec/enc32be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc32be.c rename to lib_ssl/bearssl-esp8266/src/codec/enc32be.c diff --git a/lib/bearssl-esp8266/src/codec/enc32le.c b/lib_ssl/bearssl-esp8266/src/codec/enc32le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc32le.c rename to lib_ssl/bearssl-esp8266/src/codec/enc32le.c diff --git a/lib/bearssl-esp8266/src/codec/enc64be.c b/lib_ssl/bearssl-esp8266/src/codec/enc64be.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc64be.c rename to lib_ssl/bearssl-esp8266/src/codec/enc64be.c diff --git a/lib/bearssl-esp8266/src/codec/enc64le.c b/lib_ssl/bearssl-esp8266/src/codec/enc64le.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/enc64le.c rename to lib_ssl/bearssl-esp8266/src/codec/enc64le.c diff --git a/lib/bearssl-esp8266/src/codec/pemdec.c b/lib_ssl/bearssl-esp8266/src/codec/pemdec.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/pemdec.c rename to lib_ssl/bearssl-esp8266/src/codec/pemdec.c diff --git a/lib/bearssl-esp8266/src/codec/pemenc.c b/lib_ssl/bearssl-esp8266/src/codec/pemenc.c similarity index 100% rename from lib/bearssl-esp8266/src/codec/pemenc.c rename to lib_ssl/bearssl-esp8266/src/codec/pemenc.c diff --git a/lib/bearssl-esp8266/src/ec/ec_all_m15.c b/lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_all_m15.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c diff --git a/lib/bearssl-esp8266/src/ec/ec_c25519_i15.c b/lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_c25519_i15.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c diff --git a/lib/bearssl-esp8266/src/ec/ec_curve25519.c b/lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_curve25519.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c diff --git a/lib/bearssl-esp8266/src/ec/ec_default.c b/lib_ssl/bearssl-esp8266/src/ec/ec_default.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_default.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_default.c diff --git a/lib/bearssl-esp8266/src/ec/ec_keygen.c b/lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_keygen.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c diff --git a/lib/bearssl-esp8266/src/ec/ec_p256_m15.c b/lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_p256_m15.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c diff --git a/lib/bearssl-esp8266/src/ec/ec_prime_i15.c b/lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_prime_i15.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c diff --git a/lib/bearssl-esp8266/src/ec/ec_pubkey.c b/lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_pubkey.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c diff --git a/lib/bearssl-esp8266/src/ec/ec_secp256r1.c b/lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_secp256r1.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c diff --git a/lib/bearssl-esp8266/src/ec/ec_secp384r1.c b/lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_secp384r1.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c diff --git a/lib/bearssl-esp8266/src/ec/ec_secp521r1.c b/lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ec_secp521r1.c rename to lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_atr.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_atr.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_i15_bits.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_i15_bits.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c diff --git a/lib/bearssl-esp8266/src/ec/ecdsa_rta.c b/lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c similarity index 100% rename from lib/bearssl-esp8266/src/ec/ecdsa_rta.c rename to lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c diff --git a/lib/bearssl-esp8266/src/hash/dig_oid.c b/lib_ssl/bearssl-esp8266/src/hash/dig_oid.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/dig_oid.c rename to lib_ssl/bearssl-esp8266/src/hash/dig_oid.c diff --git a/lib/bearssl-esp8266/src/hash/dig_size.c b/lib_ssl/bearssl-esp8266/src/hash/dig_size.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/dig_size.c rename to lib_ssl/bearssl-esp8266/src/hash/dig_size.c diff --git a/lib/bearssl-esp8266/src/hash/ghash_ctmul.c b/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/ghash_ctmul.c rename to lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c diff --git a/lib/bearssl-esp8266/src/hash/ghash_ctmul32.c b/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/ghash_ctmul32.c rename to lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c diff --git a/lib/bearssl-esp8266/src/hash/ghash_ctmul64.c b/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/ghash_ctmul64.c rename to lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c diff --git a/lib/bearssl-esp8266/src/hash/ghash_pclmul.c b/lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/ghash_pclmul.c rename to lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c diff --git a/lib/bearssl-esp8266/src/hash/md5.c b/lib_ssl/bearssl-esp8266/src/hash/md5.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/md5.c rename to lib_ssl/bearssl-esp8266/src/hash/md5.c diff --git a/lib/bearssl-esp8266/src/hash/md5sha1.c b/lib_ssl/bearssl-esp8266/src/hash/md5sha1.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/md5sha1.c rename to lib_ssl/bearssl-esp8266/src/hash/md5sha1.c diff --git a/lib/bearssl-esp8266/src/hash/mgf1.c b/lib_ssl/bearssl-esp8266/src/hash/mgf1.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/mgf1.c rename to lib_ssl/bearssl-esp8266/src/hash/mgf1.c diff --git a/lib/bearssl-esp8266/src/hash/multihash.c b/lib_ssl/bearssl-esp8266/src/hash/multihash.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/multihash.c rename to lib_ssl/bearssl-esp8266/src/hash/multihash.c diff --git a/lib/bearssl-esp8266/src/hash/sha1.c b/lib_ssl/bearssl-esp8266/src/hash/sha1.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/sha1.c rename to lib_ssl/bearssl-esp8266/src/hash/sha1.c diff --git a/lib/bearssl-esp8266/src/hash/sha2big.c b/lib_ssl/bearssl-esp8266/src/hash/sha2big.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/sha2big.c rename to lib_ssl/bearssl-esp8266/src/hash/sha2big.c diff --git a/lib/bearssl-esp8266/src/hash/sha2small.c b/lib_ssl/bearssl-esp8266/src/hash/sha2small.c similarity index 100% rename from lib/bearssl-esp8266/src/hash/sha2small.c rename to lib_ssl/bearssl-esp8266/src/hash/sha2small.c diff --git a/lib/bearssl-esp8266/src/int/i15_add.c b/lib_ssl/bearssl-esp8266/src/int/i15_add.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_add.c rename to lib_ssl/bearssl-esp8266/src/int/i15_add.c diff --git a/lib/bearssl-esp8266/src/int/i15_bitlen.c b/lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_bitlen.c rename to lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c diff --git a/lib/bearssl-esp8266/src/int/i15_decmod.c b/lib_ssl/bearssl-esp8266/src/int/i15_decmod.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_decmod.c rename to lib_ssl/bearssl-esp8266/src/int/i15_decmod.c diff --git a/lib/bearssl-esp8266/src/int/i15_decode.c b/lib_ssl/bearssl-esp8266/src/int/i15_decode.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_decode.c rename to lib_ssl/bearssl-esp8266/src/int/i15_decode.c diff --git a/lib/bearssl-esp8266/src/int/i15_decred.c b/lib_ssl/bearssl-esp8266/src/int/i15_decred.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_decred.c rename to lib_ssl/bearssl-esp8266/src/int/i15_decred.c diff --git a/lib/bearssl-esp8266/src/int/i15_encode.c b/lib_ssl/bearssl-esp8266/src/int/i15_encode.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_encode.c rename to lib_ssl/bearssl-esp8266/src/int/i15_encode.c diff --git a/lib/bearssl-esp8266/src/int/i15_fmont.c b/lib_ssl/bearssl-esp8266/src/int/i15_fmont.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_fmont.c rename to lib_ssl/bearssl-esp8266/src/int/i15_fmont.c diff --git a/lib/bearssl-esp8266/src/int/i15_iszero.c b/lib_ssl/bearssl-esp8266/src/int/i15_iszero.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_iszero.c rename to lib_ssl/bearssl-esp8266/src/int/i15_iszero.c diff --git a/lib/bearssl-esp8266/src/int/i15_moddiv.c b/lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_moddiv.c rename to lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c diff --git a/lib/bearssl-esp8266/src/int/i15_modpow.c b/lib_ssl/bearssl-esp8266/src/int/i15_modpow.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_modpow.c rename to lib_ssl/bearssl-esp8266/src/int/i15_modpow.c diff --git a/lib/bearssl-esp8266/src/int/i15_modpow2.c b/lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_modpow2.c rename to lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c diff --git a/lib/bearssl-esp8266/src/int/i15_montmul.c b/lib_ssl/bearssl-esp8266/src/int/i15_montmul.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_montmul.c rename to lib_ssl/bearssl-esp8266/src/int/i15_montmul.c diff --git a/lib/bearssl-esp8266/src/int/i15_mulacc.c b/lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_mulacc.c rename to lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c diff --git a/lib/bearssl-esp8266/src/int/i15_muladd.c b/lib_ssl/bearssl-esp8266/src/int/i15_muladd.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_muladd.c rename to lib_ssl/bearssl-esp8266/src/int/i15_muladd.c diff --git a/lib/bearssl-esp8266/src/int/i15_ninv15.c b/lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_ninv15.c rename to lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c diff --git a/lib/bearssl-esp8266/src/int/i15_reduce.c b/lib_ssl/bearssl-esp8266/src/int/i15_reduce.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_reduce.c rename to lib_ssl/bearssl-esp8266/src/int/i15_reduce.c diff --git a/lib/bearssl-esp8266/src/int/i15_rshift.c b/lib_ssl/bearssl-esp8266/src/int/i15_rshift.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_rshift.c rename to lib_ssl/bearssl-esp8266/src/int/i15_rshift.c diff --git a/lib/bearssl-esp8266/src/int/i15_sub.c b/lib_ssl/bearssl-esp8266/src/int/i15_sub.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_sub.c rename to lib_ssl/bearssl-esp8266/src/int/i15_sub.c diff --git a/lib/bearssl-esp8266/src/int/i15_tmont.c b/lib_ssl/bearssl-esp8266/src/int/i15_tmont.c similarity index 100% rename from lib/bearssl-esp8266/src/int/i15_tmont.c rename to lib_ssl/bearssl-esp8266/src/int/i15_tmont.c diff --git a/lib/bearssl-esp8266/src/kdf/hkdf.c b/lib_ssl/bearssl-esp8266/src/kdf/hkdf.c similarity index 100% rename from lib/bearssl-esp8266/src/kdf/hkdf.c rename to lib_ssl/bearssl-esp8266/src/kdf/hkdf.c diff --git a/lib/bearssl-esp8266/src/kdf/shake.c b/lib_ssl/bearssl-esp8266/src/kdf/shake.c similarity index 100% rename from lib/bearssl-esp8266/src/kdf/shake.c rename to lib_ssl/bearssl-esp8266/src/kdf/shake.c diff --git a/lib/bearssl-esp8266/src/mac/hmac.c b/lib_ssl/bearssl-esp8266/src/mac/hmac.c similarity index 100% rename from lib/bearssl-esp8266/src/mac/hmac.c rename to lib_ssl/bearssl-esp8266/src/mac/hmac.c diff --git a/lib/bearssl-esp8266/src/mac/hmac_ct.c b/lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c similarity index 100% rename from lib/bearssl-esp8266/src/mac/hmac_ct.c rename to lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c diff --git a/lib/bearssl-esp8266/src/pgmspace_bearssl.h b/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h similarity index 100% rename from lib/bearssl-esp8266/src/pgmspace_bearssl.h rename to lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h diff --git a/lib/bearssl-esp8266/src/rand/aesctr_drbg.c b/lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c similarity index 100% rename from lib/bearssl-esp8266/src/rand/aesctr_drbg.c rename to lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c diff --git a/lib/bearssl-esp8266/src/rand/hmac_drbg.c b/lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c similarity index 100% rename from lib/bearssl-esp8266/src/rand/hmac_drbg.c rename to lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c diff --git a/lib/bearssl-esp8266/src/rand/sysrng.c b/lib_ssl/bearssl-esp8266/src/rand/sysrng.c similarity index 100% rename from lib/bearssl-esp8266/src/rand/sysrng.c rename to lib_ssl/bearssl-esp8266/src/rand/sysrng.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_keygen.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_keygen.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_modulus.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_modulus.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_priv.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_priv.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_privexp.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_privexp.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pub.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pub.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_default_pubexp.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_default_pubexp.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_keygen.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_keygen.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_modulus.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_modulus.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_priv.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_priv.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_privexp.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_privexp.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pub.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pub.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_oaep_pad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_oaep_pad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c diff --git a/lib/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c b/lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c similarity index 100% rename from lib/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c rename to lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c diff --git a/lib/bearssl-esp8266/src/settings.c b/lib_ssl/bearssl-esp8266/src/settings.c similarity index 100% rename from lib/bearssl-esp8266/src/settings.c rename to lib_ssl/bearssl-esp8266/src/settings.c diff --git a/lib/bearssl-esp8266/src/ssl/prf.c b/lib_ssl/bearssl-esp8266/src/ssl/prf.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/prf.c rename to lib_ssl/bearssl-esp8266/src/ssl/prf.c diff --git a/lib/bearssl-esp8266/src/ssl/prf_md5sha1.c b/lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/prf_md5sha1.c rename to lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c diff --git a/lib/bearssl-esp8266/src/ssl/prf_sha256.c b/lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/prf_sha256.c rename to lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c diff --git a/lib/bearssl-esp8266/src/ssl/prf_sha384.c b/lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/prf_sha384.c rename to lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_client.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_client.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_client_full.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_client_full.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_hashes.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_hashes.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_hs_client.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_hs_client.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_hs_server.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_hs_server.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_io.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_io.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_keyexport.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_keyexport.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_lru.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_lru.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_rec_cbc.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_rec_cbc.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_rec_ccm.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_rec_ccm.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_rec_chapol.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_rec_chapol.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_rec_gcm.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_rec_gcm.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c diff --git a/lib/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c b/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c similarity index 100% rename from lib/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c rename to lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_ctr.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_ctr.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_dec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_dec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_big_enc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_big_enc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_common.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_common.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_dec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_dec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct64_enc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct64_enc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_ctr.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_ctr.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_dec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_dec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_ct_enc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_ct_enc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_ctr.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_ctr.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_dec.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_dec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c diff --git a/lib/bearssl-esp8266/src/symcipher/aes_small_enc.c b/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/aes_small_enc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c diff --git a/lib/bearssl-esp8266/src/symcipher/chacha20_ct.c b/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/chacha20_ct.c rename to lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c diff --git a/lib/bearssl-esp8266/src/symcipher/chacha20_sse2.c b/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/chacha20_sse2.c rename to lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_ct.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_ct.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_support.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_support.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_support.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_support.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_tab.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_tab.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c diff --git a/lib/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c b/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c rename to lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c diff --git a/lib/bearssl-esp8266/src/symcipher/poly1305_ctmul.c b/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/poly1305_ctmul.c rename to lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c diff --git a/lib/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c b/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c rename to lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c diff --git a/lib/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c b/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c rename to lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c diff --git a/lib/bearssl-esp8266/src/symcipher/poly1305_i15.c b/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c similarity index 100% rename from lib/bearssl-esp8266/src/symcipher/poly1305_i15.c rename to lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c diff --git a/lib/bearssl-esp8266/src/t_bearssl.h b/lib_ssl/bearssl-esp8266/src/t_bearssl.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_aead.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_aead.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_block.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_block.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_block.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_block.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_ec.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_ec.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_hash.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_hash.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_hmac.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_hmac.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_kdf.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_kdf.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_pem.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_pem.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_prf.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_prf.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_rand.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_rand.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_rsa.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_rsa.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_ssl.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_ssl.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_tasmota_config.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_tasmota_config.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h diff --git a/lib/bearssl-esp8266/src/t_bearssl_x509.h b/lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h similarity index 100% rename from lib/bearssl-esp8266/src/t_bearssl_x509.h rename to lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h diff --git a/lib/bearssl-esp8266/src/t_config.h b/lib_ssl/bearssl-esp8266/src/t_config.h similarity index 100% rename from lib/bearssl-esp8266/src/t_config.h rename to lib_ssl/bearssl-esp8266/src/t_config.h diff --git a/lib/bearssl-esp8266/src/t_inner.h b/lib_ssl/bearssl-esp8266/src/t_inner.h similarity index 100% rename from lib/bearssl-esp8266/src/t_inner.h rename to lib_ssl/bearssl-esp8266/src/t_inner.h diff --git a/lib/bearssl-esp8266/src/x509/asn1enc.c b/lib_ssl/bearssl-esp8266/src/x509/asn1enc.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/asn1enc.c rename to lib_ssl/bearssl-esp8266/src/x509/asn1enc.c diff --git a/lib/bearssl-esp8266/src/x509/encode_ec_pk8der.c b/lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/encode_ec_pk8der.c rename to lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c diff --git a/lib/bearssl-esp8266/src/x509/encode_ec_rawder.c b/lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/encode_ec_rawder.c rename to lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c diff --git a/lib/bearssl-esp8266/src/x509/encode_rsa_pk8der.c b/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/encode_rsa_pk8der.c rename to lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c diff --git a/lib/bearssl-esp8266/src/x509/encode_rsa_rawder.c b/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/encode_rsa_rawder.c rename to lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c diff --git a/lib/bearssl-esp8266/src/x509/pkey_decoder.c b/lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/pkey_decoder.c rename to lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c diff --git a/lib/bearssl-esp8266/src/x509/skey_decoder.c b/lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/skey_decoder.c rename to lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c diff --git a/lib/bearssl-esp8266/src/x509/x509_decoder.c b/lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/x509_decoder.c rename to lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c diff --git a/lib/bearssl-esp8266/src/x509/x509_knownkey.c b/lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/x509_knownkey.c rename to lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c diff --git a/lib/bearssl-esp8266/src/x509/x509_minimal.c b/lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/x509_minimal.c rename to lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c diff --git a/lib/bearssl-esp8266/src/x509/x509_minimal_full.c b/lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c similarity index 100% rename from lib/bearssl-esp8266/src/x509/x509_minimal_full.c rename to lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c diff --git a/platformio.ini b/platformio.ini index 4d33b9a7f..64c4d4c6c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -59,7 +59,7 @@ build_cache_dir = .cache extra_configs = platformio_tasmota32.ini platformio_tasmota_env.ini platformio_tasmota_env32.ini - platformio_lib.ini + ;platformio_lib.ini platformio_override.ini default_envs = ${build_envs.default_envs} @@ -82,7 +82,16 @@ upload_speed = 115200 upload_resetmethod = nodemcu upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} +lib_ldf_mode = chain+ shared_libdeps_dir = lib +lib_extra_dirs = + lib_basic + lib_i2c + lib_display + lib_ssl + lib_audio + lib_rf + lib_div [scripts_defaults] extra_scripts = pio/strip-floats.py diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 35768c686..2adcce410 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -76,8 +76,14 @@ build_flags = ${esp_defaults.build_flags} -D memcpy_P=memcpy -D memcmp_P=memcmp -lib_extra_dirs = +lib_ldf_mode = chain+ +shared_libdeps_dir = lib +lib_extra_dirs = libesp32 - -lib_ignore = - cc1101 + lib_basic + lib_i2c + lib_display + lib_ssl + lib_audio + lib_rf + lib_div diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 06c36cc7c..c88ad75e2 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -14,131 +14,124 @@ upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -lib_extra_dirs = ${common.shared_libdeps_dir} +lib_extra_dirs = ${common.lib_extra_dirs} +lib_ignore = + Servo(esp8266) + ESP8266AVRISP + ESP8266LLMNR + ESP8266NetBIOS + ESP8266SSDP + SP8266WiFiMesh + Ethernet(esp8266) + GDBStub + TFT_Touch_Shield_V2 + ESP8266HTTPUpdateServer + ESP8266WiFiMesh + EspSoftwareSerial + SPISlave + Hash [env:tasmota] -lib_ignore = ${lib_Tasmota.lib_ignore} +lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-minimal] build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -lib_ignore = ${lib_minimal.lib_ignore} +lib_extra_dirs = [env:tasmota-lite] build_flags = ${common.build_flags} -DFIRMWARE_LITE -lib_ignore = ${lib_lite.lib_ignore} +lib_extra_dirs = [env:tasmota-knx] build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_ignore = ${lib_knx.lib_ignore} +lib_extra_dirs = lib_basic [env:tasmota-sensors] build_flags = ${common.build_flags} -DFIRMWARE_SENSORS -lib_ignore = ${lib_sensors.lib_ignore} +lib_extra_dirs = lib_basic, lib_i2c, lib_rf, lib_div [env:tasmota-display] build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS -lib_ignore = ${lib_display.lib_ignore} +lib_extra_dirs = lib_basic, lib_display [env:tasmota-ir] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR -lib_ignore = ${lib_ir.lib_ignore} +lib_extra_dirs = lib_basic [env:tasmota-ircustom] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM -lib_ignore = ${lib_Tasmota.lib_ignore} +lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE -lib_ignore = ${lib_zbbridge.lib_ignore} +lib_extra_dirs = lib_basic, lib_ssl [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG -lib_ignore = ${lib_Tasmota.lib_ignore} +lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-BR] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_BR -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-CN] build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_CN -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-CZ] build_flags = ${common.build_flags} -DMY_LANGUAGE=cs_CZ -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-DE] build_flags = ${common.build_flags} -DMY_LANGUAGE=de_DE -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-ES] build_flags = ${common.build_flags} -DMY_LANGUAGE=es_ES -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-FR] build_flags = ${common.build_flags} -DMY_LANGUAGE=fr_FR -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-GR] build_flags = ${common.build_flags} -DMY_LANGUAGE=el_GR -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-HE] build_flags = ${common.build_flags} -DMY_LANGUAGE=he_HE -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-HU] build_flags = ${common.build_flags} -DMY_LANGUAGE=hu_HU -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-IT] build_flags = ${common.build_flags} -DMY_LANGUAGE=it_IT -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-KO] build_flags = ${common.build_flags} -DMY_LANGUAGE=ko_KO -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-NL] build_flags = ${common.build_flags} -DMY_LANGUAGE=nl_NL -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-PL] build_flags = ${common.build_flags} -DMY_LANGUAGE=pl_PL -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-PT] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_PT -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-RO] build_flags = ${common.build_flags} -DMY_LANGUAGE=ro_RO -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-RU] build_flags = ${common.build_flags} -DMY_LANGUAGE=ru_RU -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-SE] build_flags = ${common.build_flags} -DMY_LANGUAGE=sv_SE -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-SK] build_flags = ${common.build_flags} -DMY_LANGUAGE=sk_SK -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-TR] build_flags = ${common.build_flags} -DMY_LANGUAGE=tr_TR -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-TW] build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_TW -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-UK] build_flags = ${common.build_flags} -DMY_LANGUAGE=uk_UA -lib_ignore = ${lib_Tasmota.lib_ignore} [env:tasmota-VN] build_flags = ${common.build_flags} -DMY_LANGUAGE=vi_VN -lib_ignore = ${lib_Tasmota.lib_ignore} diff --git a/platformio_tasmota_env.ini.new b/platformio_tasmota_env.ini.new new file mode 100644 index 000000000..6cee57be9 --- /dev/null +++ b/platformio_tasmota_env.ini.new @@ -0,0 +1,144 @@ +[env] +platform = ${common.platform} +platform_packages = ${common.platform_packages} +framework = ${common.framework} +board = ${common.board} +board_build.ldscript = ${common.board_build.ldscript} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_flash = ${common.board_build.f_flash} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +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} +lib_extra_dirs = ${common.shared_libdeps_dir} + +[env:tasmota] +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-minimal] +build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL +lib_ignore = ${lib_minimal.lib_ignore} + +[env:tasmota-lite] +build_flags = ${common.build_flags} -DFIRMWARE_LITE +lib_ignore = ${lib_lite.lib_ignore} + +[env:tasmota-knx] +build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION +lib_ignore = ${lib_knx.lib_ignore} + +[env:tasmota-sensors] +build_flags = ${common.build_flags} -DFIRMWARE_SENSORS +lib_ignore = ${lib_sensors.lib_ignore} + +[env:tasmota-display] +build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS +lib_ignore = ${lib_display.lib_ignore} + +[env:tasmota-ir] +build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR +lib_ignore = ${lib_ir.lib_ignore} + +[env:tasmota-ircustom] +build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-zbbridge] +build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE +lib_ignore = ${lib_zbbridge.lib_ignore} + +[env:tasmota-BG] +build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-BR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_BR +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-CN] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_CN +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-CZ] +build_flags = ${common.build_flags} -DMY_LANGUAGE=cs_CZ +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-DE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=de_DE +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-ES] +build_flags = ${common.build_flags} -DMY_LANGUAGE=es_ES +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-FR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=fr_FR +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-GR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=el_GR +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-HE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=he_HE +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-HU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=hu_HU +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-IT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=it_IT +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-KO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ko_KO +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-NL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=nl_NL +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-PL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pl_PL +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-PT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_PT +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-RO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ro_RO +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-RU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ru_RU +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-SE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sv_SE +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-SK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sk_SK +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-TR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=tr_TR +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-TW] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_TW +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-UK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=uk_UA +lib_ignore = ${lib_Tasmota.lib_ignore} + +[env:tasmota-VN] +build_flags = ${common.build_flags} -DMY_LANGUAGE=vi_VN +lib_ignore = ${lib_Tasmota.lib_ignore} diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 2e8b98fbb..d5c4c3d57 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -13,64 +13,86 @@ upload_port = ${common32.upload_port} upload_resetmethod = ${common32.upload_resetmethod} upload_speed = ${common32.upload_speed} extra_scripts = ${common32.extra_scripts} -lib_extra_dirs = ${common32.lib_extra_dirs} -lib_ignore = ${common32.lib_ignore} build_unflags = ${common32.build_unflags} build_flags = ${common32.build_flags} +lib_extra_dirs = ${common32.lib_extra_dirs} +lib_ignore = + cc1101 + ESP32 Azure IoT Arduino + ESP32 Async UDP + ESP32 BLE Arduino + SimpleBLE + NetBIOS + ESP32 + Preferences + BluetoothSerial [env:tasmota32-webcam] extends = env:tasmota32 board = esp32cam board_build.f_cpu = 240000000L build_flags = ${common32.build_flags} -DFIRMWARE_WEBCAM +lib_extra_dirs = libesp32, lib_basic [env:tasmota32-minimal] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_MINIMAL +lib_extra_dirs = libesp32 [env:tasmota32-lite] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_LITE +lib_extra_dirs = libesp32 [env:tasmota32-knx] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_KNX_NO_EMULATION +lib_extra_dirs = libesp32, lib_basic [env:tasmota32-sensors] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_SENSORS +lib_extra_dirs = libesp32, lib_basic, lib_i2c, lib_rf, lib_div [env:tasmota32-display] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_DISPLAYS +lib_extra_dirs = libesp32, lib_basic, lib_display [env:tasmota32-ir] extends = env:tasmota32 build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR +lib_extra_dirs = libesp32, lib_basic [env:tasmota32-ircustom] extends = env:tasmota32 build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-BG] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=bg_BG +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-BR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pt_BR +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-CN] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=zh_CN +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-CZ] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=cs_CZ +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-DE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=de_DE +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-ES] extends = env:tasmota32 @@ -79,50 +101,62 @@ build_flags = ${common32.build_flags} -DMY_LANGUAGE=es_ES [env:tasmota32-FR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=fr_FR +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-GR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=el_GR +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-HE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=he_HE +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-HU] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=hu_HU +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-IT] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=it_IT +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-KO] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ko_KO +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-NL] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=nl_NL +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-PL] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pl_PL +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-PT] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pt_PT +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-RO] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ro_RO +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-RU] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ru_RU +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-SE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=sv_SE +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-SK] extends = env:tasmota32 @@ -131,15 +165,19 @@ build_flags = ${common32.build_flags} -DMY_LANGUAGE=sk_SK [env:tasmota32-TR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=tr_TR +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-TW] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=zh_TW +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-UK] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=uk_UA +lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-VN] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=vi_VN +lib_extra_dirs = ${common32.lib_extra_dirs} From fdbac5e58822f5fd91f4587c6b30eabf4aba1a4d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:11:28 +0100 Subject: [PATCH 09/38] Unishox move to lib --- .../Unishox-1.0-shadinger/generator/generator.c | 0 .../Unishox-1.0-shadinger/generator/remapping.xlsx | Bin .../Unishox-1.0-shadinger/library.properties | 0 .../Unishox-1.0-shadinger/python/unishox.py | 0 .../Unishox-1.0-shadinger/src/unishox.cpp | 0 .../Unishox-1.0-shadinger/src/unishox.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {lib_basic => lib}/Unishox-1.0-shadinger/generator/generator.c (100%) rename {lib_basic => lib}/Unishox-1.0-shadinger/generator/remapping.xlsx (100%) rename {lib_basic => lib}/Unishox-1.0-shadinger/library.properties (100%) rename {lib_basic => lib}/Unishox-1.0-shadinger/python/unishox.py (100%) rename {lib_basic => lib}/Unishox-1.0-shadinger/src/unishox.cpp (100%) rename {lib_basic => lib}/Unishox-1.0-shadinger/src/unishox.h (100%) diff --git a/lib_basic/Unishox-1.0-shadinger/generator/generator.c b/lib/Unishox-1.0-shadinger/generator/generator.c similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/generator/generator.c rename to lib/Unishox-1.0-shadinger/generator/generator.c diff --git a/lib_basic/Unishox-1.0-shadinger/generator/remapping.xlsx b/lib/Unishox-1.0-shadinger/generator/remapping.xlsx similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/generator/remapping.xlsx rename to lib/Unishox-1.0-shadinger/generator/remapping.xlsx diff --git a/lib_basic/Unishox-1.0-shadinger/library.properties b/lib/Unishox-1.0-shadinger/library.properties similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/library.properties rename to lib/Unishox-1.0-shadinger/library.properties diff --git a/lib_basic/Unishox-1.0-shadinger/python/unishox.py b/lib/Unishox-1.0-shadinger/python/unishox.py similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/python/unishox.py rename to lib/Unishox-1.0-shadinger/python/unishox.py diff --git a/lib_basic/Unishox-1.0-shadinger/src/unishox.cpp b/lib/Unishox-1.0-shadinger/src/unishox.cpp similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/src/unishox.cpp rename to lib/Unishox-1.0-shadinger/src/unishox.cpp diff --git a/lib_basic/Unishox-1.0-shadinger/src/unishox.h b/lib/Unishox-1.0-shadinger/src/unishox.h similarity index 100% rename from lib_basic/Unishox-1.0-shadinger/src/unishox.h rename to lib/Unishox-1.0-shadinger/src/unishox.h From 98fe750f9b30d22743c00377d13cee3bf10f0eef Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:45:00 +0100 Subject: [PATCH 10/38] Add libs explanation --- platformio.ini | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/platformio.ini b/platformio.ini index cfa48946e..ab505478a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -84,13 +84,26 @@ upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} lib_ldf_mode = chain+ shared_libdeps_dir = lib + +; *** Library disable / enable for variant Tasmota. Disable reduces compile time +; *** !!! Disabling needed libs will generate compile errors !!! +; *** The resulting firmware will NOT be different if you leave all libs enabled +; *** Disabling by putting a ";" in front of the lib name +; *** If you dont know what it is all about, do not change lib_extra_dirs = +; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! lib_basic +; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled lib_i2c +; *** Displays. Disable if you dont have any Display activated lib_display +; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated lib_ssl +; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable lib_audio +; *** RF 433 stuff (not RF Bridge). Recommended to disable lib_rf +; *** Mostly not used functions. Recommended to disable lib_div [scripts_defaults] From 0c93bdb5e83e4019e2877daec641d16ff9cb5810 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:47:32 +0100 Subject: [PATCH 11/38] UDP listener to lib --- {lib_basic => lib}/UdpListener/library.properties | 0 {lib_basic => lib}/UdpListener/src/UdpListener.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {lib_basic => lib}/UdpListener/library.properties (100%) rename {lib_basic => lib}/UdpListener/src/UdpListener.h (100%) diff --git a/lib_basic/UdpListener/library.properties b/lib/UdpListener/library.properties similarity index 100% rename from lib_basic/UdpListener/library.properties rename to lib/UdpListener/library.properties diff --git a/lib_basic/UdpListener/src/UdpListener.h b/lib/UdpListener/src/UdpListener.h similarity index 100% rename from lib_basic/UdpListener/src/UdpListener.h rename to lib/UdpListener/src/UdpListener.h From 38021d3c92a3084dde5dc2d3b418f2c55de64881 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:55:38 +0100 Subject: [PATCH 12/38] add ESP32 lib infos --- platformio_tasmota32.ini | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 2adcce410..310124a30 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -78,12 +78,26 @@ build_flags = ${esp_defaults.build_flags} lib_ldf_mode = chain+ shared_libdeps_dir = lib -lib_extra_dirs = - libesp32 - lib_basic - lib_i2c - lib_display - lib_ssl - lib_audio - lib_rf - lib_div +; *** Library disable / enable for variant Tasmota. Disable reduces compile time +; *** !!! Disabling needed libs will generate compile errors !!! +; *** The resulting firmware will NOT be different if you leave all libs enabled +; *** Disabling by putting a ";" in front of the lib name +; *** If you dont know what it is all about, do not change +lib_extra_dirs = +; *** ESP32 lib. ALWAYS needed for ESP32 !!! + libesp32 +; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! + lib_basic +; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled + lib_i2c +; *** Displays. Disable if you dont have any Display activated + lib_display +; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated + lib_ssl +; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable + lib_audio +; *** RF 433 stuff (not RF Bridge). Recommended to disable + lib_rf +; *** Mostly not used functions. Recommended to disable + lib_div + From 580b205dfe3d2c2ad12f63a7091204db9a3d0d4e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 15:00:11 +0100 Subject: [PATCH 13/38] 160Mhz for zbbridge --- platformio_tasmota_env.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index c88ad75e2..c38943b93 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -64,6 +64,7 @@ lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE +board_build.f_cpu = 160000000L lib_extra_dirs = lib_basic, lib_ssl [env:tasmota-BG] From a82ccdc2cd5fb328273016b0ae477b8aeada3231 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 15:19:38 +0100 Subject: [PATCH 14/38] merge conflicts... --- .../AT24C256_512/Eeprom24C128_256.cpp | 0 .../AT24C256_512/Eeprom24C128_256.h | 0 .../AT24C256_512/Eeprom24C512.cpp | 0 .../AT24C256_512/Eeprom24C512.h | 0 .../AT24C256_512/library.properties | 0 lib_div/AT24C256/Eeprom24C128_256.cpp | 334 ------------------ lib_div/AT24C256/Eeprom24C128_256.h | 212 ----------- lib_div/AT24C256/library.properties | 9 - 8 files changed, 555 deletions(-) rename {lib => lib_basic}/AT24C256_512/Eeprom24C128_256.cpp (100%) rename {lib => lib_basic}/AT24C256_512/Eeprom24C128_256.h (100%) rename {lib => lib_basic}/AT24C256_512/Eeprom24C512.cpp (100%) rename {lib => lib_basic}/AT24C256_512/Eeprom24C512.h (100%) rename {lib => lib_basic}/AT24C256_512/library.properties (100%) delete mode 100644 lib_div/AT24C256/Eeprom24C128_256.cpp delete mode 100644 lib_div/AT24C256/Eeprom24C128_256.h delete mode 100644 lib_div/AT24C256/library.properties diff --git a/lib/AT24C256_512/Eeprom24C128_256.cpp b/lib_basic/AT24C256_512/Eeprom24C128_256.cpp similarity index 100% rename from lib/AT24C256_512/Eeprom24C128_256.cpp rename to lib_basic/AT24C256_512/Eeprom24C128_256.cpp diff --git a/lib/AT24C256_512/Eeprom24C128_256.h b/lib_basic/AT24C256_512/Eeprom24C128_256.h similarity index 100% rename from lib/AT24C256_512/Eeprom24C128_256.h rename to lib_basic/AT24C256_512/Eeprom24C128_256.h diff --git a/lib/AT24C256_512/Eeprom24C512.cpp b/lib_basic/AT24C256_512/Eeprom24C512.cpp similarity index 100% rename from lib/AT24C256_512/Eeprom24C512.cpp rename to lib_basic/AT24C256_512/Eeprom24C512.cpp diff --git a/lib/AT24C256_512/Eeprom24C512.h b/lib_basic/AT24C256_512/Eeprom24C512.h similarity index 100% rename from lib/AT24C256_512/Eeprom24C512.h rename to lib_basic/AT24C256_512/Eeprom24C512.h diff --git a/lib/AT24C256_512/library.properties b/lib_basic/AT24C256_512/library.properties similarity index 100% rename from lib/AT24C256_512/library.properties rename to lib_basic/AT24C256_512/library.properties diff --git a/lib_div/AT24C256/Eeprom24C128_256.cpp b/lib_div/AT24C256/Eeprom24C128_256.cpp deleted file mode 100644 index f7b66afba..000000000 --- a/lib_div/AT24C256/Eeprom24C128_256.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/**************************************************************************//** - * \brief EEPROM 24C128 / 24C256 library for Arduino - * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com - * \version 1.0 - * \date 20120203 - * - * This file is part of the EEPROM 24C128 / 24C256 library for Arduino. - * - * 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 3 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 program. If not, see http://www.gnu.org/licenses/ - ******************************************************************************/ - -/**************************************************************************//** - * \file Eeprom24C128_256.cpp - ******************************************************************************/ - -/****************************************************************************** - * Header file inclusions. - ******************************************************************************/ - -#include -#include - -#include - -/****************************************************************************** - * Private macro definitions. - ******************************************************************************/ - -/**************************************************************************//** - * \def EEPROM__PAGE_SIZE - * \brief Size of a page in EEPROM memory. - * This size is given by EEPROM memory datasheet. - ******************************************************************************/ -#define EEPROM__PAGE_SIZE 64 - -/**************************************************************************//** - * \def EEPROM__RD_BUFFER_SIZE - * \brief Size of input TWI buffer. - * This size is equal to BUFFER_LENGTH defined in Wire library (32 bytes). - ******************************************************************************/ - #define xBUFFER_LENGTH 24 -#define EEPROM__RD_BUFFER_SIZE xBUFFER_LENGTH - -/**************************************************************************//** - * \def EEPROM__WR_BUFFER_SIZE - * \brief Size of output TWI buffer. - * This size is equal to BUFFER_LENGTH - 2 bytes reserved for address. - ******************************************************************************/ -#define EEPROM__WR_BUFFER_SIZE (xBUFFER_LENGTH - 2) - -/****************************************************************************** - * Public method definitions. - ******************************************************************************/ - -/**************************************************************************//** - * \fn Eeprom24C128_256::Eeprom24C128_256(byte deviceAddress) - * - * \brief Constructor. - * - * \param deviceAddress EEPROM address on TWI bus. - ******************************************************************************/ -Eeprom24C128_256::Eeprom24C128_256 -( - byte deviceAddress -){ - m_deviceAddress = deviceAddress; -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::initialize() - * - * \brief Initialize library and TWI bus. - * - * If several devices are connected to TWI bus, this method mustn't be - * called. TWI bus must be initialized out of this library using - * Wire.begin() method. - ******************************************************************************/ -void -Eeprom24C128_256::initialize() -{ - Wire.begin(); -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::writeByte( - * word address, - * byte data) - * - * \brief Write a byte in EEPROM memory. - * - * \remarks A delay of 10 ms is required after write cycle. - * - * \param address Address. - * \param data Byte to write. - ******************************************************************************/ -void -Eeprom24C128_256::writeByte -( - word address, - byte data -){ - Wire.beginTransmission(m_deviceAddress); - Wire.write(address >> 8); - Wire.write(address & 0xFF); - Wire.write(data); - Wire.endTransmission(); -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::writeBytes( - * word address, - * word length, - * byte* p_data) - * - * \brief Write bytes in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes to write. - * \param[in] p_data Bytes to write. - ******************************************************************************/ -void -Eeprom24C128_256::writeBytes -( - word address, - word length, - byte* p_data -){ - // Write first page if not aligned. - byte notAlignedLength = 0; - byte pageOffset = address % EEPROM__PAGE_SIZE; - if (pageOffset > 0) - { - notAlignedLength = EEPROM__PAGE_SIZE - pageOffset; - if (length < notAlignedLength) - { - notAlignedLength = length; - } - writePage(address, notAlignedLength, p_data); - length -= notAlignedLength; - } - - if (length > 0) - { - address += notAlignedLength; - p_data += notAlignedLength; - - // Write complete and aligned pages. - word pageCount = length / EEPROM__PAGE_SIZE; - for (word i = 0; i < pageCount; i++) - { - writePage(address, EEPROM__PAGE_SIZE, p_data); - address += EEPROM__PAGE_SIZE; - p_data += EEPROM__PAGE_SIZE; - length -= EEPROM__PAGE_SIZE; - } - - if (length > 0) - { - // Write remaining uncomplete page. - writePage(address, length, p_data); - } - } -} - -/**************************************************************************//** - * \fn byte Eeprom24C128_256::readByte(word address) - * - * \brief Read a byte in EEPROM memory. - * - * \param address Address. - * - * \return Read byte. - ******************************************************************************/ -byte -Eeprom24C128_256::readByte -( - word address -){ - Wire.beginTransmission(m_deviceAddress); - Wire.write(address >> 8); - Wire.write(address & 0xFF); - Wire.endTransmission(); - Wire.requestFrom(m_deviceAddress, (byte)1); - byte data = 0; - if (Wire.available()) - { - data = Wire.read(); - } - return data; -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::readBytes( - * word address, - * word length, - * byte* p_data) - * - * \brief Read bytes in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes to read. - * \patam[in] p_data Byte array to fill with read bytes. - ******************************************************************************/ -void -Eeprom24C128_256::readBytes -( - word address, - word length, - byte* p_data -){ - byte bufferCount = length / EEPROM__RD_BUFFER_SIZE; - for (byte i = 0; i < bufferCount; i++) - { - word offset = i * EEPROM__RD_BUFFER_SIZE; - readBuffer(address + offset, EEPROM__RD_BUFFER_SIZE, p_data + offset); - } - - byte remainingBytes = length % EEPROM__RD_BUFFER_SIZE; - word offset = length - remainingBytes; - readBuffer(address + offset, remainingBytes, p_data + offset); -} - -/****************************************************************************** - * Private method definitions. - ******************************************************************************/ - -/**************************************************************************//** - * \fn void Eeprom24C128_256::writePage( - * word address, - * byte length, - * byte* p_data) - * - * \brief Write page in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes (EEPROM__PAGE_SIZE bytes max). - * \param[in] p_data Data. - ******************************************************************************/ -void -Eeprom24C128_256::writePage -( - word address, - byte length, - byte* p_data -){ - // Write complete buffers. - byte bufferCount = length / EEPROM__WR_BUFFER_SIZE; - for (byte i = 0; i < bufferCount; i++) - { - byte offset = i * EEPROM__WR_BUFFER_SIZE; - writeBuffer(address + offset, EEPROM__WR_BUFFER_SIZE, p_data + offset); - } - - // Write remaining bytes. - byte remainingBytes = length % EEPROM__WR_BUFFER_SIZE; - byte offset = length - remainingBytes; - writeBuffer(address + offset, remainingBytes, p_data + offset); -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::writeBuffer( - * word address, - * byte length, - * byte* p_data) - * - * \brief Write bytes into memory. - * - * \param address Start address. - * \param length Number of bytes (EEPROM__WR_BUFFER_SIZE bytes max). - * \param[in] p_data Data. - ******************************************************************************/ -void -Eeprom24C128_256::writeBuffer -( - word address, - byte length, - byte* p_data -){ - Wire.beginTransmission(m_deviceAddress); - Wire.write(address >> 8); - Wire.write(address & 0xFF); - for (byte i = 0; i < length; i++) - { - Wire.write(p_data[i]); - } - Wire.endTransmission(); - - // Write cycle time (tWR). See EEPROM memory datasheet for more details. - delay(10); -} - -/**************************************************************************//** - * \fn void Eeprom24C128_256::readBuffer( - * word address, - * byte length, - * byte* p_data) - * - * \brief Read bytes in memory. - * - * \param address Start address. - * \param length Number of bytes (EEPROM__RD_BUFFER_SIZE bytes max). - * \param[in] p_data Buffer to fill with read bytes. - ******************************************************************************/ -void -Eeprom24C128_256::readBuffer -( - word address, - byte length, - byte* p_data -){ - Wire.beginTransmission(m_deviceAddress); - Wire.write(address >> 8); - Wire.write(address & 0xFF); - Wire.endTransmission(); - Wire.requestFrom(m_deviceAddress, length); - for (byte i = 0; i < length; i++) - { - if (Wire.available()) - { - p_data[i] = Wire.read(); - } - } -} diff --git a/lib_div/AT24C256/Eeprom24C128_256.h b/lib_div/AT24C256/Eeprom24C128_256.h deleted file mode 100644 index 865c76226..000000000 --- a/lib_div/AT24C256/Eeprom24C128_256.h +++ /dev/null @@ -1,212 +0,0 @@ -/**************************************************************************//** - * \brief EEPROM 24C128 / 24C256 library for Arduino - * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com - * \version 1.0 - * \date 20120203 - * - * This file is part of the EEPROM 24C128 / 24C256 library for Arduino. - * - * 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 3 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 program. If not, see http://www.gnu.org/licenses/ - ******************************************************************************/ - -/**************************************************************************//** - * \headerfile Eeprom24C128_256.h - ******************************************************************************/ - -#ifndef Eeprom24C128_256_h -#define Eeprom24C128_256_h - -/****************************************************************************** - * Header file inclusion. - ******************************************************************************/ - -#include - -/**************************************************************************//** - * \class Eeprom24C128_256 - * - * \brief EEPROM 24C128 / 24C256 memory driver. - * - * This driver is mainly designed for 24C128 and 24C256 EEPROM memories. It's - * also suitable for 24C512 memories. - ******************************************************************************/ -class Eeprom24C128_256 -{ - public: - - /******************************************************************//** - * \fn Eeprom24C128_256(byte deviceAddress) - * - * \brief Constructor. - * - * \param deviceAddress EEPROM address on TWI bus. - **********************************************************************/ - Eeprom24C128_256 - ( - byte deviceAddress - ); - - /******************************************************************//** - * \fn void initialize() - * - * \brief Initialize library abnd TWI bus. - * - * If several devices are connected to TWI bus, this method mustn't be - * called. TWI bus must be initialized out of this library using - * Wire.begin() method. - **********************************************************************/ - void - initialize(); - - /******************************************************************//** - * \fn void writeByte( - * word address, - * byte data) - * - * \brief Write a byte in EEPROM memory. - * - * \remarks A delay of 10 ms is required after write cycle. - * - * \param address Address. - * \param data Byte to write. - **********************************************************************/ - void - writeByte - ( - word address, - byte data - ); - - /******************************************************************//** - * \fn void writeBytes( - * word address, - * word length, - * byte* p_data) - * - * \brief Write bytes in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes to write. - * \param[in] p_data Bytes to write. - **********************************************************************/ - void - writeBytes - ( - word address, - word length, - byte* p_data - ); - - /******************************************************************//** - * \fn byte readByte(word address) - * - * \brief Read a byte in EEPROM memory. - * - * \param address Address. - * - * \return Read byte. - **********************************************************************/ - byte - readByte - ( - word address - ); - - /******************************************************************//** - * \fn void readBytes( - * word address, - * word length, - * byte* p_data) - * - * \brief Read bytes in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes to read. - * \patam[in] p_data Byte array to fill with read bytes. - **********************************************************************/ - void - readBytes - ( - word address, - word length, - byte* p_buffer - ); - - private: - - byte m_deviceAddress; - - /******************************************************************//** - * \fn void writePage( - * word address, - * byte length, - * byte* p_data) - * - * \brief Write page in EEPROM memory. - * - * \param address Start address. - * \param length Number of bytes (64 bytes max). - * \param[in] p_data Data. - **********************************************************************/ - void - writePage - ( - word address, - byte length, - byte* p_data - ); - - /******************************************************************//** - * \fn void writeBuffer( - * word address, - * byte length, - * byte* p_data) - * - * \brief Write bytes into memory. - * - * \param address Start address. - * \param length Number of bytes (30 bytes max). - * \param[in] p_date Data. - **********************************************************************/ - void - writeBuffer - ( - word address, - byte length, - byte* p_data - ); - - /******************************************************************//** - * \fn void readBuffer( - * word address, - * byte length, - * byte* p_data) - * - * \brief Read bytes in memory. - * - * \param address Start address. - * \param length Number of bytes to read (32 bytes max). - * \param[in] p_data Buffer to fill with read bytes. - **********************************************************************/ - void - readBuffer - ( - word address, - byte length, - byte* p_data - ); -}; - -#endif // Eeprom24C128_256_h - diff --git a/lib_div/AT24C256/library.properties b/lib_div/AT24C256/library.properties deleted file mode 100644 index 648e89096..000000000 --- a/lib_div/AT24C256/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=EEPROM 24C128 -version= -author=Julien Le Sech -maintainer=Julien Le Sech - www.idreammicro.com -sentence=EEPROM 24C128 / 24C256 memory driver. -paragraph=EEPROM 24C128 / 24C256 memory driver. -category= -url= -architectures=* From ca07a0f7af0db711ea79ae4974fa933972da70d4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:27:34 +0100 Subject: [PATCH 15/38] move lib disable in override --- platformio.ini | 14 -------------- platformio_override_sample.ini | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/platformio.ini b/platformio.ini index ab505478a..a30214f4c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -59,7 +59,6 @@ build_cache_dir = .cache extra_configs = platformio_tasmota32.ini platformio_tasmota_env.ini platformio_tasmota_env32.ini - ;platformio_lib.ini platformio_override.ini default_envs = ${build_envs.default_envs} @@ -84,26 +83,13 @@ upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} lib_ldf_mode = chain+ shared_libdeps_dir = lib - -; *** Library disable / enable for variant Tasmota. Disable reduces compile time -; *** !!! Disabling needed libs will generate compile errors !!! -; *** The resulting firmware will NOT be different if you leave all libs enabled -; *** Disabling by putting a ";" in front of the lib name -; *** If you dont know what it is all about, do not change lib_extra_dirs = -; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! lib_basic -; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled lib_i2c -; *** Displays. Disable if you dont have any Display activated lib_display -; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated lib_ssl -; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable lib_audio -; *** RF 433 stuff (not RF Bridge). Recommended to disable lib_rf -; *** Mostly not used functions. Recommended to disable lib_div [scripts_defaults] diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 9afe61b04..9bd30b21f 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -72,6 +72,31 @@ extra_scripts = ${scripts_defaults.extra_scripts} ; pio/strip-floats.py ; pio/http-uploader.py +lib_ldf_mode = chain+ +shared_libdeps_dir = lib + +; *** Library disable / enable for variant Tasmota. Disable reduces compile time +; *** !!! Disabling needed libs will generate compile errors !!! +; *** The resulting firmware will NOT be different if you leave all libs enabled +; *** Disabling by putting a ";" in front of the lib name +; *** If you dont know what it is all about, do not change +lib_extra_dirs = +; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! + lib_basic +; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled + lib_i2c +; *** Displays. Disable if you dont have any Display activated + lib_display +; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated + lib_ssl +; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable +; lib_audio +; *** RF 433 stuff (not RF Bridge). Recommended to disable + lib_rf +; *** Mostly not used functions. Recommended to disable +; lib_div + + [core] ; Activate only (one set) if you want to override the standard core defined in platformio.ini !!! @@ -156,7 +181,6 @@ build_flags = ${esp82xx_defaults.build_flags} ; -fexceptions ; -lstdc++-exc - [core32] ; Activate Stage Core32 by removing ";" in next line, if you want to override the standard core32 ;platform_packages = ${core32_stage.platform_packages} From 220e1a6041faf8ccb3cacafabd72c1cee40618d4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:40:27 +0100 Subject: [PATCH 16/38] Deleted left over --- platformio_lib.ini | 284 --------------------------------------------- 1 file changed, 284 deletions(-) delete mode 100644 platformio_lib.ini diff --git a/platformio_lib.ini b/platformio_lib.ini deleted file mode 100644 index 7c4ed544b..000000000 --- a/platformio_lib.ini +++ /dev/null @@ -1,284 +0,0 @@ -; ******************************************************** -; *** PlatformIO Configuration for Library DISABLING *** -; ******************************************************** -; -; -; *********************************************************************** -; *** Config Setup for disabling for the different Tasmota variants *** -; *********************************************************************** - -[lib_Tasmota] -; Disable not needed libs to build TASMOTA, IR-CUSTOM and all language variants -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_minimal] -; Disable not needed libs to build TASMOTA-minimal -lib_ignore = - ${lib_all_EP8266.lib_ignore} - -[lib_lite] -; Disable not needed libs to build TASMOTA-lite -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_knx] -; Disable not needed libs to build TASMOTA-KNX -lib_ignore = - ;${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_sensors] -; Disable not needed libs to build TASMOTA-sensors -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} -; ${lib_i2c_sensor.lib_ignore} -; ${lib_sensor.lib_ignore} -; ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_display] -; Disable not needed libs to build TASMOTA-display -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} -; ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_ir] -; Disable not needed libs to build TASMOTA-IR -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - - -[lib_zbbridge] -; Disable not needed libs to build TASMOTA-ZbBridge -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - - - - -; ****************************** -; *** Library groups setup *** -; ****************************** - -[lib_EP8266_default] -lib_ignore = - Servo(esp8266) - ESP8266AVRISP - ESP8266LLMNR - ESP8266NetBIOS - ESP8266SSDP - SP8266WiFiMesh - Ethernet(esp8266) - GDBStub - TFT_Touch_Shield_V2 - ESP8266HTTPUpdateServer - ESP8266WiFiMesh - EspSoftwareSerial - SPISlave - Hash - -[lib_EP8266] -lib_ignore = - ${lib_EP8266_default.lib_ignore} - LittleFS(esp8266) - -[lib_all_EP8266] -lib_ignore = - ${lib_EP8266.lib_ignore} - ${lib_knx.lib_ignore} - ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_custom] -lib_ignore = - NTP Library - base64 - Unishox Compressor Decompressor highly customized and optimized for ESP8266 and Tasmota - UdpListener - C2Programmer - TasmotaSerial - TasmotaModbus - -[lib_ESP_knx] -lib_ignore = - ;ESP KNX IP Library - -[lib_SSL] -lib_ignore = - BearSSL - -[lib_ESP_display] -lib_ignore = - LinkedList - Adafruit GFX Library - Arduino ST7789 Library - Adafruit ILI9341 - ILI9488 - RA8876 - Adafruit LED Backpack Library - Waveshare esp 2.9 inch e-paper display driver - LiquidCrystal_I2C - Adafruit SH1106-gemu-1.0 - Adafruit SSD1306 - SSD3115 - -[lib_i2c_sensor] -lib_ignore = - LinkedList - Adafruit BusIO - I2Cdevlib-Core - Adafruit CCS811 Library - Adafruit MAX31865 library - Adafruit MCP9808 Library - Adafruit SGP30 Sensor - Adafruit TSL2591 - Joba Tsl2561 Library - Joba_Tsl2561 - Adafruit VEML7700 Library - MPU6050 I2C - LinkedList - LOLIN_HP303B - Grove - Multichannel Gas Sensor - Mutichannel_Gas_Sensor - OneWire - VL53L0X - VL53L1X - MLX90640 - FrogmoreScd30 - BME680 - FT5206_Library - HPMA115S0 Arduino Library - -[lib_sensor] -lib_ignore = - NewPing - -[lib_rf] -lib_ignore = - rc-switch - RF24 - KeeloqLib - -[lib_ESP_ir] -lib_ignore = - IRremoteESP8266 - -[lib_light] -lib_ignore = - NeoPixelBus - -[lib_audio] -lib_ignore = - ESP8266Audio - ESP8266SAM - -[lib_serial] -lib_ignore = - LibTeleinfo - -[lib_other] -lib_ignore = - OpenTherm Library - A4988_Stepper - EEPROM 24C128 - -[lib_SPI] -lib_ignore = - cc1101 - EEPROM 24C128 From 949faffd0d097072908132fc982314a6393b7d05 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:42:07 +0100 Subject: [PATCH 17/38] Delete platformio_lib.ini --- platformio_lib.ini | 284 --------------------------------------------- 1 file changed, 284 deletions(-) delete mode 100644 platformio_lib.ini diff --git a/platformio_lib.ini b/platformio_lib.ini deleted file mode 100644 index 7c4ed544b..000000000 --- a/platformio_lib.ini +++ /dev/null @@ -1,284 +0,0 @@ -; ******************************************************** -; *** PlatformIO Configuration for Library DISABLING *** -; ******************************************************** -; -; -; *********************************************************************** -; *** Config Setup for disabling for the different Tasmota variants *** -; *********************************************************************** - -[lib_Tasmota] -; Disable not needed libs to build TASMOTA, IR-CUSTOM and all language variants -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_minimal] -; Disable not needed libs to build TASMOTA-minimal -lib_ignore = - ${lib_all_EP8266.lib_ignore} - -[lib_lite] -; Disable not needed libs to build TASMOTA-lite -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_knx] -; Disable not needed libs to build TASMOTA-KNX -lib_ignore = - ;${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_sensors] -; Disable not needed libs to build TASMOTA-sensors -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} -; ${lib_i2c_sensor.lib_ignore} -; ${lib_sensor.lib_ignore} -; ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_display] -; Disable not needed libs to build TASMOTA-display -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} -; ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} -; ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_ir] -; Disable not needed libs to build TASMOTA-IR -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} -; ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - - -[lib_zbbridge] -; Disable not needed libs to build TASMOTA-ZbBridge -lib_ignore = - ${lib_ESP_knx.lib_ignore} - ${lib_EP8266.lib_ignore} -; ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - - - - -; ****************************** -; *** Library groups setup *** -; ****************************** - -[lib_EP8266_default] -lib_ignore = - Servo(esp8266) - ESP8266AVRISP - ESP8266LLMNR - ESP8266NetBIOS - ESP8266SSDP - SP8266WiFiMesh - Ethernet(esp8266) - GDBStub - TFT_Touch_Shield_V2 - ESP8266HTTPUpdateServer - ESP8266WiFiMesh - EspSoftwareSerial - SPISlave - Hash - -[lib_EP8266] -lib_ignore = - ${lib_EP8266_default.lib_ignore} - LittleFS(esp8266) - -[lib_all_EP8266] -lib_ignore = - ${lib_EP8266.lib_ignore} - ${lib_knx.lib_ignore} - ${lib_custom.lib_ignore} - ${lib_SSL.lib_ignore} - ${lib_ESP_display.lib_ignore} - ${lib_i2c_sensor.lib_ignore} - ${lib_sensor.lib_ignore} - ${lib_rf.lib_ignore} - ${lib_ESP_ir.lib_ignore} - ${lib_light.lib_ignore} - ${lib_audio.lib_ignore} - ${lib_serial.lib_ignore} - ${lib_other.lib_ignore} - ${lib_SPI.lib_ignore} - -[lib_custom] -lib_ignore = - NTP Library - base64 - Unishox Compressor Decompressor highly customized and optimized for ESP8266 and Tasmota - UdpListener - C2Programmer - TasmotaSerial - TasmotaModbus - -[lib_ESP_knx] -lib_ignore = - ;ESP KNX IP Library - -[lib_SSL] -lib_ignore = - BearSSL - -[lib_ESP_display] -lib_ignore = - LinkedList - Adafruit GFX Library - Arduino ST7789 Library - Adafruit ILI9341 - ILI9488 - RA8876 - Adafruit LED Backpack Library - Waveshare esp 2.9 inch e-paper display driver - LiquidCrystal_I2C - Adafruit SH1106-gemu-1.0 - Adafruit SSD1306 - SSD3115 - -[lib_i2c_sensor] -lib_ignore = - LinkedList - Adafruit BusIO - I2Cdevlib-Core - Adafruit CCS811 Library - Adafruit MAX31865 library - Adafruit MCP9808 Library - Adafruit SGP30 Sensor - Adafruit TSL2591 - Joba Tsl2561 Library - Joba_Tsl2561 - Adafruit VEML7700 Library - MPU6050 I2C - LinkedList - LOLIN_HP303B - Grove - Multichannel Gas Sensor - Mutichannel_Gas_Sensor - OneWire - VL53L0X - VL53L1X - MLX90640 - FrogmoreScd30 - BME680 - FT5206_Library - HPMA115S0 Arduino Library - -[lib_sensor] -lib_ignore = - NewPing - -[lib_rf] -lib_ignore = - rc-switch - RF24 - KeeloqLib - -[lib_ESP_ir] -lib_ignore = - IRremoteESP8266 - -[lib_light] -lib_ignore = - NeoPixelBus - -[lib_audio] -lib_ignore = - ESP8266Audio - ESP8266SAM - -[lib_serial] -lib_ignore = - LibTeleinfo - -[lib_other] -lib_ignore = - OpenTherm Library - A4988_Stepper - EEPROM 24C128 - -[lib_SPI] -lib_ignore = - cc1101 - EEPROM 24C128 From 8d71ade035a0b344e4d316af0f13fec0cfd9a671 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 25 Oct 2020 17:38:06 +0100 Subject: [PATCH 18/38] Fixed rule Break not working as expected Fixed rule Break not working as expected when ONCE is enabled (#9245) --- CHANGELOG.md | 3 +++ RELEASENOTES.md | 7 ++++--- tasmota/xdrv_10_rules.ino | 13 +++++++------ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a8ef98d9..35a1c370f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to this project will be documented in this file. ### Added - TLS in binary tasmota-zbbridge (#9620) +### Fixed +- Rule Break not working as expected when ONCE is enabled (#9245) + ## [9.0.0.2] - 20201025 ### Added - Support for Vietnamese language translations by Tâm.NT diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 58c6117f2..3f9f212ba 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -19,13 +19,13 @@ See [migration path](https://tasmota.github.io/docs/Upgrading#migration-path) fo --- Major change in internal GPIO function representation --- -8. Migrate to **Tasmota 9.x** +8. Migrate to **Tasmota 9.1** While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v9.1.0 Imogen** the internal GPIO function representation has changed in such a way that fallback is only possible to the latest GPIO configuration before installing **v9.1.0**. ## Supported Core versions -This release will be supported from ESP8266/Arduino library Core version **2.7.4.3** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. +This release will be supported from ESP8266/Arduino library Core version **2.7.4.5** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. Support of Core versions before 2.7.1 has been removed. @@ -39,7 +39,7 @@ For initial configuration this release supports Webserver based **WifiManager** ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.4.3**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.4.5**. - **tasmota.bin** = The Tasmota version with most drivers. **RECOMMENDED RELEASE BINARY** - **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages. @@ -112,6 +112,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Scripter memory alignment (#9608) - Zigbee battery percentage (#9607) - HassAnyKey anomaly (#9601) +- Rule Break not working as expected when ONCE is enabled (#9245) ### Removed - Support for direct upgrade from Tasmota versions before v7.0 diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index e5a041674..35b7525dc 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -401,7 +401,7 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) { /*******************************************************************************************/ -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all_rules) { // event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} // event = {"System":{"Boot":1}} @@ -575,7 +575,9 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } } else match = true; -//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 1 %d"), match); + if (stop_all_rules) { match = false; } + +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 1 %d, Triggers %08X, TriggerCount %d"), match, Rules.triggers[rule_set], Rules.trigger_count[rule_set]); if (bitRead(Settings.rule_once, rule_set)) { if (match) { // Only allow match state changes @@ -589,7 +591,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } } -//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 2 %d"), match); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 2 %d, Triggers %08X, TriggerCount %d"), match, Rules.triggers[rule_set], Rules.trigger_count[rule_set]); return match; } @@ -696,8 +698,8 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) //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)) { - if (plen == plen2) { stop_all_rules = true; } // If BREAK was used on a triggered rule, Stop execution of this rule set + if (RulesRuleMatch(rule_set, event, event_trigger, stop_all_rules)) { + if (plen == plen2) { stop_all_rules = true; } // If BREAK was used on a triggered rule, Stop execution of this rule set commands.trim(); String ucommand = commands; ucommand.toUpperCase(); @@ -754,7 +756,6 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) #endif ExecuteCommand(command, SRC_RULE); serviced = true; - if (stop_all_rules) { return serviced; } // If BREAK was used, Stop execution of this rule set } plen += 6; Rules.trigger_count[rule_set]++; From 3b71ba197dadcd74c9d115885bb3927cca9040ad Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sun, 25 Oct 2020 16:01:15 -0300 Subject: [PATCH 19/38] Fix fulltopic order for HA integration --- tasmota/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index bb9e5caf9..85483c62c 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -322,7 +322,7 @@ void NewHAssDiscovery(void) if (!Settings.flag.hass_discovery) { // HassDiscoveryRelays(relays) Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME), stemp2, my_hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), - my_version, mqtt_topic, MQTT_FULLTOPIC, SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, + my_version, mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag3.shutter_mode, Settings.flag4.alexa_ct_range, light_controller.isCTRGBLinked(), Light.subtype); } From 7fc02d5ded6439edc70b5c4a4c076cc195450673 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 25 Oct 2020 22:41:29 +0100 Subject: [PATCH 20/38] Optimize compile time for zbbridge --- {lib_basic => lib}/AT24C256_512/Eeprom24C128_256.cpp | 0 {lib_basic => lib}/AT24C256_512/Eeprom24C128_256.h | 0 {lib_basic => lib}/AT24C256_512/Eeprom24C512.cpp | 0 {lib_basic => lib}/AT24C256_512/Eeprom24C512.h | 0 {lib_basic => lib}/AT24C256_512/library.properties | 0 platformio_tasmota_env.ini | 2 +- 6 files changed, 1 insertion(+), 1 deletion(-) rename {lib_basic => lib}/AT24C256_512/Eeprom24C128_256.cpp (100%) rename {lib_basic => lib}/AT24C256_512/Eeprom24C128_256.h (100%) rename {lib_basic => lib}/AT24C256_512/Eeprom24C512.cpp (100%) rename {lib_basic => lib}/AT24C256_512/Eeprom24C512.h (100%) rename {lib_basic => lib}/AT24C256_512/library.properties (100%) diff --git a/lib_basic/AT24C256_512/Eeprom24C128_256.cpp b/lib/AT24C256_512/Eeprom24C128_256.cpp similarity index 100% rename from lib_basic/AT24C256_512/Eeprom24C128_256.cpp rename to lib/AT24C256_512/Eeprom24C128_256.cpp diff --git a/lib_basic/AT24C256_512/Eeprom24C128_256.h b/lib/AT24C256_512/Eeprom24C128_256.h similarity index 100% rename from lib_basic/AT24C256_512/Eeprom24C128_256.h rename to lib/AT24C256_512/Eeprom24C128_256.h diff --git a/lib_basic/AT24C256_512/Eeprom24C512.cpp b/lib/AT24C256_512/Eeprom24C512.cpp similarity index 100% rename from lib_basic/AT24C256_512/Eeprom24C512.cpp rename to lib/AT24C256_512/Eeprom24C512.cpp diff --git a/lib_basic/AT24C256_512/Eeprom24C512.h b/lib/AT24C256_512/Eeprom24C512.h similarity index 100% rename from lib_basic/AT24C256_512/Eeprom24C512.h rename to lib/AT24C256_512/Eeprom24C512.h diff --git a/lib_basic/AT24C256_512/library.properties b/lib/AT24C256_512/library.properties similarity index 100% rename from lib_basic/AT24C256_512/library.properties rename to lib/AT24C256_512/library.properties diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index c38943b93..e536f7c46 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -65,7 +65,7 @@ lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE board_build.f_cpu = 160000000L -lib_extra_dirs = lib_basic, lib_ssl +lib_extra_dirs = lib_ssl [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG From a80944d9a2be6ef5b8d22ee45b865b0f10d898ad Mon Sep 17 00:00:00 2001 From: Christopher Tremblay Date: Mon, 26 Oct 2020 00:09:44 -0700 Subject: [PATCH 21/38] Cleanup the EZO devices Fixed a few mistakes in the comments and organized the code to make it easier to read & extend. --- tasmota/my_user_config.h | 12 +-- tasmota/tasmota_configurations.h | 2 +- tasmota/xsns_78_ezo.ino | 4 +- tasmota/xsns_78_ezoco2.ino | 4 + tasmota/xsns_78_ezoec.ino | 10 ++- tasmota/xsns_78_ezohum.ino | 4 + tasmota/xsns_78_ezoorp.ino | 8 +- tasmota/xsns_78_ezoph.ino | 8 +- tasmota/xsns_78_ezortd.ino | 8 +- tasmota/xsns_78_xezo.ino | 125 ++++++++----------------------- 10 files changed, 75 insertions(+), 110 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 34b479e0e..74fb012be 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -562,12 +562,12 @@ // #define USE_MCP9808 // [I2cDriver51] Enable MCP9808 temperature sensor (I2C addresses 0x18 - 0x1F) (+0k9 code) // #define USE_HP303B // [I2cDriver52] Enable HP303B temperature and pressure sensor (I2C address 0x76 or 0x77) (+6k2 code) // #define USE_MLX90640 // [I2cDriver53] Enable MLX90640 IR array temperature sensor (I2C address 0x33) (+20k code) -// #define USE_EZOPH // [I2cDriver55] Enable support for EZO's pH sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZOORP // [I2cDriver55] Enable support for EZO's ORP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZORTD // [I2cDriver55] Enable support for EZO's RTD sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZOPH // [I2cDriver55] Enable support for EZO's pH sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZOORP // [I2cDriver55] Enable support for EZO's ORP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZORTD // [I2cDriver55] Enable support for EZO's RTD sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) + #define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 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/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index 95fdcbea0..ed425a645 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -132,7 +132,7 @@ //#define USE_EZORTD // [I2cDriver55] Enable support for EZO's RTD sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) -//#define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +//#define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 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) diff --git a/tasmota/xsns_78_ezo.ino b/tasmota/xsns_78_ezo.ino index 783d86538..36fcea423 100644 --- a/tasmota/xsns_78_ezo.ino +++ b/tasmota/xsns_78_ezo.ino @@ -80,6 +80,8 @@ struct EZOStruct { virtual void ProcessMeasurement(void); virtual void Show(bool json, const char *name); + static const char id[] PROGMEM; + protected: void ProcessMeasurement(char *const data, const uint32_t len, const uint32_t latency) { @@ -108,7 +110,7 @@ protected: uint32_t lastRead; }; - +const char EZOStruct::id[] PROGMEM = ""; #endif // USE_EZO #endif // USE_I2C diff --git a/tasmota/xsns_78_ezoco2.ino b/tasmota/xsns_78_ezoco2.ino index df23a05cf..f9f09e1c4 100644 --- a/tasmota/xsns_78_ezoco2.ino +++ b/tasmota/xsns_78_ezoco2.ino @@ -49,9 +49,13 @@ struct EZOCO2 : public EZOStruct { } } + static const char id[] PROGMEM; + private: uint16_t CO2; }; +const char EZOCO2::id[] PROGMEM = "CO2"; + #endif // USE_EZOCO2 #endif // USE_I2C diff --git a/tasmota/xsns_78_ezoec.ino b/tasmota/xsns_78_ezoec.ino index 8d5a22912..1566e2907 100644 --- a/tasmota/xsns_78_ezoec.ino +++ b/tasmota/xsns_78_ezoec.ino @@ -1,5 +1,5 @@ /* - xsns_78_ezoph.ino - EZO EC I2C EC sensor support for Tasmota + xsns_78_ezoec.ino - EZO EC I2C EC sensor support for Tasmota Copyright (C) 2020 Christopher Tremblay @@ -35,8 +35,8 @@ struct EZOEC : public EZOStruct { virtual void Show(bool json, const char *name) { - char str[6]; - dtostrfd(EC, 2, str); + char str[10]; + dtostrfd(EC, 3, str); if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_EC "\":%s}" ), name, str); @@ -48,9 +48,13 @@ struct EZOEC : public EZOStruct { } } + static const char id[] PROGMEM; + private: float EC; }; +const char EZOEC::id[] PROGMEM = "EC"; + #endif // USE_EZOEC #endif // USE_I2C diff --git a/tasmota/xsns_78_ezohum.ino b/tasmota/xsns_78_ezohum.ino index 1eadb767d..62b6edc68 100644 --- a/tasmota/xsns_78_ezohum.ino +++ b/tasmota/xsns_78_ezohum.ino @@ -52,10 +52,14 @@ struct EZOHUM : public EZOStruct { } } + static const char id[] PROGMEM; + private: float humidity; float temperature; }; +const char EZOHUM::id[] PROGMEM = "HUM"; + #endif // USE_EZOHUM #endif // USE_I2C diff --git a/tasmota/xsns_78_ezoorp.ino b/tasmota/xsns_78_ezoorp.ino index 187245f35..d9faa999c 100644 --- a/tasmota/xsns_78_ezoorp.ino +++ b/tasmota/xsns_78_ezoorp.ino @@ -35,8 +35,8 @@ struct EZOORP : public EZOStruct { virtual void Show(bool json, const char *name) { - char str[6]; - dtostrfd(ORP, 0, str); + char str[8]; + dtostrfd(ORP, 2, str); if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ORP "\":%s}" ), name, str); @@ -48,11 +48,13 @@ struct EZOORP : public EZOStruct { } } + static const char id[] PROGMEM; + private: float ORP; }; - +const char EZOORP::id[] PROGMEM = "ORP"; #endif // USE_EZOORP #endif // USE_I2C diff --git a/tasmota/xsns_78_ezoph.ino b/tasmota/xsns_78_ezoph.ino index 522f93eea..77939d97a 100644 --- a/tasmota/xsns_78_ezoph.ino +++ b/tasmota/xsns_78_ezoph.ino @@ -22,8 +22,8 @@ #define EZO_PH_READ_LATENCY 900 -struct EZOpH : public EZOStruct { - EZOpH(uint32_t addr) : EZOStruct(addr), pH(NAN) {} +struct EZOPH : public EZOStruct { + EZOPH(uint32_t addr) : EZOStruct(addr), pH(NAN) {} virtual void ProcessMeasurement(void) { @@ -48,9 +48,13 @@ struct EZOpH : public EZOStruct { } } + static const char id[] PROGMEM; + private: float pH; }; +const char EZOPH::id[] PROGMEM = "pH"; + #endif // USE_EZOPH #endif // USE_I2C diff --git a/tasmota/xsns_78_ezortd.ino b/tasmota/xsns_78_ezortd.ino index da5869439..1d564d095 100644 --- a/tasmota/xsns_78_ezortd.ino +++ b/tasmota/xsns_78_ezortd.ino @@ -34,7 +34,7 @@ struct EZORTD : public EZOStruct { } virtual void Show(bool json, const char *name) -{ + { char str[10]; dtostrfd(ConvertTemp(temperature), Settings.flag2.temperature_resolution, str); @@ -46,11 +46,15 @@ struct EZORTD : public EZOStruct { WSContentSend_PD(HTTP_SNS_TEMP, name, str, TempUnit()); #endif // USE_WEBSERVER } -} + } + + static const char id[] PROGMEM; private: float temperature; }; +const char EZORTD::id[] PROGMEM = "RTD"; + #endif // USE_EZORTD #endif // USE_I2C diff --git a/tasmota/xsns_78_xezo.ino b/tasmota/xsns_78_xezo.ino index beb8a2288..0415c335d 100644 --- a/tasmota/xsns_78_xezo.ino +++ b/tasmota/xsns_78_xezo.ino @@ -28,7 +28,6 @@ // List of known EZO devices and their default address - enum { EZO_DO = 0x61, // D.O. EZO_ORP = 0x62, // ORP @@ -49,83 +48,37 @@ enum { }; -const char EZO_EMPTY[] PROGMEM = ""; -//const char EZO_DO_NAME[] PROGMEM = "DO"; -#ifdef USE_EZOORP -const char EZO_ORP_NAME[] PROGMEM = "ORP"; -#endif -#ifdef USE_EZOPH -const char EZO_PH_NAME[] PROGMEM = "pH"; -#endif -#ifdef USE_EZOEC -const char EZO_EC_NAME[] PROGMEM = "EC"; -#endif -#ifdef USE_EZORTD -const char EZO_RTD_NAME[] PROGMEM = "RTD"; -#endif -//const char EZO_PMP_NAME[] PROGMEM = "PMP"; -//const char EZO_FLO_NAME[] PROGMEM = "FLO"; -const char EZO_CO2_NAME[] PROGMEM = "CO2"; -//const char EZO_PRS_NAME[] PROGMEM = "PRS"; -//const char EZO_O2_NAME[] PROGMEM = "O2"; -#ifdef USE_EZOHUM -const char EZO_HUM_NAME[] PROGMEM = "HUM"; -#endif -//const char EZO_RGB_NAME[] PROGMEM = "RGB"; +// Creates a complex preprocessor macro to fetch a specified class OR EZOStruct if it wasn't defined +template struct IsComplete : std::false_type {}; +template struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type {}; + +#define GET_EZO_CLASS(CLASS) std::conditional::value, CLASS, EZOStruct>::type + +// The order of the EZO devices must map with the enum declared above const char *const EZOSupport[EZO_ADDR_n] PROGMEM = { - EZO_EMPTY, - -#ifdef USE_EZOORP - EZO_ORP_NAME, -#else - EZO_EMPTY, -#endif - -#ifdef USE_EZOPH - EZO_PH_NAME, -#else - EZO_EMPTY, -#endif - -#ifdef USE_EZOEC - EZO_EC_NAME, -#else - EZO_EMPTY, -#endif - - EZO_EMPTY, - -#ifdef USE_EZORTD - EZO_RTD_NAME, -#else - EZO_EMPTY, -#endif - - EZO_EMPTY, - EZO_EMPTY, - -#ifdef USE_EZOCO2 - EZO_CO2_NAME, -#else - EZO_EMPTY, -#endif - - EZO_EMPTY, - EZO_EMPTY, - EZO_EMPTY, - EZO_EMPTY, - EZO_EMPTY, - -#ifdef USE_EZOHUM - EZO_HUM_NAME, -#else - EZO_EMPTY, -#endif - - EZO_EMPTY, + EZOStruct::id, // "DO" + GET_EZO_CLASS(EZOORP)::id, + GET_EZO_CLASS(EZOPH)::id, + GET_EZO_CLASS(EZOEC)::id, + EZOStruct::id, + GET_EZO_CLASS(EZORTD)::id, + EZOStruct::id, // "PMP" + EZOStruct::id, // "FLO" + GET_EZO_CLASS(EZOCO2)::id, + EZOStruct::id, // "PRS" + EZOStruct::id, + EZOStruct::id, // "O2" + EZOStruct::id, + EZOStruct::id, + GET_EZO_CLASS(EZOHUM)::id, + EZOStruct::id, // "RGB" }; +#define CREATE_EZO_CLASS(CLASS) \ + case EZO_ ## CLASS: \ + sensor[count] = new EZO ## CLASS(addr); \ + break; struct EZOManager { @@ -252,34 +205,22 @@ private: // We use switch intead of virtual function to save RAM switch (j + EZO_ADDR_0) { #ifdef USE_EZOORP - case EZO_ORP: - sensor[count] = new EZOORP(addr); - break; + CREATE_EZO_CLASS(ORP) #endif #ifdef USE_EZOPH - case EZO_PH: - sensor[count] = new EZOpH(addr); - break; + CREATE_EZO_CLASS(PH) #endif #ifdef USE_EZOEC - case EZO_EC: - sensor[count] = new EZOEC(addr); - break; + CREATE_EZO_CLASS(EC) #endif #ifdef USE_EZORTD - case EZO_RTD: - sensor[count] = new EZORTD(addr); - break; + CREATE_EZO_CLASS(RTD) #endif #ifdef USE_EZOCO2 - case EZO_CO2: - sensor[count] = new EZOCO2(addr); - break; + CREATE_EZO_CLASS(CO2) #endif #ifdef USE_EZOHUM - case EZO_HUM: - sensor[count] = new EZOHUM(addr); - break; + CREATE_EZO_CLASS(HUM) #endif } From faa45994d233f902c96fa66b3a9a4f14438e73b6 Mon Sep 17 00:00:00 2001 From: Christopher Tremblay Date: Mon, 26 Oct 2020 00:11:07 -0700 Subject: [PATCH 22/38] Reset deafult my_user_config Removed debug code --- tasmota/my_user_config.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 74fb012be..e1497d93a 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -562,12 +562,12 @@ // #define USE_MCP9808 // [I2cDriver51] Enable MCP9808 temperature sensor (I2C addresses 0x18 - 0x1F) (+0k9 code) // #define USE_HP303B // [I2cDriver52] Enable HP303B temperature and pressure sensor (I2C address 0x76 or 0x77) (+6k2 code) // #define USE_MLX90640 // [I2cDriver53] Enable MLX90640 IR array temperature sensor (I2C address 0x33) (+20k code) - #define USE_EZOPH // [I2cDriver55] Enable support for EZO's pH sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) - #define USE_EZOORP // [I2cDriver55] Enable support for EZO's ORP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) - #define USE_EZORTD // [I2cDriver55] Enable support for EZO's RTD sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) - #define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) - #define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) - #define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOPH // [I2cDriver55] Enable support for EZO's pH sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOORP // [I2cDriver55] Enable support for EZO's ORP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZORTD // [I2cDriver55] Enable support for EZO's RTD sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 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 From 787a5a0451e3177002e56ccc3814f5b70ea38d6b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 08:13:13 +0100 Subject: [PATCH 23/38] remove redundant entrys in PlatformIO ENV --- platformio_tasmota_env.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index c38943b93..8b0e3cd41 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -32,7 +32,6 @@ lib_ignore = Hash [env:tasmota] -lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-minimal] build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL @@ -60,7 +59,6 @@ lib_extra_dirs = lib_basic [env:tasmota-ircustom] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM -lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE @@ -69,7 +67,6 @@ lib_extra_dirs = lib_basic, lib_ssl [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG -lib_extra_dirs = ${common.lib_extra_dirs} [env:tasmota-BR] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_BR From 71192db442e639bb161f75b34f7152ddf0786344 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 08:17:10 +0100 Subject: [PATCH 24/38] remove redundant entrys in PlatformIO ENV32 --- platformio_tasmota_env32.ini | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index d5c4c3d57..819b6aa75 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -67,32 +67,26 @@ lib_extra_dirs = libesp32, lib_basic [env:tasmota32-ircustom] extends = env:tasmota32 build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-BG] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=bg_BG -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-BR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pt_BR -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-CN] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=zh_CN -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-CZ] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=cs_CZ -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-DE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=de_DE -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-ES] extends = env:tasmota32 @@ -101,62 +95,50 @@ build_flags = ${common32.build_flags} -DMY_LANGUAGE=es_ES [env:tasmota32-FR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=fr_FR -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-GR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=el_GR -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-HE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=he_HE -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-HU] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=hu_HU -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-IT] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=it_IT -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-KO] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ko_KO -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-NL] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=nl_NL -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-PL] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pl_PL -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-PT] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=pt_PT -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-RO] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ro_RO -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-RU] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=ru_RU -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-SE] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=sv_SE -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-SK] extends = env:tasmota32 @@ -165,19 +147,15 @@ build_flags = ${common32.build_flags} -DMY_LANGUAGE=sk_SK [env:tasmota32-TR] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=tr_TR -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-TW] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=zh_TW -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-UK] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=uk_UA -lib_extra_dirs = ${common32.lib_extra_dirs} [env:tasmota32-VN] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=vi_VN -lib_extra_dirs = ${common32.lib_extra_dirs} From c860e0068ba9c6dbb58cab0b1b6d5655689e2192 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:29:12 +0100 Subject: [PATCH 25/38] Create readme.txt --- lib/headers/readme.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 lib/headers/readme.txt diff --git a/lib/headers/readme.txt b/lib/headers/readme.txt new file mode 100644 index 000000000..695df2dcb --- /dev/null +++ b/lib/headers/readme.txt @@ -0,0 +1 @@ +KNX header files. Workaround to exclude KNX library when not needed From d0c4bf59119f553afc2976bb0fd48d650ef50ab3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:31:24 +0100 Subject: [PATCH 26/38] Move KNX library to lib_div --- lib_div/esp-knx-ip-0.5.2/LICENSE | 21 + lib_div/esp-knx-ip-0.5.2/README.md | 94 +++ .../environment-sensor/environment-sensor.ino | 159 +++++ .../examples/sonoff/sonoff.ino | 183 +++++ .../examples/static-config/static-config.ino | 142 ++++ lib_div/esp-knx-ip-0.5.2/keywords.txt | 107 +++ lib_div/esp-knx-ip-0.5.2/library.json | 18 + .../esp-knx-ip-0.5.2/library.properties.off | 10 + lib_div/esp-knx-ip-0.5.2/src/DPT.h | 73 ++ .../src/esp-knx-ip-config.cpp | 358 ++++++++++ .../src/esp-knx-ip-conversion.cpp | 87 +++ .../esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp | 201 ++++++ .../src/esp-knx-ip-webserver.cpp | 540 ++++++++++++++ lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp | 664 ++++++++++++++++++ lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h | 600 ++++++++++++++++ 15 files changed, 3257 insertions(+) create mode 100644 lib_div/esp-knx-ip-0.5.2/LICENSE create mode 100644 lib_div/esp-knx-ip-0.5.2/README.md create mode 100644 lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino create mode 100644 lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino create mode 100644 lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino create mode 100644 lib_div/esp-knx-ip-0.5.2/keywords.txt create mode 100644 lib_div/esp-knx-ip-0.5.2/library.json create mode 100644 lib_div/esp-knx-ip-0.5.2/library.properties.off create mode 100644 lib_div/esp-knx-ip-0.5.2/src/DPT.h create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp create mode 100644 lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h diff --git a/lib_div/esp-knx-ip-0.5.2/LICENSE b/lib_div/esp-knx-ip-0.5.2/LICENSE new file mode 100644 index 000000000..80f432a97 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Nico Weichbrodt + +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. \ No newline at end of file diff --git a/lib_div/esp-knx-ip-0.5.2/README.md b/lib_div/esp-knx-ip-0.5.2/README.md new file mode 100644 index 000000000..a93c09192 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/README.md @@ -0,0 +1,94 @@ +# ESP-KNX-IP # + +This is a library for the ESP8266 to enable KNXnet/IP communication. It uses UDP multicast on 224.0.23.12:3671. +It is intended to be used with the Arduino platform for the ESP8266. + +## How to use ## + +The library is under development. API may change multiple times in the future. + +API documentation is available [here](https://github.com/envy/esp-knx-ip/wiki/API) + +A simple example: + +```c++ +#include + +const char* ssid = "my-ssid"; // your network SSID (name) +const char* pass = "my-pw"; // your network password + +config_id_t my_GA; +config_id_t param_id; + +int8_t some_var = 0; + +void setup() +{ + // Register a callback that is called when a configurable group address is receiving a telegram + knx.register_callback("Set/Get callback", my_callback); + knx.register_callback("Write callback", my_other_callback); + + int default_val = 21; + param_id = knx.config_register_int("My Parameter", default_val); + + // Register a configurable group address for sending out answers + my_GA = knx.config_register_ga("Answer GA"); + + knx.load(); // Try to load a config from EEPROM + + WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + } + + knx.start(); // Start everything. Must be called after WiFi connection has been established +} + +void loop() +{ + knx.loop(); +} + + +void my_callback(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_WRITE: + // Save received data + some_var = knx.data_to_1byte_int(msg.data); + break; + case KNX_CT_READ: + // Answer with saved data + knx.answer1ByteInt(msg.received_on, some_var); + break; + } +} + +void my_other_callback(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_WRITE: + // Write an answer somewhere else + int value = knx.config_get_int(param_id); + address_t ga = knx.config_get_ga(my_GA); + knx.answer1ByteInt(ga, (int8_t)value); + break; + } +} + +``` + +## How to configure (buildtime) ## + +Open the `esp-knx-ip.h` and take a look at the config options at the top inside the block marked `CONFIG` + +## How to configure (runtime) ## + +Simply visit the IP of your ESP with a webbrowser. You can configure the following: +* KNX physical address +* Which group address should trigger which callback +* Which group address are to be used by the program (e.g. for status replies) + +The configuration is dynamically generated from the code. diff --git a/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino b/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino new file mode 100644 index 000000000..02621bbc6 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino @@ -0,0 +1,159 @@ +/* + * This is an example showing a simple environment sensor based on a BME280 attached via I2C. + * This sketch was tested on a WeMos D1 mini + */ + +#include +#include + +// WiFi config here +const char* ssid = "myssid"; +const char* pass = "mypassword"; + +#define LED_PIN D4 +#define UPDATE_INTERVAL 10000 + +unsigned long next_change = 0; + +float last_temp = 0.0; +float last_hum = 0.0; +float last_pres = 0.0; + +config_id_t temp_ga, hum_ga, pres_ga; +config_id_t hostname_id; +config_id_t update_rate_id, send_rate_id; +config_id_t enable_sending_id; +config_id_t enable_reading_id; + +Adafruit_BME280 bme; + +void setup() { + pinMode(LED_PIN, OUTPUT); + Serial.begin(115200); + + hostname_id = knx.config_register_string("Hostname", 20, String("env")); + enable_sending_id = knx.config_register_bool("Send on update", true); + update_rate_id = knx.config_register_int("Update rate (ms)", UPDATE_INTERVAL); + temp_ga = knx.config_register_ga("Temperature", show_periodic_options); + hum_ga = knx.config_register_ga("Humidity", show_periodic_options); + pres_ga = knx.config_register_ga("Pressure", show_periodic_options); + + knx.callback_register("Read Temperature", temp_cb); + knx.callback_register("Read Humidity", hum_cb); + knx.callback_register("Read Pressure", pres_cb); + + knx.feedback_register_float("Temperature (°C)", &last_temp); + knx.feedback_register_float("Humidity (%)", &last_hum); + knx.feedback_register_float("Pressure (hPa)", &last_pres, 0); + + // Load previous config from EEPROM + knx.load(); + + // Init sensor + if (!bme.begin(0x76)) { + Serial.println("Could not find a valid BME280 sensor, check wiring!"); + } + + // Init WiFi + WiFi.hostname(knx.config_get_string(hostname_id)); + WiFi.begin(ssid, pass); + + Serial.println(""); + Serial.print("[Connecting]"); + Serial.print(ssid); + + digitalWrite(LED_PIN, LOW); + while (WiFi.status() != WL_CONNECTED) { + digitalWrite(LED_PIN, HIGH); + delay(250); + Serial.print("."); + digitalWrite(LED_PIN, LOW); + delay(250); + } + digitalWrite(LED_PIN, HIGH); + + // Start knx + knx.start(); + + Serial.println(); + Serial.println("Connected to wifi"); + Serial.println(WiFi.localIP()); +} + +void loop() { + knx.loop(); + + unsigned long now = millis(); + + if (next_change < now) + { + next_change = now + knx.config_get_int(update_rate_id); + + last_temp = bme.readTemperature(); + last_hum = bme.readHumidity(); + last_pres = bme.readPressure()/100.0f; + + Serial.print("T: "); + Serial.print(last_temp); + Serial.print("°C H: "); + Serial.print(last_hum); + Serial.print("% P: "); + Serial.print(last_pres); + Serial.println("hPa"); + + if (knx.config_get_bool(enable_sending_id)) + { + knx.write_2byte_float(knx.config_get_ga(temp_ga), last_temp); + knx.write_2byte_float(knx.config_get_ga(hum_ga), last_hum); + knx.write_2byte_float(knx.config_get_ga(pres_ga), last_pres); + } + } + + delay(50); +} + +bool show_periodic_options() +{ + return knx.config_get_bool(enable_sending_id); +} + +bool enable_reading_callback() +{ + return knx.config_get_bool(enable_reading_id); +} + +void temp_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_temp); + break; + } + } +} + +void hum_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_hum); + break; + } + } +} + +void pres_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_pres); + break; + } + } +} diff --git a/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino b/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino new file mode 100644 index 000000000..fc2400b7b --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino @@ -0,0 +1,183 @@ +#include + +// WiFi config here +const char* ssid = "ssid"; +const char* pass = "pass"; + +// Common +#define LED_PIN 13 + +// For Basic and S20 +#define BTN1_PIN 0 +#define CH1_PIN 12 + +// For 4CH +#define BTN2_PIN 9 +#define CH2_PIN 5 +#define BTN3_PIN 10 +#define CH3_PIN 4 +#define BTN4_PIN 14 +#define CH4_PIN 15 + +typedef enum __type_option +{ + SONOFF_TYPE_NONE = 0, + SONOFF_TYPE_BASIC = 1, + SONOFF_TYPE_S20 = 2, + SONOFF_TYPE_4CH = 3, + SONOFF_TYPE_4CH_PRO = 4, +} type_option_t; + +option_entry_t type_options[] = { + {"Sonoff Basic", SONOFF_TYPE_BASIC}, + {"Sonoff S20", SONOFF_TYPE_S20}, + {"Sonoff 4CH", SONOFF_TYPE_4CH}, + {"Sonoff 4CH Pro", SONOFF_TYPE_4CH_PRO}, + {nullptr, 0} +}; + +config_id_t hostname_id; +config_id_t type_id; + +typedef struct __sonoff_channel +{ + int pin; + int btn_pin; + config_id_t status_ga_id; + bool state; + bool last_btn_state; +} sonoff_channel_t; + +sonoff_channel_t channels[] = { + {CH1_PIN, BTN1_PIN, 0, false, false}, + {CH2_PIN, BTN2_PIN, 0, false, false}, + {CH3_PIN, BTN3_PIN, 0, false, false}, + {CH4_PIN, BTN4_PIN, 0, false, false}, +}; + +void setup() +{ + pinMode(LED_PIN, OUTPUT); + pinMode(BTN1_PIN, INPUT_PULLUP); + pinMode(BTN2_PIN, INPUT_PULLUP); + pinMode(BTN3_PIN, INPUT_PULLUP); + pinMode(BTN4_PIN, INPUT_PULLUP); + pinMode(CH1_PIN, OUTPUT); + pinMode(CH2_PIN, OUTPUT); + pinMode(CH3_PIN, OUTPUT); + pinMode(CH4_PIN, OUTPUT); + Serial.begin(115200); + + // Register the config options + hostname_id = knx.config_register_string("Hostname", 20, String("sonoff")); + type_id = knx.config_register_options("Type", type_options, SONOFF_TYPE_BASIC); + + channels[0].status_ga_id = knx.config_register_ga("Channel 1 Status GA"); + channels[1].status_ga_id = knx.config_register_ga("Channel 2 Status GA", is_4ch_or_4ch_pro); + channels[2].status_ga_id = knx.config_register_ga("Channel 3 Status GA", is_4ch_or_4ch_pro); + channels[3].status_ga_id = knx.config_register_ga("Channel 4 Status GA", is_4ch_or_4ch_pro); + + knx.callback_register("Channel 1", channel_cb, &channels[0]); + knx.callback_register("Channel 2", channel_cb, &channels[1], is_4ch_or_4ch_pro); + knx.callback_register("Channel 3", channel_cb, &channels[2], is_4ch_or_4ch_pro); + knx.callback_register("Channel 4", channel_cb, &channels[3], is_4ch_or_4ch_pro); + + knx.feedback_register_bool("Channel 1 is on", &(channels[0].state)); + knx.feedback_register_action("Toogle channel 1", toggle_chan, &channels[0]); + knx.feedback_register_bool("Channel 2 is on", &(channels[1].state), is_4ch_or_4ch_pro); + knx.feedback_register_action("Toogle channel 2", toggle_chan, &channels[1], is_4ch_or_4ch_pro); + knx.feedback_register_bool("Channel 3 is on", &(channels[2].state), is_4ch_or_4ch_pro); + knx.feedback_register_action("Toogle channel 3", toggle_chan, &channels[2], is_4ch_or_4ch_pro); + knx.feedback_register_bool("Channel 4 is on", &(channels[3].state), is_4ch_or_4ch_pro); + knx.feedback_register_action("Toogle channel 4", toggle_chan, &channels[3], is_4ch_or_4ch_pro); + + knx.load(); + + // Init WiFi + WiFi.hostname(knx.config_get_string(hostname_id)); + WiFi.begin(ssid, pass); + + Serial.println(""); + Serial.print("[Connecting]"); + Serial.print(ssid); + + digitalWrite(LED_PIN, LOW); + while (WiFi.status() != WL_CONNECTED) { + digitalWrite(LED_PIN, HIGH); + delay(500); + Serial.print("."); + digitalWrite(LED_PIN, LOW); + } + digitalWrite(LED_PIN, HIGH); + + // Start knx + knx.start(); + + Serial.println(); + Serial.println("Connected to wifi"); + Serial.println(WiFi.localIP()); +} + +void loop() +{ + knx.loop(); + + // Check local buttons + check_button(&channels[0]); + if (is_4ch_or_4ch_pro()) + { + check_button(&channels[1]); + check_button(&channels[2]); + check_button(&channels[3]); + } + + delay(50); +} + +bool is_basic_or_s20() +{ + uint8_t type = knx.config_get_options(type_id); + return type == SONOFF_TYPE_BASIC || type == SONOFF_TYPE_S20; +} + +bool is_4ch_or_4ch_pro() +{ + uint8_t type = knx.config_get_options(type_id); + return type == SONOFF_TYPE_4CH ||type == SONOFF_TYPE_4CH_PRO; +} + +void check_button(sonoff_channel_t *chan) +{ + bool state_now = digitalRead(chan->btn_pin) == HIGH ? true : false; + if (state_now != chan->last_btn_state && state_now == LOW) + { + chan->state = !chan->state; + digitalWrite(chan->pin, chan->state ? HIGH : LOW); + knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); + } + chan->last_btn_state = state_now; +} + +void toggle_chan(void *arg) +{ + sonoff_channel_t *chan = (sonoff_channel_t *)arg; + chan->state = !chan->state; + digitalWrite(chan->pin, chan->state ? HIGH : LOW); + knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); +} + +void channel_cb(message_t const &msg, void *arg) +{ + sonoff_channel_t *chan = (sonoff_channel_t *)arg; + switch (msg.ct) + { + case KNX_CT_WRITE: + chan->state = msg.data[0]; + Serial.println(chan->state ? "Toggle on" : "Toggle off"); + digitalWrite(chan->pin, chan->state ? HIGH : LOW); + knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); + break; + case KNX_CT_READ: + knx.answer_1bit(msg.received_on, chan->state); + } +} diff --git a/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino b/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino new file mode 100644 index 000000000..54472dda3 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino @@ -0,0 +1,142 @@ +/* + * This is an example showing a simple environment sensor based on a BME280 attached via I2C. + * It shows, how the library can used to statically configure a device without a webserver for config. + * This sketch was tested on a WeMos D1 mini + */ + +#include +#include + +// WiFi config here +const char* ssid = "myssid"; +const char* pass = "mypassword"; + +#define LED_PIN D4 +#define UPDATE_INTERVAL 10000 + +unsigned long next_change = 0; + +float last_temp = 0.0; +float last_hum = 0.0; +float last_pres = 0.0; + +Adafruit_BME280 bme; + +// Group addresses to send to (1/1/1, 1/1/2 and 1/1/3) +address_t temp_ga = knx.GA_to_address(1, 1, 1); +address_t hum_ga = knx.GA_to_address(1, 1, 2); +address_t pres_ga = knx.GA_to_address(1, 1, 3); + +void setup() { + pinMode(LED_PIN, OUTPUT); + Serial.begin(115200); + + callback_id_t temp_cb_id = knx.callback_register("Read Temperature", temp_cb); + callback_id_t hum_cb_id =knx.callback_register("Read Humidity", hum_cb); + callback_id_t pres_cb_id =knx.callback_register("Read Pressure", pres_cb); + + // Assign callbacks to group addresses (2/1/1, 2/1/2, 2/1/3) + knx.callback_assign(temp_cb_id, knx.GA_to_address(2, 1, 1)); + knx.callback_assign(hum_cb_id, knx.GA_to_address(2, 1, 2)); + knx.callback_assign(pres_cb_id, knx.GA_to_address(2, 1, 3)); + + // Set physical address (1.1.1) + knx.physical_address_set(knx.PA_to_address(1, 1, 1)); + + // Do not call knx.load() for static config, it will try to load config from EEPROM which we don't have here + + // Init sensor + if (!bme.begin(0x76)) { + Serial.println("Could not find a valid BME280 sensor, check wiring!"); + } + + // Init WiFi + WiFi.hostname("env"); + WiFi.begin(ssid, pass); + + Serial.println(""); + Serial.print("[Connecting]"); + Serial.print(ssid); + + digitalWrite(LED_PIN, LOW); + while (WiFi.status() != WL_CONNECTED) { + digitalWrite(LED_PIN, HIGH); + delay(250); + Serial.print("."); + digitalWrite(LED_PIN, LOW); + delay(250); + } + digitalWrite(LED_PIN, HIGH); + + // Start knx, disable webserver by passing nullptr + knx.start(nullptr); + + Serial.println(); + Serial.println("Connected to wifi"); + Serial.println(WiFi.localIP()); +} + +void loop() { + knx.loop(); + + unsigned long now = millis(); + + if (next_change < now) + { + next_change = now + UPDATE_INTERVAL; + + last_temp = bme.readTemperature(); + last_hum = bme.readHumidity(); + last_pres = bme.readPressure()/100.0f; + + Serial.print("T: "); + Serial.print(last_temp); + Serial.print("°C H: "); + Serial.print(last_hum); + Serial.print("% P: "); + Serial.print(last_pres); + Serial.println("hPa"); + + knx.write_2byte_float(temp_ga, last_temp); + knx.write_2byte_float(hum_ga, last_hum); + knx.write_2byte_float(pres_ga, last_pres); + } + + delay(50); +} + +void temp_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_temp); + break; + } + } +} + +void hum_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_hum); + break; + } + } +} + +void pres_cb(message_t const &msg, void *arg) +{ + switch (msg.ct) + { + case KNX_CT_READ: + { + knx.answer_2byte_float(msg.received_on, last_pres); + break; + } + } +} diff --git a/lib_div/esp-knx-ip-0.5.2/keywords.txt b/lib_div/esp-knx-ip-0.5.2/keywords.txt new file mode 100644 index 000000000..59836ef05 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/keywords.txt @@ -0,0 +1,107 @@ +# datatypes +address_t KEYWORD1 DATA_TYPE +message_t KEYWORD1 DATA_TYPE +callback_id_t KEYWORD1 DATA_TYPE +callback_assignment_id_t KEYWORD1 DATA_TYPE +option_entry_t KEYWORD1 DATA_TYPE +config_id_t KEYWORD1 DATA_TYPE +enable_condition_t KEYWORD1 DATA_TYPE +callback_fptr_t KEYWORD1 DATA_TYPE +feedback_action_fptr_t KEYWORD1 DATA_TYPE +knx_command_type_t KEYWORD1 DATA_TYPE + +# methods +setup KEYWORD2 +loop KEYWORD2 +GA_to_address KEYWORD2 +PA_to_address KEYWORD2 +callback_register KEYWORD2 +callback_assign KEYWORD2 +callback_deregister KEYWORD2 +callback_unassign KEYWORD2 +physical_address_set KEYWORD2 +physical_address_get KEYWORD2 +config_register_string KEYWORD2 +config_register_int KEYWORD2 +config_register_bool KEYWORD2 +config_register_options KEYWORD2 +config_register_ga KEYWORD2 +config_get_string KEYWORD2 +config_get_int KEYWORD2 +config_get_bool KEYWORD2 +config_get_options KEYWORD2 +config_get_ga KEYWORD2 +config_set_string KEYWORD2 +config_set_int KEYWORD2 +config_set_bool KEYWORD2 +config_set_options KEYWORD2 +config_set_ga KEYWORD2 +feedback_register_int KEYWORD2 +feedback_register_float KEYWORD2 +feedback_register_bool KEYWORD2 +feedback_register_action KEYWORD2 +send_1bit KEYWORD2 +send_2bit KEYWORD2 +send_4bit KEYWORD2 +send_1byte_int KEYWORD2 +send_1byte_uint KEYWORD2 +send_2byte_int KEYWORD2 +send_2byte_uint KEYWORD2 +send_2byte_float KEYWORD2 +send_3byte_time KEYWORD2 +send_3byte_time KEYWORD2 +send_3byte_date KEYWORD2 +send_3byte_date KEYWORD2 +send_3byte_color KEYWORD2 +send_3byte_color KEYWORD2 +send_4byte_int KEYWORD2 +send_4byte_uint KEYWORD2 +send_4byte_float KEYWORD2 +send_14byte_string KEYWORD2 +write_1bit KEYWORD2 +write_2bit KEYWORD2 +write_4bit KEYWORD2 +write_1byte_int KEYWORD2 +write_1byte_uint KEYWORD2 +write_2byte_int KEYWORD2 +write_2byte_uint KEYWORD2 +write_2byte_float KEYWORD2 +write_3byte_time KEYWORD2 +write_3byte_time KEYWORD2 +write_3byte_date KEYWORD2 +write_3byte_date KEYWORD2 +write_3byte_color KEYWORD2 +write_3byte_color KEYWORD2 +write_4byte_int KEYWORD2 +write_4byte_uint KEYWORD2 +write_4byte_float KEYWORD2 +write_14byte_string KEYWORD2 +answer_1bit KEYWORD2 +answer_2bit KEYWORD2 +answer_4bit KEYWORD2 +answer_1byte_int KEYWORD2 +answer_1byte_uint KEYWORD2 +answer_2byte_int KEYWORD2 +answer_2byte_uint KEYWORD2 +answer_2byte_float KEYWORD2 +answer_3byte_time KEYWORD2 +answer_3byte_time KEYWORD2 +answer_3byte_date KEYWORD2 +answer_3byte_date KEYWORD2 +answer_3byte_color KEYWORD2 +answer_3byte_color KEYWORD2 +answer_4byte_int KEYWORD2 +answer_4byte_uint KEYWORD2 +answer_4byte_float KEYWORD2 +answer_14byte_string KEYWORD2 + +data_to_1byte_int KEYWORD2 +data_to_2byte_int KEYWORD2 +data_to_2byte_float KEYWORD2 +data_to_4byte_float KEYWORD2 +data_to_3byte_color KEYWORD2 +data_to_3byte_time KEYWORD2 +data_to_3byte_data KEYWORD2 + +# constants +knx LITERAL1 diff --git a/lib_div/esp-knx-ip-0.5.2/library.json b/lib_div/esp-knx-ip-0.5.2/library.json new file mode 100644 index 000000000..0e2b42361 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/library.json @@ -0,0 +1,18 @@ +{ + "name": "ESP KNX IP Library", + "keywords": "knx, ethernet, mqtt, m2m, iot", + "description": "ESP8266 library for KNX/IP communication.", + "authors": [ + { + "name": "Nico Weichbrodt", + "maintainer": true + } + ], + "repository": { + "type": "git", + "url": "https://github.com/envy/esp-knx-ip.git" + }, + "version": "0.5.2", + "frameworks": "arduino", + "platforms": ["espressif8266", "espressif32"] +} diff --git a/lib_div/esp-knx-ip-0.5.2/library.properties.off b/lib_div/esp-knx-ip-0.5.2/library.properties.off new file mode 100644 index 000000000..f3b86de9c --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/library.properties.off @@ -0,0 +1,10 @@ +name=ESP KNX IP Library +version=0.5.2 +author=Nico Weichbrodt +maintainer=Nico Weichbrodt +sentence=ESP8266 library for KNX/IP communication. +paragraph=Build your own IoT devices with KNX/IP connectivity! +category=Communication +url=https://github.com/envy/esp-knx-ip +architectures=esp8266 +includes=esp-knx-ip.h diff --git a/lib_div/esp-knx-ip-0.5.2/src/DPT.h b/lib_div/esp-knx-ip-0.5.2/src/DPT.h new file mode 100644 index 000000000..3529d51af --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/DPT.h @@ -0,0 +1,73 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +typedef enum __dpt_1_001 +{ + DPT_1_001_OFF = 0x00, + DPT_1_001_ON = 0x01, +} dpt_1_001_t; + +typedef enum __dpt_2_001 +{ + DPT_2_001_NO_OFF = 0b00, + DPT_2_001_NO_ON = 0b01, + DPT_2_001_YES_OFF = 0b10, + DPT_2_001_YES_ON = 0b11, +} dpt_2_001_t; + +typedef enum __dpt_3_007 +{ + DPT_3_007_DECREASE_STOP = 0x00, + DPT_3_007_DECREASE_100 = 0x01, + DPT_3_007_DECREASE_50 = 0x02, + DPT_3_007_DECREASE_25 = 0x03, + DPT_3_007_DECREASE_12 = 0x04, + DPT_3_007_DECREASE_6 = 0x05, + DPT_3_007_DECREASE_3 = 0x06, + DPT_3_007_DECREASE_1 = 0x07, + DPT_3_007_INCREASE_STOP = 0x08, + DPT_3_007_INCREASE_100 = 0x09, + DPT_3_007_INCREASE_50 = 0x0A, + DPT_3_007_INCREASE_25 = 0x0B, + DPT_3_007_INCREASE_12 = 0x0C, + DPT_3_007_INCREASE_6 = 0x0D, + DPT_3_007_INCREASE_3 = 0x0E, + DPT_3_007_INCREASE_1 = 0x0F, +} dpt_3_007_t; + +typedef enum __weekday +{ + DPT_10_001_WEEKDAY_NODAY = 0, + DPT_10_001_WEEKDAY_MONDAY = 1, + DPT_10_001_WEEKDAY_TUESDAY = 2, + DPT_10_001_WEEKDAY_WEDNESDAY = 3, + DPT_10_001_WEEKDAY_THURSDAY = 4, + DPT_10_001_WEEKDAY_FRIDAY = 5, + DPT_10_001_WEEKDAY_SATURDAY = 6, + DPT_10_001_WEEKDAY_SUNDAY = 7, +} weekday_t; + +typedef struct __time_of_day +{ + weekday_t weekday; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} time_of_day_t; + +typedef struct __date +{ + uint8_t day; + uint8_t month; + uint8_t year; +} date_t; + +typedef struct __color +{ + uint8_t red; + uint8_t green; + uint8_t blue; +} color_t; diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp new file mode 100644 index 000000000..8d2b7b39d --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp @@ -0,0 +1,358 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#include "esp-knx-ip.h" + +/** + * Physical address functions + */ + +void ESPKNXIP::physical_address_set(address_t const &addr) +{ + physaddr = addr; +} + +address_t ESPKNXIP::physical_address_get() +{ + return physaddr; +} + +/** + * Configuration functions start here + */ +config_id_t ESPKNXIP::config_register_string(String name, uint8_t len, String _default, enable_condition_t cond) +{ + if (registered_configs >= MAX_CONFIGS) + return -1; + + if (_default.length() >= len) + return -1; + + config_id_t id = registered_configs; + + custom_configs[id].name = name; + custom_configs[id].type = CONFIG_TYPE_STRING; + custom_configs[id].len = sizeof(uint8_t) + len; + custom_configs[id].cond = cond; + if (id == 0) + custom_configs[id].offset = 0; + else + custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; + + __config_set_string(id, _default); + + registered_configs++; + + DEBUG_PRINT("Registered config >"); + DEBUG_PRINT(name); + DEBUG_PRINT("< @ "); + DEBUG_PRINT(id); + DEBUG_PRINT("/string["); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT("+"); + DEBUG_PRINT(custom_configs[id].len); + DEBUG_PRINTLN("]"); + + return id; +} + +config_id_t ESPKNXIP::config_register_int(String name, int32_t _default, enable_condition_t cond) +{ + if (registered_configs >= MAX_CONFIGS) + return -1; + + config_id_t id = registered_configs; + + custom_configs[id].name = name; + custom_configs[id].type = CONFIG_TYPE_INT; + custom_configs[id].len = sizeof(uint8_t) + sizeof(int32_t); + custom_configs[id].cond = cond; + if (id == 0) + custom_configs[id].offset = 0; + else + custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; + + __config_set_int(id, _default); + + registered_configs++; + + DEBUG_PRINT("Registered config >"); + DEBUG_PRINT(name); + DEBUG_PRINT("< @ "); + DEBUG_PRINT(id); + DEBUG_PRINT("/int["); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT("+"); + DEBUG_PRINT(custom_configs[id].len); + DEBUG_PRINTLN("]"); + + return id; +} + +config_id_t ESPKNXIP::config_register_bool(String name, bool _default, enable_condition_t cond) +{ + if (registered_configs >= MAX_CONFIGS) + return -1; + + config_id_t id = registered_configs; + + custom_configs[id].name = name; + custom_configs[id].type = CONFIG_TYPE_BOOL; + custom_configs[id].len = sizeof(uint8_t) + sizeof(uint8_t); + custom_configs[id].cond = cond; + if (id == 0) + custom_configs[id].offset = 0; + else + custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; + + __config_set_bool(id, _default); + + registered_configs++; + + DEBUG_PRINT("Registered config >"); + DEBUG_PRINT(name); + DEBUG_PRINT("< @ "); + DEBUG_PRINT(id); + DEBUG_PRINT("/bool["); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT("+"); + DEBUG_PRINT(custom_configs[id].len); + DEBUG_PRINTLN("]"); + + return id; +} + +config_id_t ESPKNXIP::config_register_options(String name, option_entry_t *options, uint8_t _default, enable_condition_t cond) +{ + if (registered_configs >= MAX_CONFIGS) + return -1; + + if (options == nullptr || options->name == nullptr) + return -1; + + config_id_t id = registered_configs; + + custom_configs[id].name = name; + custom_configs[id].type = CONFIG_TYPE_OPTIONS; + custom_configs[id].len = sizeof(uint8_t) + sizeof(uint8_t); + custom_configs[id].cond = cond; + if (id == 0) + custom_configs[id].offset = 0; + else + custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; + + custom_configs[id].data.options = options; + + __config_set_options(id, _default); + + registered_configs++; + + DEBUG_PRINT("Registered config >"); + DEBUG_PRINT(name); + DEBUG_PRINT("< @ "); + DEBUG_PRINT(id); + DEBUG_PRINT("/opt["); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT("+"); + DEBUG_PRINT(custom_configs[id].len); + DEBUG_PRINTLN("]"); + + return id; +} + +config_id_t ESPKNXIP::config_register_ga(String name, enable_condition_t cond) +{ + if (registered_configs >= MAX_CONFIGS) + return -1; + + config_id_t id = registered_configs; + + custom_configs[id].name = name; + custom_configs[id].type = CONFIG_TYPE_GA; + custom_configs[id].len = sizeof(uint8_t) + sizeof(address_t); + custom_configs[id].cond = cond; + if (id == 0) + custom_configs[id].offset = 0; + else + custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; + + address_t t; + t.value = 0; + __config_set_ga(id, t); + + registered_configs++; + + DEBUG_PRINT("Registered config >"); + DEBUG_PRINT(name); + DEBUG_PRINT("< @ "); + DEBUG_PRINT(id); + DEBUG_PRINT("/ga["); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT("+"); + DEBUG_PRINT(custom_configs[id].len); + DEBUG_PRINTLN("]"); + + return id; +} + +void ESPKNXIP::__config_set_flags(config_id_t id, config_flags_t flags) +{ + DEBUG_PRINT("Setting flag @ "); + DEBUG_PRINT(custom_configs[id].offset); + DEBUG_PRINT(" to "); + DEBUG_PRINT(custom_config_data[custom_configs[id].offset], BIN); + DEBUG_PRINT(" | "); + DEBUG_PRINT(flags, BIN); + custom_config_data[custom_configs[id].offset] |= (uint8_t)flags; + DEBUG_PRINT(" = "); + DEBUG_PRINTLN(custom_config_data[custom_configs[id].offset], BIN); +} + +void ESPKNXIP::config_set_string(config_id_t id, String val) +{ + if (id >= registered_configs) + return; + if (custom_configs[id].type != CONFIG_TYPE_STRING) + return; + if (val.length() >= custom_configs[id].len) + return; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_string(id, val); +} + +void ESPKNXIP::__config_set_string(config_id_t id, String &val) +{ + memcpy(&custom_config_data[custom_configs[id].offset + sizeof(uint8_t)], val.c_str(), val.length()+1); +} + +void ESPKNXIP::config_set_int(config_id_t id, int32_t val) +{ + if (id >= registered_configs) + return; + if (custom_configs[id].type != CONFIG_TYPE_INT) + return; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_int(id, val); +} + +void ESPKNXIP::__config_set_int(config_id_t id, int32_t val) +{ + // This does not work for some reason: + // Could be due to pointer alignment + //int32_t *v = (int32_t *)(custom_config_data + custom_configs[id].offset); + //*v = val; + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] = (uint8_t)((val & 0xFF000000) >> 24); + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] = (uint8_t)((val & 0x00FF0000) >> 16); + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 2] = (uint8_t)((val & 0x0000FF00) >> 8); + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 3] = (uint8_t)((val & 0x000000FF) >> 0); +} + +void ESPKNXIP::config_set_bool(config_id_t id, bool val) +{ + if (id >= registered_configs) + return; + if (custom_configs[id].type != CONFIG_TYPE_BOOL) + return; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_bool(id, val); +} + +void ESPKNXIP::__config_set_bool(config_id_t id, bool val) +{ + custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] = val ? 1 : 0; +} + +void ESPKNXIP::config_set_options(config_id_t id, uint8_t val) +{ + if (id >= registered_configs) + return; + if (custom_configs[id].type != CONFIG_TYPE_OPTIONS) + return; + + option_entry_t *cur = custom_configs[id].data.options; + while (cur->name != nullptr) + { + if (cur->value == val) + { + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_options(id, val); + break; + } + cur++; + } +} + +void ESPKNXIP::__config_set_options(config_id_t id, uint8_t val) +{ + custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] = val; +} + +void ESPKNXIP::config_set_ga(config_id_t id, address_t const &val) +{ + if (id >= registered_configs) + return; + if (custom_configs[id].type != CONFIG_TYPE_GA) + return; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_ga(id, val); +} + +void ESPKNXIP::__config_set_ga(config_id_t id, address_t const &val) +{ + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] = val.bytes.high; + custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] = val.bytes.low; +} + +String ESPKNXIP::config_get_string(config_id_t id) +{ + if (id >= registered_configs) + return String(""); + + return String((char *)&custom_config_data[custom_configs[id].offset + sizeof(uint8_t)]); +} + +int32_t ESPKNXIP::config_get_int(config_id_t id) +{ + if (id >= registered_configs) + return 0; + + int32_t v = (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] << 24) + + (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] << 16) + + (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 2] << 8) + + (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 3] << 0); + return v; +} + +bool ESPKNXIP::config_get_bool(config_id_t id) +{ + if (id >= registered_configs) + return false; + + return custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] != 0; +} + +uint8_t ESPKNXIP::config_get_options(config_id_t id) +{ + if (id >= registered_configs) + return false; + + return custom_config_data[custom_configs[id].offset + sizeof(uint8_t)]; +} + +address_t ESPKNXIP::config_get_ga(config_id_t id) +{ + address_t t; + if (id >= registered_configs) + { + t.value = 0; + return t; + } + + t.bytes.high = custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0]; + t.bytes.low = custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1]; + + return t; +} diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp new file mode 100644 index 000000000..9dc2fd563 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp @@ -0,0 +1,87 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#include "esp-knx-ip.h" + +/** + * Conversion functions + */ + +bool ESPKNXIP::data_to_bool(uint8_t *data) +{ + return (data[0] & 0x01) == 1 ? true : false; +} + +int8_t ESPKNXIP::data_to_1byte_int(uint8_t *data) +{ + return (int8_t)data[1]; +} + +uint8_t ESPKNXIP::data_to_1byte_uint(uint8_t *data) +{ + return data[1]; +} + +int16_t ESPKNXIP::data_to_2byte_int(uint8_t *data) +{ + return (int16_t)((data[1] << 8) | data[2]); +} + +uint16_t ESPKNXIP::data_to_2byte_uint(uint8_t *data) +{ + return (uint16_t)((data[1] << 8) | data[2]); +} + +float ESPKNXIP::data_to_2byte_float(uint8_t *data) +{ + //uint8_t sign = (data[1] & 0b10000000) >> 7; + uint8_t expo = (data[1] & 0b01111000) >> 3; + int16_t mant = ((data[1] & 0b10000111) << 8) | data[2]; + return 0.01f * mant * pow(2, expo); +} + +time_of_day_t ESPKNXIP::data_to_3byte_time(uint8_t *data) +{ + time_of_day_t time; + time.weekday = (weekday_t)((data[1] & 0b11100000) >> 5); + time.hours = (data[1] & 0b00011111); + time.minutes = (data[2] & 0b00111111); + time.seconds = (data[3] & 0b00111111); + return time; +} + +date_t ESPKNXIP::data_to_3byte_data(uint8_t *data) +{ + date_t date; + date.day = (data[1] & 0b00011111); + date.month = (data[2] & 0b00001111); + date.year = (data[3] & 0b01111111); + return date; +} + +color_t ESPKNXIP::data_to_3byte_color(uint8_t *data) +{ + color_t color; + color.red = data[1]; + color.green = data[2]; + color.blue = data[3]; + return color; +} + +int32_t ESPKNXIP::data_to_4byte_int(uint8_t *data) +{ + return (int32_t)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) | (data[4] << 0)); +} + +uint32_t ESPKNXIP::data_to_4byte_uint(uint8_t *data) +{ + return (uint32_t)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) | (data[4] << 0)); +} + +float ESPKNXIP::data_to_4byte_float(uint8_t *data) +{ + return (float)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) |data[4]); +} \ No newline at end of file diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp new file mode 100644 index 000000000..e71e5954c --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp @@ -0,0 +1,201 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#include "esp-knx-ip.h" + +/** + * Send functions + */ + +void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t data_len, uint8_t *data) +{ + if (receiver.value == 0) + return; + +#if SEND_CHECKSUM + uint32_t len = 6 + 2 + 8 + data_len + 1; // knx_pkt + cemi_msg + cemi_service + data + checksum +#else + uint32_t len = 6 + 2 + 8 + data_len; // knx_pkt + cemi_msg + cemi_service + data +#endif + DEBUG_PRINT(F("Creating packet with len ")); + DEBUG_PRINTLN(len) + uint8_t buf[len]; + knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf; + knx_pkt->header_len = 0x06; + knx_pkt->protocol_version = 0x10; + knx_pkt->service_type = __ntohs(KNX_ST_ROUTING_INDICATION); + knx_pkt->total_len.len = __ntohs(len); + cemi_msg_t *cemi_msg = (cemi_msg_t *)knx_pkt->pkt_data; + cemi_msg->message_code = KNX_MT_L_DATA_IND; + cemi_msg->additional_info_len = 0; + cemi_service_t *cemi_data = &cemi_msg->data.service_information; + cemi_data->control_1.bits.confirm = 0; +//cemi_data->control_1.bits.ack = 1; + cemi_data->control_1.bits.ack = 0; // ask for ACK? 0-no 1-yes + cemi_data->control_1.bits.priority = B11; + cemi_data->control_1.bits.system_broadcast = 0x01; + cemi_data->control_1.bits.repeat = 0x01; // 0 = repeated telegram, 1 = not repeated telegram + cemi_data->control_1.bits.reserved = 0; + cemi_data->control_1.bits.frame_type = 0x01; + cemi_data->control_2.bits.extended_frame_format = 0x00; + cemi_data->control_2.bits.hop_count = 0x06; + cemi_data->control_2.bits.dest_addr_type = 0x01; + cemi_data->source = physaddr; + cemi_data->destination = receiver; + //cemi_data->destination.bytes.high = (area << 3) | line; + //cemi_data->destination.bytes.low = member; + cemi_data->data_len = data_len; + cemi_data->pci.apci = (ct & 0x0C) >> 2; +//cemi_data->pci.apci = KNX_COT_NCD_ACK; + cemi_data->pci.tpci_seq_number = 0x00; + cemi_data->pci.tpci_comm_type = KNX_COT_UDP; // Type of communication: DATA PACKAGE or CONTROL DATA +//cemi_data->pci.tpci_comm_type = KNX_COT_NCD; // Type of communication: DATA PACKAGE or CONTROL DATA + memcpy(cemi_data->data, data, data_len); +//cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((KNX_COT_NCD_ACK & 0x03) << 6); + cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((ct & 0x03) << 6); + +#if SEND_CHECKSUM + // Calculate checksum, which is just XOR of all bytes + uint8_t cs = buf[0] ^ buf[1]; + for (uint32_t i = 2; i < len - 1; ++i) + { + cs ^= buf[i]; + } + buf[len - 1] = cs; +#endif + +#ifdef ESP_KNX_DEBUG + DEBUG_PRINT(F("Sending packet:")); + for (int i = 0; i < len; ++i) + { + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINT(buf[i], 16); + } + DEBUG_PRINTLN(F("")); +#endif + + udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); + udp.write(buf, len); + udp.endPacket(); + +} + +void ESPKNXIP::send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit) +{ + uint8_t buf[] = {(uint8_t)(bit & 0b00000001)}; + send(receiver, ct, 1, buf); +} + +void ESPKNXIP::send_2bit(address_t const &receiver, knx_command_type_t ct, uint8_t twobit) +{ + uint8_t buf[] = {(uint8_t)(twobit & 0b00000011)}; + send(receiver, ct, 1, buf); +} + +void ESPKNXIP::send_4bit(address_t const &receiver, knx_command_type_t ct, uint8_t fourbit) +{ + uint8_t buf[] = {(uint8_t)(fourbit & 0b00001111)}; + send(receiver, ct, 1, buf); +} + +void ESPKNXIP::send_1byte_int(address_t const &receiver, knx_command_type_t ct, int8_t val) +{ + uint8_t buf[] = {0x00, (uint8_t)val}; + send(receiver, ct, 2, buf); +} + +void ESPKNXIP::send_1byte_uint(address_t const &receiver, knx_command_type_t ct, uint8_t val) +{ + uint8_t buf[] = {0x00, val}; + send(receiver, ct, 2, buf); +} + +void ESPKNXIP::send_2byte_int(address_t const &receiver, knx_command_type_t ct, int16_t val) +{ + uint8_t buf[] = {0x00, (uint8_t)(val >> 8), (uint8_t)(val & 0x00FF)}; + send(receiver, ct, 3, buf); +} + +void ESPKNXIP::send_2byte_uint(address_t const &receiver, knx_command_type_t ct, uint16_t val) +{ + uint8_t buf[] = {0x00, (uint8_t)(val >> 8), (uint8_t)(val & 0x00FF)}; + send(receiver, ct, 3, buf); +} + +void ESPKNXIP::send_2byte_float(address_t const &receiver, knx_command_type_t ct, float val) +{ + float v = val * 100.0f; + int e = 0; + for (; v < -2048.0f; v /= 2) + ++e; + for (; v > 2047.0f; v /= 2) + ++e; + long m = (long)round(v) & 0x7FF; + short msb = (short) (e << 3 | m >> 8); + if (val < 0.0f) + msb |= 0x80; + uint8_t buf[] = {0x00, (uint8_t)msb, (uint8_t)m}; + send(receiver, ct, 3, buf); +} + +void ESPKNXIP::send_3byte_time(address_t const &receiver, knx_command_type_t ct, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) +{ + weekday <<= 5; + uint8_t buf[] = {0x00, (uint8_t)(((weekday << 5) & 0xE0) | (hours & 0x1F)), (uint8_t)(minutes & 0x3F), (uint8_t)(seconds & 0x3F)}; + send(receiver, ct, 4, buf); +} + +void ESPKNXIP::send_3byte_date(address_t const &receiver, knx_command_type_t ct, uint8_t day, uint8_t month, uint8_t year) +{ + uint8_t buf[] = {0x00, (uint8_t)(day & 0x1F), (uint8_t)(month & 0x0F), year}; + send(receiver, ct, 4, buf); +} + +void ESPKNXIP::send_3byte_color(address_t const &receiver, knx_command_type_t ct, uint8_t red, uint8_t green, uint8_t blue) +{ + uint8_t buf[] = {0x00, red, green, blue}; + send(receiver, ct, 4, buf); +} + +void ESPKNXIP::send_4byte_int(address_t const &receiver, knx_command_type_t ct, int32_t val) +{ + uint8_t buf[] = {0x00, + (uint8_t)((val & 0xFF000000) >> 24), + (uint8_t)((val & 0x00FF0000) >> 16), + (uint8_t)((val & 0x0000FF00) >> 8), + (uint8_t)((val & 0x000000FF) >> 0)}; + send(receiver, ct, 5, buf); +} + +void ESPKNXIP::send_4byte_uint(address_t const &receiver, knx_command_type_t ct, uint32_t val) +{ + uint8_t buf[] = {0x00, + (uint8_t)((val & 0xFF000000) >> 24), + (uint8_t)((val & 0x00FF0000) >> 16), + (uint8_t)((val & 0x0000FF00) >> 8), + (uint8_t)((val & 0x000000FF) >> 0)}; + send(receiver, ct, 5, buf); +} + +void ESPKNXIP::send_4byte_float(address_t const &receiver, knx_command_type_t ct, float val) +{ + uint8_t buf[] = {0x00, ((uint8_t *)&val)[3], ((uint8_t *)&val)[2], ((uint8_t *)&val)[1], ((uint8_t *)&val)[0]}; + send(receiver, ct, 5, buf); +} + +void ESPKNXIP::send_14byte_string(address_t const &receiver, knx_command_type_t ct, const char *val) +{ + // DPT16 strings are always 14 bytes long, however the data array is one larger due to the telegram structure. + // The first byte needs to be zero, string start after that. + uint8_t buf[15] = {0x00}; + int len = strlen(val); + if (len > 14) + { + len = 14; + } + memcpy(buf+1, val, len); + send(receiver, ct, 15, buf); +} diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp new file mode 100644 index 000000000..bdbc013fd --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp @@ -0,0 +1,540 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#include "esp-knx-ip.h" + +void ESPKNXIP::__handle_root() +{ + String m = F(""); +#if USE_BOOTSTRAP + m += F(""); + m += F(""); +#endif + m += F("
"); + m += F("

ESP KNX

"); + + // Feedback + + if (registered_feedbacks > 0) + { + m += F("

Feedback

"); + for (feedback_id_t i = 0; i < registered_feedbacks; ++i) + { + if (feedbacks[i].cond && !feedbacks[i].cond()) + { + continue; + } + m += F("
"); + m += F("
"); + m += F("
"); + m += feedbacks[i].name; + m += F("
"); + switch (feedbacks[i].type) + { + case FEEDBACK_TYPE_INT: + m += F(""); + m += String(*(int32_t *)feedbacks[i].data); + m += F(""); + break; + case FEEDBACK_TYPE_FLOAT: + m += F(""); + m += feedbacks[i].options.float_options.prefix; + m += String(*(float *)feedbacks[i].data, feedbacks[i].options.float_options.precision); + m += feedbacks[i].options.float_options.suffix; + m += F(""); + break; + case FEEDBACK_TYPE_BOOL: + m += F(""); + m += (*(bool *)feedbacks[i].data) ? F("True") : F("False"); + m += F(""); + break; + case FEEDBACK_TYPE_ACTION: + m += F("
"); + break; + } + m += F("
"); + m += F("
"); + } + } + + if (registered_callbacks > 0) + m += F("

Callbacks

"); + + if (registered_callback_assignments > 0) + { + for (uint8_t i = 0; i < registered_callback_assignments; ++i) + { + // Skip empty slots + if ((callback_assignments[i].slot_flags & SLOT_FLAGS_USED) == 0) + { + continue; + } + // Skip disabled callbacks + if (callbacks[callback_assignments[i].callback_id].cond && !callbacks[callback_assignments[i].callback_id].cond()) + { + continue; + } + address_t &addr = callback_assignments[i].address; + m += F("
"); + m += F("
"); + m += F("
"); + m += addr.ga.area; + m += F("/"); + m += addr.ga.line; + m += F("/"); + m += addr.ga.member; + m += F(""); + m += F(""); + m += callbacks[callback_assignments[i].callback_id].name; + m += F("
"); + m += F("
"); + m += F("
"); + m += F("
"); + } + } + + if (registered_callbacks > 0) + { + m += F("
"); + m += F("
"); + m += F(""); + m += F("
/
"); + m += F(""); + m += F("
/
"); + m += F(""); + m += F("
->
"); + m += F(""); + m += F("
"); + m += F("
"); + m += F("
"); + } + + m += F("

Configuration

"); + + // Physical address + m += F("
"); + m += F("
"); + m += F("
Physical address
"); + m += F(""); + m += F("
.
"); + m += F(""); + m += F("
.
"); + m += F(""); + m += F("
"); + m += F("
"); + m += F("
"); + + if (registered_configs > 0) + { + for (config_id_t i = 0; i < registered_configs; ++i) + { + // Check if this config option has a enable condition and if so check that condition + if (custom_configs[i].cond && !custom_configs[i].cond()) + continue; + + m += F("
"); + m += F("
"); + m += F("
"); + m += custom_configs[i].name; + m += F("
"); + + switch (custom_configs[i].type) + { + case CONFIG_TYPE_STRING: + m += F(""); + break; + case CONFIG_TYPE_INT: + m += F(""); + break; + case CONFIG_TYPE_BOOL: + m += F("
"); + m += F(""); + m += F("
"); + break; + case CONFIG_TYPE_OPTIONS: + { + m += F(""); + break; + } + case CONFIG_TYPE_GA: + address_t a = config_get_ga(i); + m += F(""); + m += F("
/
"); + m += F(""); + m += F("
/
"); + m += F(""); + break; + } + m += F(""); + m += F("
"); + m += F("
"); + m += F("
"); + } + } + +#if !(DISABLE_EEPROM_BUTTONS && DISABLE_RESTORE_BUTTON && DISABLE_REBOOT_BUTTON) + // EEPROM save and restore + m += F("
"); + // Save to EEPROM +#if !DISABLE_EEPROM_BUTTONS + m += F("
"); + m += F("
"); + m += F(""); + m += F(""); + m += F("
"); + m += F("
"); + // Restore from EEPROM + m += F("
"); + m += F("
"); + m += F(""); + m += F(""); + m += F("
"); + m += F("
"); +#endif +#if !DISABLE_RESTORE_BUTTON + // Load Defaults + m += F("
"); + m += F("
"); + m += F(""); + m += F("
"); + m += F("
"); +#endif +#if !DISABLE_REBOOT_BUTTON + // Reboot + m += F("
"); + m += F("
"); + m += F(""); + m += F("
"); + m += F("
"); +#endif + m += F("
"); // row +#endif + + // End of page + m += F("
"); + server->send(200, F("text/html"), m); +} + +void ESPKNXIP::__handle_register() +{ + DEBUG_PRINTLN(F("Register called")); + if (server->hasArg(F("area")) && server->hasArg(F("line")) && server->hasArg(F("member")) && server->hasArg(F("cb"))) + { + uint8_t area = server->arg(F("area")).toInt(); + uint8_t line = server->arg(F("line")).toInt(); + uint8_t member = server->arg(F("member")).toInt(); + callback_id_t cb = (callback_id_t)server->arg(F("cb")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(area); + DEBUG_PRINT(F("/")); + DEBUG_PRINT(line); + DEBUG_PRINT(F("/")); + DEBUG_PRINT(member); + DEBUG_PRINT(F("/")); + DEBUG_PRINT(cb); + DEBUG_PRINTLN(F("")); + + if (area > 31 || line > 7) + { + DEBUG_PRINTLN(F("Area or Line wrong")); + goto end; + } + + if (!__callback_is_id_valid(cb)) + { + DEBUG_PRINTLN(F("Invalid callback id")); + goto end; + } + address_t ga = {.ga={line, area, member}}; + __callback_register_assignment(ga, cb); + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} + +void ESPKNXIP::__handle_delete() +{ + DEBUG_PRINTLN(F("Delete called")); + if (server->hasArg(F("id"))) + { + callback_assignment_id_t id = (callback_assignment_id_t)server->arg(F("id")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(id); + DEBUG_PRINTLN(F("")); + + if (id >= registered_callback_assignments || (callback_assignments[id].slot_flags & SLOT_FLAGS_USED) == 0) + { + DEBUG_PRINTLN(F("ID wrong")); + goto end; + } + + __callback_delete_assignment(id); + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} + +void ESPKNXIP::__handle_set() +{ + DEBUG_PRINTLN(F("Set called")); + if (server->hasArg(F("area")) && server->hasArg(F("line")) && server->hasArg(F("member"))) + { + uint8_t area = server->arg(F("area")).toInt(); + uint8_t line = server->arg(F("line")).toInt(); + uint8_t member = server->arg(F("member")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(area); + DEBUG_PRINT(F(".")); + DEBUG_PRINT(line); + DEBUG_PRINT(F(".")); + DEBUG_PRINT(member); + DEBUG_PRINTLN(F("")); + + if (area > 31 || line > 7) + { + DEBUG_PRINTLN(F("Area or Line wrong")); + goto end; + } + + physaddr.bytes.high = (area << 4) | line; + physaddr.bytes.low = member; + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} + +void ESPKNXIP::__handle_config() +{ + DEBUG_PRINTLN(F("Config called")); + if (server->hasArg(F("id"))) + { + config_id_t id = server->arg(F("id")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(id); + DEBUG_PRINTLN(F("")); + + if (id < 0 || id >= registered_configs) + { + DEBUG_PRINTLN(F("ID wrong")); + goto end; + } + + switch (custom_configs[id].type) + { + case CONFIG_TYPE_STRING: + { + String v = server->arg(F("value")); + if (v.length() >= custom_configs[id].len) + goto end; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_string(id, v); + break; + } + case CONFIG_TYPE_INT: + { + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_int(id, server->arg(F("value")).toInt()); + break; + } + case CONFIG_TYPE_BOOL: + { + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_bool(id, server->arg(F("value")).compareTo(F("on")) == 0); + break; + } + case CONFIG_TYPE_OPTIONS: + { + uint8_t val = (uint8_t)server->arg(F("value")).toInt(); + DEBUG_PRINT(F("Value: ")); + DEBUG_PRINTLN(val); + config_set_options(id, val); + break; + } + case CONFIG_TYPE_GA: + { + uint8_t area = server->arg(F("area")).toInt(); + uint8_t line = server->arg(F("line")).toInt(); + uint8_t member = server->arg(F("member")).toInt(); + if (area > 31 || line > 7) + { + DEBUG_PRINTLN(F("Area or Line wrong")); + goto end; + } + address_t tmp; + tmp.bytes.high = (area << 3) | line; + tmp.bytes.low = member; + __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); + __config_set_ga(id, tmp); + break; + } + } + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} + +void ESPKNXIP::__handle_feedback() +{ +DEBUG_PRINTLN(F("Feedback called")); + if (server->hasArg(F("id"))) + { + config_id_t id = server->arg(F("id")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(id); + DEBUG_PRINTLN(F("")); + + if (id < 0 || id >= registered_feedbacks) + { + DEBUG_PRINTLN(F("ID wrong")); + goto end; + } + + switch (feedbacks[id].type) + { + case FEEDBACK_TYPE_ACTION: + { + feedback_action_fptr_t func = (feedback_action_fptr_t)feedbacks[id].data; + void *arg = feedbacks[id].options.action_options.arg; + func(arg); + break; + } + default: + DEBUG_PRINTLN(F("Feedback has no action")); + break; + } + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} + +#if !DISABLE_RESTORE_BUTTONS +void ESPKNXIP::__handle_restore() +{ + DEBUG_PRINTLN(F("Restore called")); + memcpy(custom_config_data, custom_config_default_data, MAX_CONFIG_SPACE); +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} +#endif + +#if !DISABLE_REBOOT_BUTTONS +void ESPKNXIP::__handle_reboot() +{ + DEBUG_PRINTLN(F("Rebooting!")); + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); + delay(1000); + ESP.restart(); + //while(1); +} +#endif + +#if !DISABLE_EEPROM_BUTTONS +void ESPKNXIP::__handle_eeprom() +{ + DEBUG_PRINTLN(F("EEPROM called")); + if (server->hasArg(F("mode"))) + { + uint8_t mode = server->arg(F("mode")).toInt(); + + DEBUG_PRINT(F("Got args: ")); + DEBUG_PRINT(mode); + DEBUG_PRINTLN(F("")); + + if (mode == 1) + { + // save + save_to_eeprom(); + } + else if (mode == 2) + { + // restore + restore_from_eeprom(); + } + } +end: + server->sendHeader(F("Location"),F(__ROOT_PATH)); + server->send(302); +} +#endif diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp new file mode 100644 index 000000000..35cbb2161 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp @@ -0,0 +1,664 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#include "esp-knx-ip.h" + +char const *string_defaults[] = +{ + "Do this", + "True", + "False", + "" +}; + +ESPKNXIP::ESPKNXIP() : server(nullptr), + registered_callback_assignments(0), + free_callback_assignment_slots(0), + registered_callbacks(0), + free_callback_slots(0), + registered_configs(0), + registered_feedbacks(0) +{ + DEBUG_PRINTLN(); + DEBUG_PRINTLN("ESPKNXIP starting up"); + // Default physical address is 1.1.0 + physaddr.bytes.high = (/*area*/1 << 4) | /*line*/1; + physaddr.bytes.low = /*member*/0; + memset(callback_assignments, 0, MAX_CALLBACK_ASSIGNMENTS * sizeof(callback_assignment_t)); + memset(callbacks, 0, MAX_CALLBACKS * sizeof(callback_fptr_t)); + memset(custom_config_data, 0, MAX_CONFIG_SPACE * sizeof(uint8_t)); + memset(custom_config_default_data, 0, MAX_CONFIG_SPACE * sizeof(uint8_t)); + memset(custom_configs, 0, MAX_CONFIGS * sizeof(config_t)); +} + +void ESPKNXIP::load() +{ + memcpy(custom_config_default_data, custom_config_data, MAX_CONFIG_SPACE); + EEPROM.begin(EEPROM_SIZE); + restore_from_eeprom(); +} + +void ESPKNXIP::start(ESP8266WebServer *srv) +{ + server = srv; + __start(); +} + +void ESPKNXIP::start() +{ + server = new ESP8266WebServer(80); + __start(); +} + +void ESPKNXIP::__start() +{ + if (server != nullptr) + { + server->on(ROOT_PREFIX, [this](){ + __handle_root(); + }); + server->on(__ROOT_PATH, [this](){ + __handle_root(); + }); + server->on(__REGISTER_PATH, [this](){ + __handle_register(); + }); + server->on(__DELETE_PATH, [this](){ + __handle_delete(); + }); + server->on(__PHYS_PATH, [this](){ + __handle_set(); + }); +#if !DISABLE_EEPROM_BUTTONS + server->on(__EEPROM_PATH, [this](){ + __handle_eeprom(); + }); +#endif + server->on(__CONFIG_PATH, [this](){ + __handle_config(); + }); + server->on(__FEEDBACK_PATH, [this](){ + __handle_feedback(); + }); +#if !DISABLE_RESTORE_BUTTON + server->on(__RESTORE_PATH, [this](){ + __handle_restore(); + }); +#endif +#if !DISABLE_REBOOT_BUTTON + server->on(__REBOOT_PATH, [this](){ + __handle_reboot(); + }); +#endif + server->begin(); + } + udp.beginMulticast(WiFi.localIP(), MULTICAST_IP, MULTICAST_PORT); +} + +void ESPKNXIP::save_to_eeprom() +{ + uint32_t address = 0; + uint64_t magic = EEPROM_MAGIC; + EEPROM.put(address, magic); + address += sizeof(uint64_t); + EEPROM.put(address++, registered_callback_assignments); + for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) + { + EEPROM.put(address, callback_assignments[i].address); + address += sizeof(address_t); + } + for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) + { + EEPROM.put(address, callback_assignments[i].callback_id); + address += sizeof(callback_id_t); + } + EEPROM.put(address, physaddr); + address += sizeof(address_t); + + EEPROM.put(address, custom_config_data); + address += sizeof(custom_config_data); + + EEPROM.commit(); + DEBUG_PRINT("Wrote to EEPROM: 0x"); + DEBUG_PRINTLN(address, HEX); +} + +void ESPKNXIP::restore_from_eeprom() +{ + uint32_t address = 0; + uint64_t magic = 0; + EEPROM.get(address, magic); + if (magic != EEPROM_MAGIC) + { + DEBUG_PRINTLN("No valid magic in EEPROM, aborting restore."); + DEBUG_PRINT("Expected 0x"); + DEBUG_PRINT((unsigned long)(EEPROM_MAGIC >> 32), HEX); + DEBUG_PRINT(" 0x"); + DEBUG_PRINT((unsigned long)(EEPROM_MAGIC), HEX); + DEBUG_PRINT(" got 0x"); + DEBUG_PRINT((unsigned long)(magic >> 32), HEX); + DEBUG_PRINT(" 0x"); + DEBUG_PRINTLN((unsigned long)magic, HEX); + return; + } + address += sizeof(uint64_t); + EEPROM.get(address++, registered_callback_assignments); + for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) + { + EEPROM.get(address, callback_assignments[i].address); + if (callback_assignments[i].address.value != 0) + { + // if address is not 0/0/0 then mark slot as used + callback_assignments[i].slot_flags |= SLOT_FLAGS_USED; + DEBUG_PRINTLN("used slot"); + } + else + { + // if address is 0/0/0, then we found a free slot, yay! + // however, only count those slots, if we have not reached registered_callback_assignments yet + if (i < registered_callback_assignments) + { + DEBUG_PRINTLN("free slot before reaching registered_callback_assignments"); + free_callback_assignment_slots++; + } + else + { + DEBUG_PRINTLN("free slot"); + } + } + address += sizeof(address_t); + } + for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) + { + EEPROM.get(address, callback_assignments[i].callback_id); + address += sizeof(callback_id_t); + } + EEPROM.get(address, physaddr); + address += sizeof(address_t); + + //EEPROM.get(address, custom_config_data); + //address += sizeof(custom_config_data); + uint32_t conf_offset = address; + for (uint8_t i = 0; i < registered_configs; ++i) + { + // First byte is flags. + config_flags_t flags = CONFIG_FLAGS_NO_FLAGS; + flags = (config_flags_t)EEPROM.read(address); + DEBUG_PRINT("Flag in EEPROM @ "); + DEBUG_PRINT(address - conf_offset); + DEBUG_PRINT(": "); + DEBUG_PRINTLN(flags, BIN); + custom_config_data[custom_configs[i].offset] = flags; + if (flags & CONFIG_FLAGS_VALUE_SET) + { + DEBUG_PRINTLN("Non-default value"); + for (int j = 0; j < custom_configs[i].len - sizeof(uint8_t); ++j) + { + custom_config_data[custom_configs[i].offset + sizeof(uint8_t) + j] = EEPROM.read(address + sizeof(uint8_t) + j); + } + } + + address += custom_configs[i].len; + } + + DEBUG_PRINT("Restored from EEPROM: 0x"); + DEBUG_PRINTLN(address, HEX); +} + +uint16_t ESPKNXIP::__ntohs(uint16_t n) +{ + return (uint16_t)((((uint8_t*)&n)[0] << 8) | (((uint8_t*)&n)[1])); +} + +callback_assignment_id_t ESPKNXIP::__callback_register_assignment(address_t address, callback_id_t id) +{ + if (registered_callback_assignments >= MAX_CALLBACK_ASSIGNMENTS) + return -1; + + if (free_callback_assignment_slots == 0) + { + callback_assignment_id_t aid = registered_callback_assignments; + + callback_assignments[aid].slot_flags |= SLOT_FLAGS_USED; + callback_assignments[aid].address = address; + callback_assignments[aid].callback_id = id; + registered_callback_assignments++; + return aid; + } + else + { + // find the free slot + for (callback_assignment_id_t aid = 0; aid < registered_callback_assignments; ++aid) + { + if (callback_assignments[aid].slot_flags & SLOT_FLAGS_USED) + { + // found a used slot + continue; + } + // and now an empty one + callback_assignments[aid].slot_flags |= SLOT_FLAGS_USED; + callback_assignments[aid].address = address; + callback_assignments[aid].callback_id = id; + + free_callback_assignment_slots--; + return id; + } + } + return -1; +} + +void ESPKNXIP::__callback_delete_assignment(callback_assignment_id_t id) +{ + // TODO this can be optimized if we are deleting the last element + // as then we can decrement registered_callback_assignments + + // clear slot and mark it as empty + callback_assignments[id].slot_flags = SLOT_FLAGS_EMPTY; + callback_assignments[id].address.value = 0; + callback_assignments[id].callback_id = 0; + + if (id == registered_callback_assignments - 1) + { + DEBUG_PRINTLN("last cba deleted"); + // If this is the last callback, we can delete it by decrementing registered_callbacks. + registered_callback_assignments--; + + // However, if the assignment before this slot are also empty, we can decrement even further + // First check if this was also the first element + if (id == 0) + { + DEBUG_PRINTLN("really last cba"); + // If this was the last, then we are done. + return; + } + + id--; + while(true) + { + DEBUG_PRINT("checking "); + DEBUG_PRINTLN((int32_t)id); + if ((callback_assignments[id].slot_flags & SLOT_FLAGS_USED) == 0) + { + DEBUG_PRINTLN("merged free slot"); + // Slot before is empty + free_callback_assignment_slots--; + registered_callback_assignments--; + } + else + { + DEBUG_PRINTLN("aborted on used slot"); + // Slot is used, abort + return; + } + id--; + if (id == CALLBACK_ASSIGNMENT_ID_MAX) + { + DEBUG_PRINTLN("abort on wrap"); + // Wrap around, abort + return; + } + } + } + else + { + DEBUG_PRINTLN("free slot created"); + // there is now one more free slot + free_callback_assignment_slots++; + } +} + +bool ESPKNXIP::__callback_is_id_valid(callback_id_t id) +{ + if (id < registered_callbacks) + return true; + + if (callbacks[id].slot_flags & SLOT_FLAGS_USED) + return true; + + return false; +} + +callback_id_t ESPKNXIP::callback_register(String name, callback_fptr_t cb, void *arg, enable_condition_t cond) +{ + if (registered_callbacks >= MAX_CALLBACKS) + return -1; + + if (free_callback_slots == 0) + { + callback_id_t id = registered_callbacks; + + callbacks[id].slot_flags |= SLOT_FLAGS_USED; + callbacks[id].name = name; + callbacks[id].fkt = cb; + callbacks[id].cond = cond; + callbacks[id].arg = arg; + registered_callbacks++; + return id; + } + else + { + // find the free slot + for (callback_id_t id = 0; id < registered_callbacks; ++id) + { + if (callbacks[id].slot_flags & SLOT_FLAGS_USED) + { + // found a used slot + continue; + } + // and now an empty one + callbacks[id].slot_flags |= SLOT_FLAGS_USED; + callbacks[id].name = name; + callbacks[id].fkt = cb; + callbacks[id].cond = cond; + callbacks[id].arg = arg; + + free_callback_slots--; + return id; + } + } + return -1; +} + +void ESPKNXIP::callback_deregister(callback_id_t id) +{ + if (!__callback_is_id_valid(id)) + return; + + // clear slot and mark it as empty + callbacks[id].slot_flags = SLOT_FLAGS_EMPTY; + callbacks[id].fkt = nullptr; + callbacks[id].cond = nullptr; + callbacks[id].arg = nullptr; + + if (id == registered_callbacks - 1) + { + // If this is the last callback, we can delete it by decrementing registered_callbacks. + registered_callbacks--; + + // However, if the callbacks before this slot are also empty, we can decrement even further + // First check if this was also the first element + if (id == 0) + { + // If this was the last, then we are done. + return; + } + + id--; + while(true) + { + if ((callbacks[id].slot_flags & SLOT_FLAGS_USED) == 0) + { + // Slot is empty + free_callback_slots--; + registered_callbacks--; + } + else + { + // Slot is used, abort + return; + } + id--; + if (id == CALLBACK_ASSIGNMENT_ID_MAX) + { + // Wrap around, abort + return; + } + } + } + else + { + // there is now one more free slot + free_callback_slots++; + } +} + +callback_assignment_id_t ESPKNXIP::callback_assign(callback_id_t id, address_t val) +{ + if (!__callback_is_id_valid(id)) + return -1; + + return __callback_register_assignment(val, id); +} + +void ESPKNXIP::callback_unassign(callback_assignment_id_t id) +{ + if (!__callback_is_id_valid(id)) + return; + + __callback_delete_assignment(id); +} + +/** + * Feedback functions start here + */ + +feedback_id_t ESPKNXIP::feedback_register_int(String name, int32_t *value, enable_condition_t cond) +{ + if (registered_feedbacks >= MAX_FEEDBACKS) + return -1; + + feedback_id_t id = registered_feedbacks; + + feedbacks[id].type = FEEDBACK_TYPE_INT; + feedbacks[id].name = name; + feedbacks[id].cond = cond; + feedbacks[id].data = (void *)value; + + registered_feedbacks++; + + return id; +} + +feedback_id_t ESPKNXIP::feedback_register_float(String name, float *value, uint8_t precision, char const *prefix, char const *suffix, enable_condition_t cond) +{ + if (registered_feedbacks >= MAX_FEEDBACKS) + return -1; + + feedback_id_t id = registered_feedbacks; + + feedbacks[id].type = FEEDBACK_TYPE_FLOAT; + feedbacks[id].name = name; + feedbacks[id].cond = cond; + feedbacks[id].data = (void *)value; + feedbacks[id].options.float_options.precision = precision; + feedbacks[id].options.float_options.prefix = prefix ? strdup(prefix) : STRING_DEFAULT_EMPTY; + feedbacks[id].options.float_options.suffix = suffix ? strdup(suffix) : STRING_DEFAULT_EMPTY; + + registered_feedbacks++; + + return id; +} + +feedback_id_t ESPKNXIP::feedback_register_bool(String name, bool *value, char const *true_text, char const *false_text, enable_condition_t cond) +{ + if (registered_feedbacks >= MAX_FEEDBACKS) + return -1; + + feedback_id_t id = registered_feedbacks; + + feedbacks[id].type = FEEDBACK_TYPE_BOOL; + feedbacks[id].name = name; + feedbacks[id].cond = cond; + feedbacks[id].data = (void *)value; + feedbacks[id].options.bool_options.true_text = true_text ? strdup(true_text) : STRING_DEFAULT_TRUE; + feedbacks[id].options.bool_options.false_text = false_text ? strdup(false_text) : STRING_DEFAULT_FALSE; + + registered_feedbacks++; + + return id; +} + +feedback_id_t ESPKNXIP::feedback_register_action(String name, feedback_action_fptr_t value, const char *btn_text, void *arg, enable_condition_t cond) +{ + if (registered_feedbacks >= MAX_FEEDBACKS) + return -1; + + feedback_id_t id = registered_feedbacks; + + feedbacks[id].type = FEEDBACK_TYPE_ACTION; + feedbacks[id].name = name; + feedbacks[id].cond = cond; + feedbacks[id].data = (void *)value; + feedbacks[id].options.action_options.arg = arg; + feedbacks[id].options.action_options.btn_text = btn_text ? strdup(btn_text) : STRING_DEFAULT_DO_THIS; + + registered_feedbacks++; + + return id; +} + +void ESPKNXIP::loop() +{ + __loop_knx(); + if (server != nullptr) + { + __loop_webserver(); + } +} + +void ESPKNXIP::__loop_webserver() +{ + server->handleClient(); +} + +void ESPKNXIP::__loop_knx() +{ + int read = udp.parsePacket(); + + if (!read) + { + return; + } + DEBUG_PRINTLN(F("")); + DEBUG_PRINT(F("LEN: ")); + DEBUG_PRINTLN(read); + + uint8_t buf[read]; + udp.read(buf, read); + + DEBUG_PRINT(F("Got packet:")); + +#ifdef ESP_KNX_DEBUG + + for (int i = 0; i < read; ++i) + + { + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINT(buf[i], 16); + } + +#endif + + DEBUG_PRINTLN(F("")); + + knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf; + + DEBUG_PRINT(F("ST: 0x")); + DEBUG_PRINTLN(__ntohs(knx_pkt->service_type), 16); + + if (knx_pkt->header_len != 0x06 && knx_pkt->protocol_version != 0x10 && knx_pkt->service_type != KNX_ST_ROUTING_INDICATION) + return; + + cemi_msg_t *cemi_msg = (cemi_msg_t *)knx_pkt->pkt_data; + + DEBUG_PRINT(F("MT: 0x")); + DEBUG_PRINTLN(cemi_msg->message_code, 16); + + if (cemi_msg->message_code != KNX_MT_L_DATA_IND) + return; + + DEBUG_PRINT(F("ADDI: 0x")); + DEBUG_PRINTLN(cemi_msg->additional_info_len, 16); + + cemi_service_t *cemi_data = &cemi_msg->data.service_information; + + if (cemi_msg->additional_info_len > 0) + cemi_data = (cemi_service_t *)(((uint8_t *)cemi_data) + cemi_msg->additional_info_len); + + DEBUG_PRINT(F("C1: 0x")); + DEBUG_PRINTLN(cemi_data->control_1.byte, 16); + + DEBUG_PRINT(F("C2: 0x")); + DEBUG_PRINTLN(cemi_data->control_2.byte, 16); + + DEBUG_PRINT(F("DT: 0x")); + DEBUG_PRINTLN(cemi_data->control_2.bits.dest_addr_type, 16); + + if (cemi_data->control_2.bits.dest_addr_type != 0x01) + return; + + DEBUG_PRINT(F("HC: 0x")); + DEBUG_PRINTLN(cemi_data->control_2.bits.hop_count, 16); + + DEBUG_PRINT(F("EFF: 0x")); + DEBUG_PRINTLN(cemi_data->control_2.bits.extended_frame_format, 16); + + DEBUG_PRINT(F("Source: 0x")); + DEBUG_PRINT(cemi_data->source.bytes.high, 16); + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINTLN(cemi_data->source.bytes.low, 16); + + DEBUG_PRINT(F("Dest: 0x")); + DEBUG_PRINT(cemi_data->destination.bytes.high, 16); + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINTLN(cemi_data->destination.bytes.low, 16); + + knx_command_type_t ct = (knx_command_type_t)(((cemi_data->data[0] & 0xC0) >> 6) | ((cemi_data->pci.apci & 0x03) << 2)); + + DEBUG_PRINT(F("CT: 0x")); + DEBUG_PRINTLN(ct, 16); + +#ifdef ESP_KNX_DEBUG + for (int i = 0; i < cemi_data->data_len; ++i) + { + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINT(cemi_data->data[i], 16); + } +#endif + + DEBUG_PRINTLN(F("==")); + + // Call callbacks + for (int i = 0; i < registered_callback_assignments; ++i) + { + DEBUG_PRINT(F("Testing: 0x")); + DEBUG_PRINT(callback_assignments[i].address.bytes.high, 16); + DEBUG_PRINT(F(" 0x")); + DEBUG_PRINTLN(callback_assignments[i].address.bytes.low, 16); + if (cemi_data->destination.value == callback_assignments[i].address.value) + { + DEBUG_PRINTLN(F("Found match")); + if (callbacks[callback_assignments[i].callback_id].cond && !callbacks[callback_assignments[i].callback_id].cond()) + { + DEBUG_PRINTLN(F("But it's disabled")); +#if ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS + continue; +#else + return; +#endif + } + uint8_t data[cemi_data->data_len]; + memcpy(data, cemi_data->data, cemi_data->data_len); + data[0] = data[0] & 0x3F; + message_t msg = {}; + msg.ct = ct; + msg.received_on = cemi_data->destination; + msg.data_len = cemi_data->data_len; + msg.data = data; + callbacks[callback_assignments[i].callback_id].fkt(msg, callbacks[callback_assignments[i].callback_id].arg); +#if ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS + continue; +#else + return; +#endif + } + } + + return; +} + +// Global "singleton" object +ESPKNXIP knx; diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h new file mode 100644 index 000000000..6834a6125 --- /dev/null +++ b/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h @@ -0,0 +1,600 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#ifndef ESP_KNX_IP_H +#define ESP_KNX_IP_H + +/** + * CONFIG + * All MAX_ values must not exceed 255 (1 byte, except MAC_CONFIG_SPACE which can go up to 2 bytes, so 0xffff in theory) and must not be negative! + * Config space is restriced by EEPROM_SIZE (default 1024). + * Required EEPROM size is 8 + MAX_GA_CALLBACKS * 3 + 2 + MAX_CONFIG_SPACE which is 552 by default + */ +#define EEPROM_SIZE 1024 // [Default 1024] +#define MAX_CALLBACK_ASSIGNMENTS 10 // [Default 10] Maximum number of group address callbacks that can be stored +#define MAX_CALLBACKS 10 // [Default 10] Maximum number of callbacks that can be stored +#define MAX_CONFIGS 20 // [Default 20] Maximum number of config items that can be stored +#define MAX_CONFIG_SPACE 0x0200 // [Default 0x0200] Maximum number of bytes that can be stored for custom config + +#define MAX_FEEDBACKS 20 // [Default 20] Maximum number of feedbacks that can be shown + +// Callbacks +#define ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS 1 // [Default 0] Set to 1 to always test all assigned callbacks. This allows for multiple callbacks being assigned to the same address. If disabled, only the first assigned will be called. + +// Webserver related +#define USE_BOOTSTRAP 0 // [Default 1] Set to 1 to enable use of bootstrap CSS for nicer webconfig. CSS is loaded from bootstrapcdn.com. Set to 0 to disable +#define ROOT_PREFIX "/knx" // [Default ""] This gets prepended to all webserver paths, default is empty string "". Set this to "/knx" if you want the config to be available on http:///knx +#define DISABLE_EEPROM_BUTTONS 1 // [Default 0] Set to 1 to disable the EEPROM buttons in the web ui. +#define DISABLE_REBOOT_BUTTON 1 // [Default 0] Set to 1 to disable the reboot button in the web ui. +#define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui. + +// These values normally don't need adjustment +#ifndef MULTICAST_IP +#define MULTICAST_IP IPAddress(224, 0, 23, 12) // [Default IPAddress(224, 0, 23, 12)] +#else +#warning USING CUSTOM MULTICAST_IP +#endif + +#ifndef MULTICAST_PORT +#define MULTICAST_PORT 3671 // [Default 3671] +#else +#warning USING CUSTOM MULTICAST_PORT +#endif + +#define SEND_CHECKSUM 0 + +// Uncomment to enable printing out debug messages. +//#define ESP_KNX_DEBUG +/** + * END CONFIG + */ + +#include "Arduino.h" +#include +#include +#include +#include + +#include "DPT.h" + +#define EEPROM_MAGIC (0xDEADBEEF00000000 + (MAX_CONFIG_SPACE) + (MAX_CALLBACK_ASSIGNMENTS << 16) + (MAX_CALLBACKS << 8)) + +// Define where debug output will be printed. +#ifndef DEBUG_PRINTER +#define DEBUG_PRINTER Serial +#endif + +// Setup debug printing macros. +#ifdef ESP_KNX_DEBUG + #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } + #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } +#else + #define DEBUG_PRINT(...) {} + #define DEBUG_PRINTLN(...) {} +#endif + +#define __ROOT_PATH ROOT_PREFIX"/" +#define __REGISTER_PATH ROOT_PREFIX"/register" +#define __DELETE_PATH ROOT_PREFIX"/delete" +#define __PHYS_PATH ROOT_PREFIX"/phys" +#define __EEPROM_PATH ROOT_PREFIX"/eeprom" +#define __CONFIG_PATH ROOT_PREFIX"/config" +#define __FEEDBACK_PATH ROOT_PREFIX"/feedback" +#define __RESTORE_PATH ROOT_PREFIX"/restore" +#define __REBOOT_PATH ROOT_PREFIX"/reboot" + +/** + * Different service types, we are mainly interested in KNX_ST_ROUTING_INDICATION + */ +typedef enum __knx_service_type +{ + KNX_ST_SEARCH_REQUEST = 0x0201, + KNX_ST_SEARCH_RESPONSE = 0x0202, + KNX_ST_DESCRIPTION_REQUEST = 0x0203, + KNX_ST_DESCRIPTION_RESPONSE = 0x0204, + KNX_ST_CONNECT_REQUEST = 0x0205, + KNX_ST_CONNECT_RESPONSE = 0x0206, + KNX_ST_CONNECTIONSTATE_REQUEST = 0x0207, + KNX_ST_CONNECTIONSTATE_RESPONSE = 0x0208, + KNX_ST_DISCONNECT_REQUEST = 0x0209, + KNX_ST_DISCONNECT_RESPONSE = 0x020A, + + KNX_ST_DEVICE_CONFIGURATION_REQUEST = 0x0310, + KNX_ST_DEVICE_CONFIGURATION_ACK = 0x0311, + + KNX_ST_TUNNELING_REQUEST = 0x0420, + KNX_ST_TUNNELING_ACK = 0x0421, + + KNX_ST_ROUTING_INDICATION = 0x0530, + KNX_ST_ROUTING_LOST_MESSAGE = 0x0531, + KNX_ST_ROUTING_BUSY = 0x0532, + +// KNX_ST_RLOG_START = 0x0600, +// KNX_ST_RLOG_END = 0x06FF, + + KNX_ST_REMOTE_DIAGNOSTIC_REQUEST = 0x0740, + KNX_ST_REMOTE_DIAGNOSTIC_RESPONSE = 0x0741, + KNX_ST_REMOTE_BASIC_CONFIGURATION_REQUEST = 0x0742, + KNX_ST_REMOTE_RESET_REQUEST = 0x0743, + +// KNX_ST_OBJSRV_START = 0x0800, +// KNX_ST_OBJSRV_END = 0x08FF, +} knx_service_type_t; + +/** + * Differnt command types, first three are of main interest + */ +typedef enum __knx_command_type +{ + KNX_CT_READ = 0x00, + KNX_CT_ANSWER = 0x01, + KNX_CT_WRITE = 0x02, + KNX_CT_INDIVIDUAL_ADDR_WRITE = 0x03, + KNX_CT_INDIVIDUAL_ADDR_REQUEST = 0x04, + KNX_CT_INDIVIDUAL_ADDR_RESPONSE = 0x05, + KNX_CT_ADC_READ = 0x06, + KNX_CT_ADC_ANSWER = 0x07, + KNX_CT_MEM_READ = 0x08, + KNX_CT_MEM_ANSWER = 0x09, + KNX_CT_MEM_WRITE = 0x0A, +//KNX_CT_UNKNOWN = 0x0B, + KNX_CT_MASK_VERSION_READ = 0x0C, + KNX_CT_MASK_VERSION_RESPONSE = 0x0D, + KNX_CT_RESTART = 0x0E, + KNX_CT_ESCAPE = 0x0F, +} knx_command_type_t; + +/** + * cEMI message types, mainly KNX_MT_L_DATA_IND is interesting + */ +typedef enum __knx_cemi_msg_type +{ + KNX_MT_L_DATA_REQ = 0x11, + KNX_MT_L_DATA_IND = 0x29, + KNX_MT_L_DATA_CON = 0x2E, +} knx_cemi_msg_type_t; + +/** + * TCPI communication type + */ +typedef enum __knx_communication_type { + KNX_COT_UDP = 0x00, // Unnumbered Data Packet + KNX_COT_NDP = 0x01, // Numbered Data Packet + KNX_COT_UCD = 0x02, // Unnumbered Control Data + KNX_COT_NCD = 0x03, // Numbered Control Data +} knx_communication_type_t; + +/** + * acpi for KNX_COT_NCD + */ +typedef enum __knx_cot_ncd_ack_type { + KNX_COT_NCD_ACK = 0x10, // Inform positively reception of the Previouly received telegram + KNX_COT_NCD_NACK = 0x11, // Inform negatively reception of the Previouly received telegram +} knx_cot_ncd_ack_type_t; + +/** + * KNX/IP header + */ +typedef struct __knx_ip_pkt +{ + uint8_t header_len; // Should always be 0x06 + uint8_t protocol_version; // Should be version 1.0, transmitted as 0x10 + uint16_t service_type; // See knx_service_type_t + union + { + struct { + uint8_t first_byte; + uint8_t second_byte; + } bytes; + uint16_t len; + } total_len; // header_len + rest of pkt. This is a bit weird as the spec says this: If the total number of bytes transmitted is greater than 252 bytes, the first “Total Length” byte is set to FF (255). Only in this case the second byte includes additional length information + uint8_t pkt_data[]; // This is of type cemi_msg_t +} knx_ip_pkt_t; + +typedef struct __cemi_addi +{ + uint8_t type_id; + uint8_t len; + uint8_t data[]; +} cemi_addi_t; + +typedef union __address +{ + uint16_t value; + struct + { + uint8_t high; + uint8_t low; + } bytes; + struct __attribute__((packed)) + { + uint8_t line:3; + uint8_t area:5; + uint8_t member; + } ga; + struct __attribute__((packed)) + { + uint8_t line:4; + uint8_t area:4; + uint8_t member; + } pa; + uint8_t array[2]; +} address_t; + +typedef struct __cemi_service +{ + union + { + struct + { + // Struct is reversed due to bit order + uint8_t confirm:1; // 0 = no error, 1 = error + uint8_t ack:1; // 0 = no ack, 1 = ack + uint8_t priority:2; // 0 = system, 1 = high, 2 = urgent/alarm, 3 = normal + uint8_t system_broadcast:1; // 0 = system broadcast, 1 = broadcast + uint8_t repeat:1; // 0 = repeated telegram, 1 = not repeated telegram + uint8_t reserved:1; // always zero + uint8_t frame_type:1; // 0 = extended, 1 = standard + } bits; + uint8_t byte; + } control_1; + union + { + struct + { + // Struct is reversed due to bit order + uint8_t extended_frame_format:4; + uint8_t hop_count:3; + uint8_t dest_addr_type:1; // 0 = individual, 1 = group + } bits; + uint8_t byte; + } control_2; + address_t source; + address_t destination; + uint8_t data_len; // length of data, excluding the tpci byte + struct + { + uint8_t apci:2; // If tpci.comm_type == KNX_COT_UCD or KNX_COT_NCD, then this is apparently control data? + uint8_t tpci_seq_number:4; + uint8_t tpci_comm_type:2; // See knx_communication_type_t + } pci; + uint8_t data[]; +} cemi_service_t; + +typedef struct __cemi_msg +{ + uint8_t message_code; + uint8_t additional_info_len; + union + { +// cemi_addi_t additional_info[]; // Errors in GCC 10.1 + cemi_addi_t additional_info[10]; // Changed to arbitrary number to fix compilation + cemi_service_t service_information; + } data; +} cemi_msg_t; + +typedef enum __config_type +{ + CONFIG_TYPE_UNKNOWN, + CONFIG_TYPE_INT, + CONFIG_TYPE_BOOL, + CONFIG_TYPE_STRING, + CONFIG_TYPE_OPTIONS, + CONFIG_TYPE_GA, +} config_type_t; + +typedef enum __feedback_type +{ + FEEDBACK_TYPE_UNKNOWN, + FEEDBACK_TYPE_INT, + FEEDBACK_TYPE_FLOAT, + FEEDBACK_TYPE_BOOL, + FEEDBACK_TYPE_ACTION, +} feedback_type_t; + +typedef enum __config_flags +{ + CONFIG_FLAGS_NO_FLAGS = 0, + CONFIG_FLAGS_VALUE_SET = 1, +} config_flags_t; + +typedef enum __slot_flags +{ + SLOT_FLAGS_EMPTY = 0, // Empty slots have no flags + SLOT_FLAGS_USED = 1, +} slot_flags_t; + +typedef struct __message +{ + knx_command_type_t ct; + address_t received_on; + uint8_t data_len; + uint8_t *data; +} message_t; + +typedef bool (*enable_condition_t)(void); +typedef void (*callback_fptr_t)(message_t const &msg, void *arg); +typedef void (*feedback_action_fptr_t)(void *arg); + +typedef uint8_t callback_id_t; +#define CALLBACK_ID_MAX UINT8_MAX +typedef uint8_t callback_assignment_id_t; +#define CALLBACK_ASSIGNMENT_ID_MAX UINT8_MAX +typedef uint8_t config_id_t; +typedef uint8_t feedback_id_t; + +typedef struct __option_entry +{ + char const *name; + uint8_t value; +} option_entry_t; + +typedef struct __config +{ + config_type_t type; + String name; + uint8_t offset; + uint8_t len; + enable_condition_t cond; + union { + option_entry_t *options; + } data; +} config_t; + +extern char const *string_defaults[]; +#define STRING_DEFAULT_DO_THIS (string_defaults[0]) +#define STRING_DEFAULT_TRUE (string_defaults[1]) +#define STRING_DEFAULT_FALSE (string_defaults[2]) +#define STRING_DEFAULT_EMPTY (string_defaults[3]) + +typedef struct __feedback_float_options +{ + uint8_t precision; + char const *prefix; + char const *suffix; +} feedback_float_options_t; + +typedef struct __feedback_bool_options +{ + char const *true_text; + char const *false_text; +} feedback_bool_options_t; + +typedef struct __feedback_action_options +{ + void *arg; + char const *btn_text; +} feedback_action_options_t; + +typedef struct __feedback +{ + feedback_type_t type; + String name; + enable_condition_t cond; + void *data; + union { + feedback_bool_options_t bool_options; + feedback_float_options_t float_options; + feedback_action_options_t action_options; + } options; +} feedback_t; + +typedef struct __callback +{ + uint8_t slot_flags; + callback_fptr_t fkt; + enable_condition_t cond; + void *arg; + String name; +} callback_t; + +typedef struct __callback_assignment +{ + uint8_t slot_flags; + address_t address; + callback_id_t callback_id; +} callback_assignment_t; + +// FastPrecisePowf from tasmota/support_float.ino +//extern float FastPrecisePowf(const float x, const float y); + +class ESPKNXIP { + public: + ESPKNXIP(); + void load(); + void start(); + void start(ESP8266WebServer *srv); + void loop(); + + void save_to_eeprom(); + void restore_from_eeprom(); + + callback_id_t callback_register(String name, callback_fptr_t cb, void *arg = nullptr, enable_condition_t cond = nullptr); + callback_assignment_id_t callback_assign(callback_id_t id, address_t val); + void callback_deregister(callback_id_t id); + void callback_unassign(callback_assignment_id_t id); + + void physical_address_set(address_t const &addr); + address_t physical_address_get(); + + // Configuration functions + config_id_t config_register_string(String name, uint8_t len, String _default, enable_condition_t cond = nullptr); + config_id_t config_register_int(String name, int32_t _default, enable_condition_t cond = nullptr); + config_id_t config_register_bool(String name, bool _default, enable_condition_t cond = nullptr); + config_id_t config_register_options(String name, option_entry_t *options, uint8_t _default, enable_condition_t cond = nullptr); + config_id_t config_register_ga(String name, enable_condition_t cond = nullptr); + + String config_get_string(config_id_t id); + int32_t config_get_int(config_id_t id); + bool config_get_bool(config_id_t id); + uint8_t config_get_options(config_id_t id); + address_t config_get_ga(config_id_t id); + + void config_set_string(config_id_t id, String val); + void config_set_int(config_id_t id, int32_t val); + void config_set_bool(config_id_t, bool val); + void config_set_options(config_id_t id, uint8_t val); + void config_set_ga(config_id_t id, address_t const &val); + + // Feedback functions + feedback_id_t feedback_register_int(String name, int32_t *value, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_float(String name, float *value, uint8_t precision = 2, char const *prefix = nullptr, char const *suffix = nullptr, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_bool(String name, bool *value, char const *true_text = nullptr, char const *false_text = nullptr, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_action(String name, feedback_action_fptr_t value, char const *btn_text = nullptr, void *arg = nullptr, enable_condition_t = nullptr); + + // Send functions + void send(address_t const &receiver, knx_command_type_t ct, uint8_t data_len, uint8_t *data); + + void send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit); + void send_2bit(address_t const &receiver, knx_command_type_t ct, uint8_t twobit); + void send_4bit(address_t const &receiver, knx_command_type_t ct, uint8_t fourbit); + void send_1byte_int(address_t const &receiver, knx_command_type_t ct, int8_t val); + void send_1byte_uint(address_t const &receiver, knx_command_type_t ct, uint8_t val); + void send_2byte_int(address_t const &receiver, knx_command_type_t ct, int16_t val); + void send_2byte_uint(address_t const &receiver, knx_command_type_t ct, uint16_t val); + void send_2byte_float(address_t const &receiver, knx_command_type_t ct, float val); + void send_3byte_time(address_t const &receiver, knx_command_type_t ct, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds); + void send_3byte_time(address_t const &receiver, knx_command_type_t ct, time_of_day_t const &time) { send_3byte_time(receiver, ct, time.weekday, time.hours, time.minutes, time.seconds); } + void send_3byte_date(address_t const &receiver, knx_command_type_t ct, uint8_t day, uint8_t month, uint8_t year); + void send_3byte_date(address_t const &receiver, knx_command_type_t ct, date_t const &date) { send_3byte_date(receiver, ct, date.day, date.month, date.year); } + void send_3byte_color(address_t const &receiver, knx_command_type_t ct, uint8_t red, uint8_t green, uint8_t blue); + void send_3byte_color(address_t const &receiver, knx_command_type_t ct, color_t const &color) { send_3byte_color(receiver, ct, color.red, color.green, color.blue); } + void send_4byte_int(address_t const &receiver, knx_command_type_t ct, int32_t val); + void send_4byte_uint(address_t const &receiver, knx_command_type_t ct, uint32_t val); + void send_4byte_float(address_t const &receiver, knx_command_type_t ct, float val); + void send_14byte_string(address_t const &receiver, knx_command_type_t ct, const char *val); + + void write_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_WRITE, bit); } + void write_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_WRITE, twobit); } + void write_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_WRITE, fourbit); } + void write_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_WRITE, val); } + void write_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_WRITE, val); } + void write_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_WRITE, val); } + void write_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_WRITE, val); } + void write_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_WRITE, val); } + void write_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_WRITE, weekday, hours, minutes, seconds); } + void write_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_WRITE, time.weekday, time.hours, time.minutes, time.seconds); } + void write_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_WRITE, day, month, year); } + void write_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_WRITE, date.day, date.month, date.year); } + void write_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_WRITE, red, green, blue); } + void write_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_WRITE, color); } + void write_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_WRITE, val); } + void write_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_WRITE, val); } + void write_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_WRITE, val);} + void write_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_WRITE, val); } + + void answer_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_ANSWER, bit); } + void answer_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_ANSWER, twobit); } + void answer_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_ANSWER, fourbit); } + void answer_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_ANSWER, val); } + void answer_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_ANSWER, weekday, hours, minutes, seconds); } + void answer_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_ANSWER, time.weekday, time.hours, time.minutes, time.seconds); } + void answer_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_ANSWER, day, month, year); } + void answer_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_ANSWER, date.day, date.month, date.year); } + void answer_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_ANSWER, red, green, blue); } + void answer_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_ANSWER, color); } + void answer_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_ANSWER, val);} + void answer_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_ANSWER, val); } + + bool data_to_bool(uint8_t *data); + int8_t data_to_1byte_int(uint8_t *data); + uint8_t data_to_1byte_uint(uint8_t *data); + int16_t data_to_2byte_int(uint8_t *data); + uint16_t data_to_2byte_uint(uint8_t *data); + float data_to_2byte_float(uint8_t *data); + color_t data_to_3byte_color(uint8_t *data); + time_of_day_t data_to_3byte_time(uint8_t *data); + date_t data_to_3byte_data(uint8_t *data); + int32_t data_to_4byte_int(uint8_t *data); + uint32_t data_to_4byte_uint(uint8_t *data); + float data_to_4byte_float(uint8_t *data); + + static address_t GA_to_address(uint8_t area, uint8_t line, uint8_t member) + { + // Yes, the order is correct, see the struct definition above + address_t tmp = {.ga={line, area, member}}; + return tmp; + } + + static address_t PA_to_address(uint8_t area, uint8_t line, uint8_t member) + { + // Yes, the order is correct, see the struct definition above + address_t tmp = {.pa={line, area, member}}; + return tmp; + } + + private: + void __start(); + + void __loop_knx(); + + // Webserver functions + void __loop_webserver(); + void __handle_root(); + void __handle_register(); + void __handle_delete(); + void __handle_set(); +#if !DISABLE_EEPROM_BUTTONS + void __handle_eeprom(); +#endif + void __handle_config(); + void __handle_feedback(); +#if !DISABLE_RESTORE_BUTTONS + void __handle_restore(); +#endif +#if !DISABLE_REBOOT_BUTTONS + void __handle_reboot(); +#endif + + void __config_set_flags(config_id_t id, config_flags_t flags); + + void __config_set_string(config_id_t id, String &val); + void __config_set_int(config_id_t id, int32_t val); + void __config_set_bool(config_id_t id, bool val); + void __config_set_options(config_id_t id, uint8_t val); + void __config_set_ga(config_id_t id, address_t const &val); + + bool __callback_is_id_valid(callback_id_t id); + + callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id); + void __callback_delete_assignment(callback_assignment_id_t id); + + //static inline float pow(float a, float b) { return FastPrecisePowf(a, b); } + + ESP8266WebServer *server; + address_t physaddr; + + WiFiUDP udp; + + callback_assignment_id_t registered_callback_assignments; + callback_assignment_id_t free_callback_assignment_slots; + callback_assignment_t callback_assignments[MAX_CALLBACK_ASSIGNMENTS]; + + callback_id_t registered_callbacks; + callback_id_t free_callback_slots; + callback_t callbacks[MAX_CALLBACKS]; + + config_id_t registered_configs; + uint8_t custom_config_data[MAX_CONFIG_SPACE]; + uint8_t custom_config_default_data[MAX_CONFIG_SPACE]; + config_t custom_configs[MAX_CONFIGS]; + + feedback_id_t registered_feedbacks; + feedback_t feedbacks[MAX_FEEDBACKS]; + + uint16_t __ntohs(uint16_t); +}; + +// Global "singleton" object +extern ESPKNXIP knx; + +#endif From 7f95a51f0ada4e0aab5bd484eea837854a02e86f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:32:31 +0100 Subject: [PATCH 27/38] Add files via upload --- lib/headers/DPT.h | 73 +++++ lib/headers/esp-knx-ip.h | 600 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 673 insertions(+) create mode 100644 lib/headers/DPT.h create mode 100644 lib/headers/esp-knx-ip.h diff --git a/lib/headers/DPT.h b/lib/headers/DPT.h new file mode 100644 index 000000000..3529d51af --- /dev/null +++ b/lib/headers/DPT.h @@ -0,0 +1,73 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +typedef enum __dpt_1_001 +{ + DPT_1_001_OFF = 0x00, + DPT_1_001_ON = 0x01, +} dpt_1_001_t; + +typedef enum __dpt_2_001 +{ + DPT_2_001_NO_OFF = 0b00, + DPT_2_001_NO_ON = 0b01, + DPT_2_001_YES_OFF = 0b10, + DPT_2_001_YES_ON = 0b11, +} dpt_2_001_t; + +typedef enum __dpt_3_007 +{ + DPT_3_007_DECREASE_STOP = 0x00, + DPT_3_007_DECREASE_100 = 0x01, + DPT_3_007_DECREASE_50 = 0x02, + DPT_3_007_DECREASE_25 = 0x03, + DPT_3_007_DECREASE_12 = 0x04, + DPT_3_007_DECREASE_6 = 0x05, + DPT_3_007_DECREASE_3 = 0x06, + DPT_3_007_DECREASE_1 = 0x07, + DPT_3_007_INCREASE_STOP = 0x08, + DPT_3_007_INCREASE_100 = 0x09, + DPT_3_007_INCREASE_50 = 0x0A, + DPT_3_007_INCREASE_25 = 0x0B, + DPT_3_007_INCREASE_12 = 0x0C, + DPT_3_007_INCREASE_6 = 0x0D, + DPT_3_007_INCREASE_3 = 0x0E, + DPT_3_007_INCREASE_1 = 0x0F, +} dpt_3_007_t; + +typedef enum __weekday +{ + DPT_10_001_WEEKDAY_NODAY = 0, + DPT_10_001_WEEKDAY_MONDAY = 1, + DPT_10_001_WEEKDAY_TUESDAY = 2, + DPT_10_001_WEEKDAY_WEDNESDAY = 3, + DPT_10_001_WEEKDAY_THURSDAY = 4, + DPT_10_001_WEEKDAY_FRIDAY = 5, + DPT_10_001_WEEKDAY_SATURDAY = 6, + DPT_10_001_WEEKDAY_SUNDAY = 7, +} weekday_t; + +typedef struct __time_of_day +{ + weekday_t weekday; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} time_of_day_t; + +typedef struct __date +{ + uint8_t day; + uint8_t month; + uint8_t year; +} date_t; + +typedef struct __color +{ + uint8_t red; + uint8_t green; + uint8_t blue; +} color_t; diff --git a/lib/headers/esp-knx-ip.h b/lib/headers/esp-knx-ip.h new file mode 100644 index 000000000..6834a6125 --- /dev/null +++ b/lib/headers/esp-knx-ip.h @@ -0,0 +1,600 @@ +/** + * esp-knx-ip library for KNX/IP communication on an ESP8266 + * Author: Nico Weichbrodt + * License: MIT + */ + +#ifndef ESP_KNX_IP_H +#define ESP_KNX_IP_H + +/** + * CONFIG + * All MAX_ values must not exceed 255 (1 byte, except MAC_CONFIG_SPACE which can go up to 2 bytes, so 0xffff in theory) and must not be negative! + * Config space is restriced by EEPROM_SIZE (default 1024). + * Required EEPROM size is 8 + MAX_GA_CALLBACKS * 3 + 2 + MAX_CONFIG_SPACE which is 552 by default + */ +#define EEPROM_SIZE 1024 // [Default 1024] +#define MAX_CALLBACK_ASSIGNMENTS 10 // [Default 10] Maximum number of group address callbacks that can be stored +#define MAX_CALLBACKS 10 // [Default 10] Maximum number of callbacks that can be stored +#define MAX_CONFIGS 20 // [Default 20] Maximum number of config items that can be stored +#define MAX_CONFIG_SPACE 0x0200 // [Default 0x0200] Maximum number of bytes that can be stored for custom config + +#define MAX_FEEDBACKS 20 // [Default 20] Maximum number of feedbacks that can be shown + +// Callbacks +#define ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS 1 // [Default 0] Set to 1 to always test all assigned callbacks. This allows for multiple callbacks being assigned to the same address. If disabled, only the first assigned will be called. + +// Webserver related +#define USE_BOOTSTRAP 0 // [Default 1] Set to 1 to enable use of bootstrap CSS for nicer webconfig. CSS is loaded from bootstrapcdn.com. Set to 0 to disable +#define ROOT_PREFIX "/knx" // [Default ""] This gets prepended to all webserver paths, default is empty string "". Set this to "/knx" if you want the config to be available on http:///knx +#define DISABLE_EEPROM_BUTTONS 1 // [Default 0] Set to 1 to disable the EEPROM buttons in the web ui. +#define DISABLE_REBOOT_BUTTON 1 // [Default 0] Set to 1 to disable the reboot button in the web ui. +#define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui. + +// These values normally don't need adjustment +#ifndef MULTICAST_IP +#define MULTICAST_IP IPAddress(224, 0, 23, 12) // [Default IPAddress(224, 0, 23, 12)] +#else +#warning USING CUSTOM MULTICAST_IP +#endif + +#ifndef MULTICAST_PORT +#define MULTICAST_PORT 3671 // [Default 3671] +#else +#warning USING CUSTOM MULTICAST_PORT +#endif + +#define SEND_CHECKSUM 0 + +// Uncomment to enable printing out debug messages. +//#define ESP_KNX_DEBUG +/** + * END CONFIG + */ + +#include "Arduino.h" +#include +#include +#include +#include + +#include "DPT.h" + +#define EEPROM_MAGIC (0xDEADBEEF00000000 + (MAX_CONFIG_SPACE) + (MAX_CALLBACK_ASSIGNMENTS << 16) + (MAX_CALLBACKS << 8)) + +// Define where debug output will be printed. +#ifndef DEBUG_PRINTER +#define DEBUG_PRINTER Serial +#endif + +// Setup debug printing macros. +#ifdef ESP_KNX_DEBUG + #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } + #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } +#else + #define DEBUG_PRINT(...) {} + #define DEBUG_PRINTLN(...) {} +#endif + +#define __ROOT_PATH ROOT_PREFIX"/" +#define __REGISTER_PATH ROOT_PREFIX"/register" +#define __DELETE_PATH ROOT_PREFIX"/delete" +#define __PHYS_PATH ROOT_PREFIX"/phys" +#define __EEPROM_PATH ROOT_PREFIX"/eeprom" +#define __CONFIG_PATH ROOT_PREFIX"/config" +#define __FEEDBACK_PATH ROOT_PREFIX"/feedback" +#define __RESTORE_PATH ROOT_PREFIX"/restore" +#define __REBOOT_PATH ROOT_PREFIX"/reboot" + +/** + * Different service types, we are mainly interested in KNX_ST_ROUTING_INDICATION + */ +typedef enum __knx_service_type +{ + KNX_ST_SEARCH_REQUEST = 0x0201, + KNX_ST_SEARCH_RESPONSE = 0x0202, + KNX_ST_DESCRIPTION_REQUEST = 0x0203, + KNX_ST_DESCRIPTION_RESPONSE = 0x0204, + KNX_ST_CONNECT_REQUEST = 0x0205, + KNX_ST_CONNECT_RESPONSE = 0x0206, + KNX_ST_CONNECTIONSTATE_REQUEST = 0x0207, + KNX_ST_CONNECTIONSTATE_RESPONSE = 0x0208, + KNX_ST_DISCONNECT_REQUEST = 0x0209, + KNX_ST_DISCONNECT_RESPONSE = 0x020A, + + KNX_ST_DEVICE_CONFIGURATION_REQUEST = 0x0310, + KNX_ST_DEVICE_CONFIGURATION_ACK = 0x0311, + + KNX_ST_TUNNELING_REQUEST = 0x0420, + KNX_ST_TUNNELING_ACK = 0x0421, + + KNX_ST_ROUTING_INDICATION = 0x0530, + KNX_ST_ROUTING_LOST_MESSAGE = 0x0531, + KNX_ST_ROUTING_BUSY = 0x0532, + +// KNX_ST_RLOG_START = 0x0600, +// KNX_ST_RLOG_END = 0x06FF, + + KNX_ST_REMOTE_DIAGNOSTIC_REQUEST = 0x0740, + KNX_ST_REMOTE_DIAGNOSTIC_RESPONSE = 0x0741, + KNX_ST_REMOTE_BASIC_CONFIGURATION_REQUEST = 0x0742, + KNX_ST_REMOTE_RESET_REQUEST = 0x0743, + +// KNX_ST_OBJSRV_START = 0x0800, +// KNX_ST_OBJSRV_END = 0x08FF, +} knx_service_type_t; + +/** + * Differnt command types, first three are of main interest + */ +typedef enum __knx_command_type +{ + KNX_CT_READ = 0x00, + KNX_CT_ANSWER = 0x01, + KNX_CT_WRITE = 0x02, + KNX_CT_INDIVIDUAL_ADDR_WRITE = 0x03, + KNX_CT_INDIVIDUAL_ADDR_REQUEST = 0x04, + KNX_CT_INDIVIDUAL_ADDR_RESPONSE = 0x05, + KNX_CT_ADC_READ = 0x06, + KNX_CT_ADC_ANSWER = 0x07, + KNX_CT_MEM_READ = 0x08, + KNX_CT_MEM_ANSWER = 0x09, + KNX_CT_MEM_WRITE = 0x0A, +//KNX_CT_UNKNOWN = 0x0B, + KNX_CT_MASK_VERSION_READ = 0x0C, + KNX_CT_MASK_VERSION_RESPONSE = 0x0D, + KNX_CT_RESTART = 0x0E, + KNX_CT_ESCAPE = 0x0F, +} knx_command_type_t; + +/** + * cEMI message types, mainly KNX_MT_L_DATA_IND is interesting + */ +typedef enum __knx_cemi_msg_type +{ + KNX_MT_L_DATA_REQ = 0x11, + KNX_MT_L_DATA_IND = 0x29, + KNX_MT_L_DATA_CON = 0x2E, +} knx_cemi_msg_type_t; + +/** + * TCPI communication type + */ +typedef enum __knx_communication_type { + KNX_COT_UDP = 0x00, // Unnumbered Data Packet + KNX_COT_NDP = 0x01, // Numbered Data Packet + KNX_COT_UCD = 0x02, // Unnumbered Control Data + KNX_COT_NCD = 0x03, // Numbered Control Data +} knx_communication_type_t; + +/** + * acpi for KNX_COT_NCD + */ +typedef enum __knx_cot_ncd_ack_type { + KNX_COT_NCD_ACK = 0x10, // Inform positively reception of the Previouly received telegram + KNX_COT_NCD_NACK = 0x11, // Inform negatively reception of the Previouly received telegram +} knx_cot_ncd_ack_type_t; + +/** + * KNX/IP header + */ +typedef struct __knx_ip_pkt +{ + uint8_t header_len; // Should always be 0x06 + uint8_t protocol_version; // Should be version 1.0, transmitted as 0x10 + uint16_t service_type; // See knx_service_type_t + union + { + struct { + uint8_t first_byte; + uint8_t second_byte; + } bytes; + uint16_t len; + } total_len; // header_len + rest of pkt. This is a bit weird as the spec says this: If the total number of bytes transmitted is greater than 252 bytes, the first “Total Length” byte is set to FF (255). Only in this case the second byte includes additional length information + uint8_t pkt_data[]; // This is of type cemi_msg_t +} knx_ip_pkt_t; + +typedef struct __cemi_addi +{ + uint8_t type_id; + uint8_t len; + uint8_t data[]; +} cemi_addi_t; + +typedef union __address +{ + uint16_t value; + struct + { + uint8_t high; + uint8_t low; + } bytes; + struct __attribute__((packed)) + { + uint8_t line:3; + uint8_t area:5; + uint8_t member; + } ga; + struct __attribute__((packed)) + { + uint8_t line:4; + uint8_t area:4; + uint8_t member; + } pa; + uint8_t array[2]; +} address_t; + +typedef struct __cemi_service +{ + union + { + struct + { + // Struct is reversed due to bit order + uint8_t confirm:1; // 0 = no error, 1 = error + uint8_t ack:1; // 0 = no ack, 1 = ack + uint8_t priority:2; // 0 = system, 1 = high, 2 = urgent/alarm, 3 = normal + uint8_t system_broadcast:1; // 0 = system broadcast, 1 = broadcast + uint8_t repeat:1; // 0 = repeated telegram, 1 = not repeated telegram + uint8_t reserved:1; // always zero + uint8_t frame_type:1; // 0 = extended, 1 = standard + } bits; + uint8_t byte; + } control_1; + union + { + struct + { + // Struct is reversed due to bit order + uint8_t extended_frame_format:4; + uint8_t hop_count:3; + uint8_t dest_addr_type:1; // 0 = individual, 1 = group + } bits; + uint8_t byte; + } control_2; + address_t source; + address_t destination; + uint8_t data_len; // length of data, excluding the tpci byte + struct + { + uint8_t apci:2; // If tpci.comm_type == KNX_COT_UCD or KNX_COT_NCD, then this is apparently control data? + uint8_t tpci_seq_number:4; + uint8_t tpci_comm_type:2; // See knx_communication_type_t + } pci; + uint8_t data[]; +} cemi_service_t; + +typedef struct __cemi_msg +{ + uint8_t message_code; + uint8_t additional_info_len; + union + { +// cemi_addi_t additional_info[]; // Errors in GCC 10.1 + cemi_addi_t additional_info[10]; // Changed to arbitrary number to fix compilation + cemi_service_t service_information; + } data; +} cemi_msg_t; + +typedef enum __config_type +{ + CONFIG_TYPE_UNKNOWN, + CONFIG_TYPE_INT, + CONFIG_TYPE_BOOL, + CONFIG_TYPE_STRING, + CONFIG_TYPE_OPTIONS, + CONFIG_TYPE_GA, +} config_type_t; + +typedef enum __feedback_type +{ + FEEDBACK_TYPE_UNKNOWN, + FEEDBACK_TYPE_INT, + FEEDBACK_TYPE_FLOAT, + FEEDBACK_TYPE_BOOL, + FEEDBACK_TYPE_ACTION, +} feedback_type_t; + +typedef enum __config_flags +{ + CONFIG_FLAGS_NO_FLAGS = 0, + CONFIG_FLAGS_VALUE_SET = 1, +} config_flags_t; + +typedef enum __slot_flags +{ + SLOT_FLAGS_EMPTY = 0, // Empty slots have no flags + SLOT_FLAGS_USED = 1, +} slot_flags_t; + +typedef struct __message +{ + knx_command_type_t ct; + address_t received_on; + uint8_t data_len; + uint8_t *data; +} message_t; + +typedef bool (*enable_condition_t)(void); +typedef void (*callback_fptr_t)(message_t const &msg, void *arg); +typedef void (*feedback_action_fptr_t)(void *arg); + +typedef uint8_t callback_id_t; +#define CALLBACK_ID_MAX UINT8_MAX +typedef uint8_t callback_assignment_id_t; +#define CALLBACK_ASSIGNMENT_ID_MAX UINT8_MAX +typedef uint8_t config_id_t; +typedef uint8_t feedback_id_t; + +typedef struct __option_entry +{ + char const *name; + uint8_t value; +} option_entry_t; + +typedef struct __config +{ + config_type_t type; + String name; + uint8_t offset; + uint8_t len; + enable_condition_t cond; + union { + option_entry_t *options; + } data; +} config_t; + +extern char const *string_defaults[]; +#define STRING_DEFAULT_DO_THIS (string_defaults[0]) +#define STRING_DEFAULT_TRUE (string_defaults[1]) +#define STRING_DEFAULT_FALSE (string_defaults[2]) +#define STRING_DEFAULT_EMPTY (string_defaults[3]) + +typedef struct __feedback_float_options +{ + uint8_t precision; + char const *prefix; + char const *suffix; +} feedback_float_options_t; + +typedef struct __feedback_bool_options +{ + char const *true_text; + char const *false_text; +} feedback_bool_options_t; + +typedef struct __feedback_action_options +{ + void *arg; + char const *btn_text; +} feedback_action_options_t; + +typedef struct __feedback +{ + feedback_type_t type; + String name; + enable_condition_t cond; + void *data; + union { + feedback_bool_options_t bool_options; + feedback_float_options_t float_options; + feedback_action_options_t action_options; + } options; +} feedback_t; + +typedef struct __callback +{ + uint8_t slot_flags; + callback_fptr_t fkt; + enable_condition_t cond; + void *arg; + String name; +} callback_t; + +typedef struct __callback_assignment +{ + uint8_t slot_flags; + address_t address; + callback_id_t callback_id; +} callback_assignment_t; + +// FastPrecisePowf from tasmota/support_float.ino +//extern float FastPrecisePowf(const float x, const float y); + +class ESPKNXIP { + public: + ESPKNXIP(); + void load(); + void start(); + void start(ESP8266WebServer *srv); + void loop(); + + void save_to_eeprom(); + void restore_from_eeprom(); + + callback_id_t callback_register(String name, callback_fptr_t cb, void *arg = nullptr, enable_condition_t cond = nullptr); + callback_assignment_id_t callback_assign(callback_id_t id, address_t val); + void callback_deregister(callback_id_t id); + void callback_unassign(callback_assignment_id_t id); + + void physical_address_set(address_t const &addr); + address_t physical_address_get(); + + // Configuration functions + config_id_t config_register_string(String name, uint8_t len, String _default, enable_condition_t cond = nullptr); + config_id_t config_register_int(String name, int32_t _default, enable_condition_t cond = nullptr); + config_id_t config_register_bool(String name, bool _default, enable_condition_t cond = nullptr); + config_id_t config_register_options(String name, option_entry_t *options, uint8_t _default, enable_condition_t cond = nullptr); + config_id_t config_register_ga(String name, enable_condition_t cond = nullptr); + + String config_get_string(config_id_t id); + int32_t config_get_int(config_id_t id); + bool config_get_bool(config_id_t id); + uint8_t config_get_options(config_id_t id); + address_t config_get_ga(config_id_t id); + + void config_set_string(config_id_t id, String val); + void config_set_int(config_id_t id, int32_t val); + void config_set_bool(config_id_t, bool val); + void config_set_options(config_id_t id, uint8_t val); + void config_set_ga(config_id_t id, address_t const &val); + + // Feedback functions + feedback_id_t feedback_register_int(String name, int32_t *value, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_float(String name, float *value, uint8_t precision = 2, char const *prefix = nullptr, char const *suffix = nullptr, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_bool(String name, bool *value, char const *true_text = nullptr, char const *false_text = nullptr, enable_condition_t cond = nullptr); + feedback_id_t feedback_register_action(String name, feedback_action_fptr_t value, char const *btn_text = nullptr, void *arg = nullptr, enable_condition_t = nullptr); + + // Send functions + void send(address_t const &receiver, knx_command_type_t ct, uint8_t data_len, uint8_t *data); + + void send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit); + void send_2bit(address_t const &receiver, knx_command_type_t ct, uint8_t twobit); + void send_4bit(address_t const &receiver, knx_command_type_t ct, uint8_t fourbit); + void send_1byte_int(address_t const &receiver, knx_command_type_t ct, int8_t val); + void send_1byte_uint(address_t const &receiver, knx_command_type_t ct, uint8_t val); + void send_2byte_int(address_t const &receiver, knx_command_type_t ct, int16_t val); + void send_2byte_uint(address_t const &receiver, knx_command_type_t ct, uint16_t val); + void send_2byte_float(address_t const &receiver, knx_command_type_t ct, float val); + void send_3byte_time(address_t const &receiver, knx_command_type_t ct, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds); + void send_3byte_time(address_t const &receiver, knx_command_type_t ct, time_of_day_t const &time) { send_3byte_time(receiver, ct, time.weekday, time.hours, time.minutes, time.seconds); } + void send_3byte_date(address_t const &receiver, knx_command_type_t ct, uint8_t day, uint8_t month, uint8_t year); + void send_3byte_date(address_t const &receiver, knx_command_type_t ct, date_t const &date) { send_3byte_date(receiver, ct, date.day, date.month, date.year); } + void send_3byte_color(address_t const &receiver, knx_command_type_t ct, uint8_t red, uint8_t green, uint8_t blue); + void send_3byte_color(address_t const &receiver, knx_command_type_t ct, color_t const &color) { send_3byte_color(receiver, ct, color.red, color.green, color.blue); } + void send_4byte_int(address_t const &receiver, knx_command_type_t ct, int32_t val); + void send_4byte_uint(address_t const &receiver, knx_command_type_t ct, uint32_t val); + void send_4byte_float(address_t const &receiver, knx_command_type_t ct, float val); + void send_14byte_string(address_t const &receiver, knx_command_type_t ct, const char *val); + + void write_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_WRITE, bit); } + void write_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_WRITE, twobit); } + void write_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_WRITE, fourbit); } + void write_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_WRITE, val); } + void write_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_WRITE, val); } + void write_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_WRITE, val); } + void write_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_WRITE, val); } + void write_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_WRITE, val); } + void write_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_WRITE, weekday, hours, minutes, seconds); } + void write_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_WRITE, time.weekday, time.hours, time.minutes, time.seconds); } + void write_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_WRITE, day, month, year); } + void write_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_WRITE, date.day, date.month, date.year); } + void write_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_WRITE, red, green, blue); } + void write_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_WRITE, color); } + void write_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_WRITE, val); } + void write_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_WRITE, val); } + void write_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_WRITE, val);} + void write_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_WRITE, val); } + + void answer_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_ANSWER, bit); } + void answer_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_ANSWER, twobit); } + void answer_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_ANSWER, fourbit); } + void answer_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_ANSWER, val); } + void answer_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_ANSWER, weekday, hours, minutes, seconds); } + void answer_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_ANSWER, time.weekday, time.hours, time.minutes, time.seconds); } + void answer_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_ANSWER, day, month, year); } + void answer_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_ANSWER, date.day, date.month, date.year); } + void answer_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_ANSWER, red, green, blue); } + void answer_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_ANSWER, color); } + void answer_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_ANSWER, val); } + void answer_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_ANSWER, val); } + void answer_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_ANSWER, val);} + void answer_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_ANSWER, val); } + + bool data_to_bool(uint8_t *data); + int8_t data_to_1byte_int(uint8_t *data); + uint8_t data_to_1byte_uint(uint8_t *data); + int16_t data_to_2byte_int(uint8_t *data); + uint16_t data_to_2byte_uint(uint8_t *data); + float data_to_2byte_float(uint8_t *data); + color_t data_to_3byte_color(uint8_t *data); + time_of_day_t data_to_3byte_time(uint8_t *data); + date_t data_to_3byte_data(uint8_t *data); + int32_t data_to_4byte_int(uint8_t *data); + uint32_t data_to_4byte_uint(uint8_t *data); + float data_to_4byte_float(uint8_t *data); + + static address_t GA_to_address(uint8_t area, uint8_t line, uint8_t member) + { + // Yes, the order is correct, see the struct definition above + address_t tmp = {.ga={line, area, member}}; + return tmp; + } + + static address_t PA_to_address(uint8_t area, uint8_t line, uint8_t member) + { + // Yes, the order is correct, see the struct definition above + address_t tmp = {.pa={line, area, member}}; + return tmp; + } + + private: + void __start(); + + void __loop_knx(); + + // Webserver functions + void __loop_webserver(); + void __handle_root(); + void __handle_register(); + void __handle_delete(); + void __handle_set(); +#if !DISABLE_EEPROM_BUTTONS + void __handle_eeprom(); +#endif + void __handle_config(); + void __handle_feedback(); +#if !DISABLE_RESTORE_BUTTONS + void __handle_restore(); +#endif +#if !DISABLE_REBOOT_BUTTONS + void __handle_reboot(); +#endif + + void __config_set_flags(config_id_t id, config_flags_t flags); + + void __config_set_string(config_id_t id, String &val); + void __config_set_int(config_id_t id, int32_t val); + void __config_set_bool(config_id_t id, bool val); + void __config_set_options(config_id_t id, uint8_t val); + void __config_set_ga(config_id_t id, address_t const &val); + + bool __callback_is_id_valid(callback_id_t id); + + callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id); + void __callback_delete_assignment(callback_assignment_id_t id); + + //static inline float pow(float a, float b) { return FastPrecisePowf(a, b); } + + ESP8266WebServer *server; + address_t physaddr; + + WiFiUDP udp; + + callback_assignment_id_t registered_callback_assignments; + callback_assignment_id_t free_callback_assignment_slots; + callback_assignment_t callback_assignments[MAX_CALLBACK_ASSIGNMENTS]; + + callback_id_t registered_callbacks; + callback_id_t free_callback_slots; + callback_t callbacks[MAX_CALLBACKS]; + + config_id_t registered_configs; + uint8_t custom_config_data[MAX_CONFIG_SPACE]; + uint8_t custom_config_default_data[MAX_CONFIG_SPACE]; + config_t custom_configs[MAX_CONFIGS]; + + feedback_id_t registered_feedbacks; + feedback_t feedbacks[MAX_FEEDBACKS]; + + uint16_t __ntohs(uint16_t); +}; + +// Global "singleton" object +extern ESPKNXIP knx; + +#endif From e413dcaea2f6dbb1c2a97550626a60b74f645961 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:33:35 +0100 Subject: [PATCH 28/38] Update platformio_tasmota_env.ini --- platformio_tasmota_env.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 7496c858d..e88e37e8a 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -43,7 +43,7 @@ lib_extra_dirs = [env:tasmota-knx] build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_extra_dirs = lib_basic +lib_extra_dirs = lib_basic, lib_div [env:tasmota-sensors] build_flags = ${common.build_flags} -DFIRMWARE_SENSORS From e699c71c78456d0945ed6f52be6bafb882831866 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:34:03 +0100 Subject: [PATCH 29/38] Update platformio_tasmota_env32.ini --- platformio_tasmota_env32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 819b6aa75..cb42e1e72 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -47,7 +47,7 @@ lib_extra_dirs = libesp32 [env:tasmota32-knx] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_extra_dirs = libesp32, lib_basic +lib_extra_dirs = libesp32, lib_basic, lib_div [env:tasmota32-sensors] extends = env:tasmota32 From 0989af6015b20d776996255cb054453fd8e697aa Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 11:39:29 +0100 Subject: [PATCH 30/38] Use only KNX header files no need to include and compile whole KNX library --- tasmota/tasmota_globals.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index e245f3f2f..fa6a4f9fc 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -33,10 +33,10 @@ extern "C" { } #endif -//#ifdef USE_KNX // Enabling this will fail compilation. It has no impact if not used. (20180417) -#include +#include // KNX Header files have to be global else compile fails -> lib/headers +#ifdef USE_KNX void KNX_CB_Action(message_t const &msg, void *arg); -//#endif // USE_KNX +#endif // USE_KNX void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1); char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0'); From 3d48f1374a0f6602b940f65dfb97e05d781b94dc Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 26 Oct 2020 10:47:58 +0000 Subject: [PATCH 31/38] del KNX from lib --- lib/esp-knx-ip-0.5.2/DPT.h | 73 -- lib/esp-knx-ip-0.5.2/LICENSE | 21 - lib/esp-knx-ip-0.5.2/README.md | 94 --- lib/esp-knx-ip-0.5.2/esp-knx-ip-config.cpp | 358 ---------- .../esp-knx-ip-conversion.cpp | 87 --- lib/esp-knx-ip-0.5.2/esp-knx-ip-send.cpp | 201 ------ lib/esp-knx-ip-0.5.2/esp-knx-ip-webserver.cpp | 540 -------------- lib/esp-knx-ip-0.5.2/esp-knx-ip.cpp | 664 ------------------ lib/esp-knx-ip-0.5.2/esp-knx-ip.h | 600 ---------------- .../environment-sensor/environment-sensor.ino | 159 ----- .../examples/sonoff/sonoff.ino | 183 ----- .../examples/static-config/static-config.ino | 142 ---- lib/esp-knx-ip-0.5.2/keywords.txt | 107 --- lib/esp-knx-ip-0.5.2/library.properties | 10 - 14 files changed, 3239 deletions(-) delete mode 100644 lib/esp-knx-ip-0.5.2/DPT.h delete mode 100644 lib/esp-knx-ip-0.5.2/LICENSE delete mode 100644 lib/esp-knx-ip-0.5.2/README.md delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip-config.cpp delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip-conversion.cpp delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip-send.cpp delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip-webserver.cpp delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip.cpp delete mode 100644 lib/esp-knx-ip-0.5.2/esp-knx-ip.h delete mode 100644 lib/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino delete mode 100644 lib/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino delete mode 100644 lib/esp-knx-ip-0.5.2/examples/static-config/static-config.ino delete mode 100644 lib/esp-knx-ip-0.5.2/keywords.txt delete mode 100644 lib/esp-knx-ip-0.5.2/library.properties diff --git a/lib/esp-knx-ip-0.5.2/DPT.h b/lib/esp-knx-ip-0.5.2/DPT.h deleted file mode 100644 index 3529d51af..000000000 --- a/lib/esp-knx-ip-0.5.2/DPT.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -typedef enum __dpt_1_001 -{ - DPT_1_001_OFF = 0x00, - DPT_1_001_ON = 0x01, -} dpt_1_001_t; - -typedef enum __dpt_2_001 -{ - DPT_2_001_NO_OFF = 0b00, - DPT_2_001_NO_ON = 0b01, - DPT_2_001_YES_OFF = 0b10, - DPT_2_001_YES_ON = 0b11, -} dpt_2_001_t; - -typedef enum __dpt_3_007 -{ - DPT_3_007_DECREASE_STOP = 0x00, - DPT_3_007_DECREASE_100 = 0x01, - DPT_3_007_DECREASE_50 = 0x02, - DPT_3_007_DECREASE_25 = 0x03, - DPT_3_007_DECREASE_12 = 0x04, - DPT_3_007_DECREASE_6 = 0x05, - DPT_3_007_DECREASE_3 = 0x06, - DPT_3_007_DECREASE_1 = 0x07, - DPT_3_007_INCREASE_STOP = 0x08, - DPT_3_007_INCREASE_100 = 0x09, - DPT_3_007_INCREASE_50 = 0x0A, - DPT_3_007_INCREASE_25 = 0x0B, - DPT_3_007_INCREASE_12 = 0x0C, - DPT_3_007_INCREASE_6 = 0x0D, - DPT_3_007_INCREASE_3 = 0x0E, - DPT_3_007_INCREASE_1 = 0x0F, -} dpt_3_007_t; - -typedef enum __weekday -{ - DPT_10_001_WEEKDAY_NODAY = 0, - DPT_10_001_WEEKDAY_MONDAY = 1, - DPT_10_001_WEEKDAY_TUESDAY = 2, - DPT_10_001_WEEKDAY_WEDNESDAY = 3, - DPT_10_001_WEEKDAY_THURSDAY = 4, - DPT_10_001_WEEKDAY_FRIDAY = 5, - DPT_10_001_WEEKDAY_SATURDAY = 6, - DPT_10_001_WEEKDAY_SUNDAY = 7, -} weekday_t; - -typedef struct __time_of_day -{ - weekday_t weekday; - uint8_t hours; - uint8_t minutes; - uint8_t seconds; -} time_of_day_t; - -typedef struct __date -{ - uint8_t day; - uint8_t month; - uint8_t year; -} date_t; - -typedef struct __color -{ - uint8_t red; - uint8_t green; - uint8_t blue; -} color_t; diff --git a/lib/esp-knx-ip-0.5.2/LICENSE b/lib/esp-knx-ip-0.5.2/LICENSE deleted file mode 100644 index 80f432a97..000000000 --- a/lib/esp-knx-ip-0.5.2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Nico Weichbrodt - -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. \ No newline at end of file diff --git a/lib/esp-knx-ip-0.5.2/README.md b/lib/esp-knx-ip-0.5.2/README.md deleted file mode 100644 index a93c09192..000000000 --- a/lib/esp-knx-ip-0.5.2/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# ESP-KNX-IP # - -This is a library for the ESP8266 to enable KNXnet/IP communication. It uses UDP multicast on 224.0.23.12:3671. -It is intended to be used with the Arduino platform for the ESP8266. - -## How to use ## - -The library is under development. API may change multiple times in the future. - -API documentation is available [here](https://github.com/envy/esp-knx-ip/wiki/API) - -A simple example: - -```c++ -#include - -const char* ssid = "my-ssid"; // your network SSID (name) -const char* pass = "my-pw"; // your network password - -config_id_t my_GA; -config_id_t param_id; - -int8_t some_var = 0; - -void setup() -{ - // Register a callback that is called when a configurable group address is receiving a telegram - knx.register_callback("Set/Get callback", my_callback); - knx.register_callback("Write callback", my_other_callback); - - int default_val = 21; - param_id = knx.config_register_int("My Parameter", default_val); - - // Register a configurable group address for sending out answers - my_GA = knx.config_register_ga("Answer GA"); - - knx.load(); // Try to load a config from EEPROM - - WiFi.begin(ssid, pass); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - } - - knx.start(); // Start everything. Must be called after WiFi connection has been established -} - -void loop() -{ - knx.loop(); -} - - -void my_callback(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_WRITE: - // Save received data - some_var = knx.data_to_1byte_int(msg.data); - break; - case KNX_CT_READ: - // Answer with saved data - knx.answer1ByteInt(msg.received_on, some_var); - break; - } -} - -void my_other_callback(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_WRITE: - // Write an answer somewhere else - int value = knx.config_get_int(param_id); - address_t ga = knx.config_get_ga(my_GA); - knx.answer1ByteInt(ga, (int8_t)value); - break; - } -} - -``` - -## How to configure (buildtime) ## - -Open the `esp-knx-ip.h` and take a look at the config options at the top inside the block marked `CONFIG` - -## How to configure (runtime) ## - -Simply visit the IP of your ESP with a webbrowser. You can configure the following: -* KNX physical address -* Which group address should trigger which callback -* Which group address are to be used by the program (e.g. for status replies) - -The configuration is dynamically generated from the code. diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip-config.cpp b/lib/esp-knx-ip-0.5.2/esp-knx-ip-config.cpp deleted file mode 100644 index 8d2b7b39d..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip-config.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#include "esp-knx-ip.h" - -/** - * Physical address functions - */ - -void ESPKNXIP::physical_address_set(address_t const &addr) -{ - physaddr = addr; -} - -address_t ESPKNXIP::physical_address_get() -{ - return physaddr; -} - -/** - * Configuration functions start here - */ -config_id_t ESPKNXIP::config_register_string(String name, uint8_t len, String _default, enable_condition_t cond) -{ - if (registered_configs >= MAX_CONFIGS) - return -1; - - if (_default.length() >= len) - return -1; - - config_id_t id = registered_configs; - - custom_configs[id].name = name; - custom_configs[id].type = CONFIG_TYPE_STRING; - custom_configs[id].len = sizeof(uint8_t) + len; - custom_configs[id].cond = cond; - if (id == 0) - custom_configs[id].offset = 0; - else - custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; - - __config_set_string(id, _default); - - registered_configs++; - - DEBUG_PRINT("Registered config >"); - DEBUG_PRINT(name); - DEBUG_PRINT("< @ "); - DEBUG_PRINT(id); - DEBUG_PRINT("/string["); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT("+"); - DEBUG_PRINT(custom_configs[id].len); - DEBUG_PRINTLN("]"); - - return id; -} - -config_id_t ESPKNXIP::config_register_int(String name, int32_t _default, enable_condition_t cond) -{ - if (registered_configs >= MAX_CONFIGS) - return -1; - - config_id_t id = registered_configs; - - custom_configs[id].name = name; - custom_configs[id].type = CONFIG_TYPE_INT; - custom_configs[id].len = sizeof(uint8_t) + sizeof(int32_t); - custom_configs[id].cond = cond; - if (id == 0) - custom_configs[id].offset = 0; - else - custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; - - __config_set_int(id, _default); - - registered_configs++; - - DEBUG_PRINT("Registered config >"); - DEBUG_PRINT(name); - DEBUG_PRINT("< @ "); - DEBUG_PRINT(id); - DEBUG_PRINT("/int["); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT("+"); - DEBUG_PRINT(custom_configs[id].len); - DEBUG_PRINTLN("]"); - - return id; -} - -config_id_t ESPKNXIP::config_register_bool(String name, bool _default, enable_condition_t cond) -{ - if (registered_configs >= MAX_CONFIGS) - return -1; - - config_id_t id = registered_configs; - - custom_configs[id].name = name; - custom_configs[id].type = CONFIG_TYPE_BOOL; - custom_configs[id].len = sizeof(uint8_t) + sizeof(uint8_t); - custom_configs[id].cond = cond; - if (id == 0) - custom_configs[id].offset = 0; - else - custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; - - __config_set_bool(id, _default); - - registered_configs++; - - DEBUG_PRINT("Registered config >"); - DEBUG_PRINT(name); - DEBUG_PRINT("< @ "); - DEBUG_PRINT(id); - DEBUG_PRINT("/bool["); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT("+"); - DEBUG_PRINT(custom_configs[id].len); - DEBUG_PRINTLN("]"); - - return id; -} - -config_id_t ESPKNXIP::config_register_options(String name, option_entry_t *options, uint8_t _default, enable_condition_t cond) -{ - if (registered_configs >= MAX_CONFIGS) - return -1; - - if (options == nullptr || options->name == nullptr) - return -1; - - config_id_t id = registered_configs; - - custom_configs[id].name = name; - custom_configs[id].type = CONFIG_TYPE_OPTIONS; - custom_configs[id].len = sizeof(uint8_t) + sizeof(uint8_t); - custom_configs[id].cond = cond; - if (id == 0) - custom_configs[id].offset = 0; - else - custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; - - custom_configs[id].data.options = options; - - __config_set_options(id, _default); - - registered_configs++; - - DEBUG_PRINT("Registered config >"); - DEBUG_PRINT(name); - DEBUG_PRINT("< @ "); - DEBUG_PRINT(id); - DEBUG_PRINT("/opt["); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT("+"); - DEBUG_PRINT(custom_configs[id].len); - DEBUG_PRINTLN("]"); - - return id; -} - -config_id_t ESPKNXIP::config_register_ga(String name, enable_condition_t cond) -{ - if (registered_configs >= MAX_CONFIGS) - return -1; - - config_id_t id = registered_configs; - - custom_configs[id].name = name; - custom_configs[id].type = CONFIG_TYPE_GA; - custom_configs[id].len = sizeof(uint8_t) + sizeof(address_t); - custom_configs[id].cond = cond; - if (id == 0) - custom_configs[id].offset = 0; - else - custom_configs[id].offset = custom_configs[id - 1].offset + custom_configs[id - 1].len; - - address_t t; - t.value = 0; - __config_set_ga(id, t); - - registered_configs++; - - DEBUG_PRINT("Registered config >"); - DEBUG_PRINT(name); - DEBUG_PRINT("< @ "); - DEBUG_PRINT(id); - DEBUG_PRINT("/ga["); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT("+"); - DEBUG_PRINT(custom_configs[id].len); - DEBUG_PRINTLN("]"); - - return id; -} - -void ESPKNXIP::__config_set_flags(config_id_t id, config_flags_t flags) -{ - DEBUG_PRINT("Setting flag @ "); - DEBUG_PRINT(custom_configs[id].offset); - DEBUG_PRINT(" to "); - DEBUG_PRINT(custom_config_data[custom_configs[id].offset], BIN); - DEBUG_PRINT(" | "); - DEBUG_PRINT(flags, BIN); - custom_config_data[custom_configs[id].offset] |= (uint8_t)flags; - DEBUG_PRINT(" = "); - DEBUG_PRINTLN(custom_config_data[custom_configs[id].offset], BIN); -} - -void ESPKNXIP::config_set_string(config_id_t id, String val) -{ - if (id >= registered_configs) - return; - if (custom_configs[id].type != CONFIG_TYPE_STRING) - return; - if (val.length() >= custom_configs[id].len) - return; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_string(id, val); -} - -void ESPKNXIP::__config_set_string(config_id_t id, String &val) -{ - memcpy(&custom_config_data[custom_configs[id].offset + sizeof(uint8_t)], val.c_str(), val.length()+1); -} - -void ESPKNXIP::config_set_int(config_id_t id, int32_t val) -{ - if (id >= registered_configs) - return; - if (custom_configs[id].type != CONFIG_TYPE_INT) - return; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_int(id, val); -} - -void ESPKNXIP::__config_set_int(config_id_t id, int32_t val) -{ - // This does not work for some reason: - // Could be due to pointer alignment - //int32_t *v = (int32_t *)(custom_config_data + custom_configs[id].offset); - //*v = val; - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] = (uint8_t)((val & 0xFF000000) >> 24); - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] = (uint8_t)((val & 0x00FF0000) >> 16); - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 2] = (uint8_t)((val & 0x0000FF00) >> 8); - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 3] = (uint8_t)((val & 0x000000FF) >> 0); -} - -void ESPKNXIP::config_set_bool(config_id_t id, bool val) -{ - if (id >= registered_configs) - return; - if (custom_configs[id].type != CONFIG_TYPE_BOOL) - return; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_bool(id, val); -} - -void ESPKNXIP::__config_set_bool(config_id_t id, bool val) -{ - custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] = val ? 1 : 0; -} - -void ESPKNXIP::config_set_options(config_id_t id, uint8_t val) -{ - if (id >= registered_configs) - return; - if (custom_configs[id].type != CONFIG_TYPE_OPTIONS) - return; - - option_entry_t *cur = custom_configs[id].data.options; - while (cur->name != nullptr) - { - if (cur->value == val) - { - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_options(id, val); - break; - } - cur++; - } -} - -void ESPKNXIP::__config_set_options(config_id_t id, uint8_t val) -{ - custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] = val; -} - -void ESPKNXIP::config_set_ga(config_id_t id, address_t const &val) -{ - if (id >= registered_configs) - return; - if (custom_configs[id].type != CONFIG_TYPE_GA) - return; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_ga(id, val); -} - -void ESPKNXIP::__config_set_ga(config_id_t id, address_t const &val) -{ - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] = val.bytes.high; - custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] = val.bytes.low; -} - -String ESPKNXIP::config_get_string(config_id_t id) -{ - if (id >= registered_configs) - return String(""); - - return String((char *)&custom_config_data[custom_configs[id].offset + sizeof(uint8_t)]); -} - -int32_t ESPKNXIP::config_get_int(config_id_t id) -{ - if (id >= registered_configs) - return 0; - - int32_t v = (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0] << 24) + - (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1] << 16) + - (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 2] << 8) + - (custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 3] << 0); - return v; -} - -bool ESPKNXIP::config_get_bool(config_id_t id) -{ - if (id >= registered_configs) - return false; - - return custom_config_data[custom_configs[id].offset + sizeof(uint8_t)] != 0; -} - -uint8_t ESPKNXIP::config_get_options(config_id_t id) -{ - if (id >= registered_configs) - return false; - - return custom_config_data[custom_configs[id].offset + sizeof(uint8_t)]; -} - -address_t ESPKNXIP::config_get_ga(config_id_t id) -{ - address_t t; - if (id >= registered_configs) - { - t.value = 0; - return t; - } - - t.bytes.high = custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 0]; - t.bytes.low = custom_config_data[custom_configs[id].offset + sizeof(uint8_t) + 1]; - - return t; -} diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip-conversion.cpp b/lib/esp-knx-ip-0.5.2/esp-knx-ip-conversion.cpp deleted file mode 100644 index 9dc2fd563..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip-conversion.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#include "esp-knx-ip.h" - -/** - * Conversion functions - */ - -bool ESPKNXIP::data_to_bool(uint8_t *data) -{ - return (data[0] & 0x01) == 1 ? true : false; -} - -int8_t ESPKNXIP::data_to_1byte_int(uint8_t *data) -{ - return (int8_t)data[1]; -} - -uint8_t ESPKNXIP::data_to_1byte_uint(uint8_t *data) -{ - return data[1]; -} - -int16_t ESPKNXIP::data_to_2byte_int(uint8_t *data) -{ - return (int16_t)((data[1] << 8) | data[2]); -} - -uint16_t ESPKNXIP::data_to_2byte_uint(uint8_t *data) -{ - return (uint16_t)((data[1] << 8) | data[2]); -} - -float ESPKNXIP::data_to_2byte_float(uint8_t *data) -{ - //uint8_t sign = (data[1] & 0b10000000) >> 7; - uint8_t expo = (data[1] & 0b01111000) >> 3; - int16_t mant = ((data[1] & 0b10000111) << 8) | data[2]; - return 0.01f * mant * pow(2, expo); -} - -time_of_day_t ESPKNXIP::data_to_3byte_time(uint8_t *data) -{ - time_of_day_t time; - time.weekday = (weekday_t)((data[1] & 0b11100000) >> 5); - time.hours = (data[1] & 0b00011111); - time.minutes = (data[2] & 0b00111111); - time.seconds = (data[3] & 0b00111111); - return time; -} - -date_t ESPKNXIP::data_to_3byte_data(uint8_t *data) -{ - date_t date; - date.day = (data[1] & 0b00011111); - date.month = (data[2] & 0b00001111); - date.year = (data[3] & 0b01111111); - return date; -} - -color_t ESPKNXIP::data_to_3byte_color(uint8_t *data) -{ - color_t color; - color.red = data[1]; - color.green = data[2]; - color.blue = data[3]; - return color; -} - -int32_t ESPKNXIP::data_to_4byte_int(uint8_t *data) -{ - return (int32_t)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) | (data[4] << 0)); -} - -uint32_t ESPKNXIP::data_to_4byte_uint(uint8_t *data) -{ - return (uint32_t)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) | (data[4] << 0)); -} - -float ESPKNXIP::data_to_4byte_float(uint8_t *data) -{ - return (float)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) |data[4]); -} \ No newline at end of file diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip-send.cpp b/lib/esp-knx-ip-0.5.2/esp-knx-ip-send.cpp deleted file mode 100644 index e71e5954c..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip-send.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#include "esp-knx-ip.h" - -/** - * Send functions - */ - -void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t data_len, uint8_t *data) -{ - if (receiver.value == 0) - return; - -#if SEND_CHECKSUM - uint32_t len = 6 + 2 + 8 + data_len + 1; // knx_pkt + cemi_msg + cemi_service + data + checksum -#else - uint32_t len = 6 + 2 + 8 + data_len; // knx_pkt + cemi_msg + cemi_service + data -#endif - DEBUG_PRINT(F("Creating packet with len ")); - DEBUG_PRINTLN(len) - uint8_t buf[len]; - knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf; - knx_pkt->header_len = 0x06; - knx_pkt->protocol_version = 0x10; - knx_pkt->service_type = __ntohs(KNX_ST_ROUTING_INDICATION); - knx_pkt->total_len.len = __ntohs(len); - cemi_msg_t *cemi_msg = (cemi_msg_t *)knx_pkt->pkt_data; - cemi_msg->message_code = KNX_MT_L_DATA_IND; - cemi_msg->additional_info_len = 0; - cemi_service_t *cemi_data = &cemi_msg->data.service_information; - cemi_data->control_1.bits.confirm = 0; -//cemi_data->control_1.bits.ack = 1; - cemi_data->control_1.bits.ack = 0; // ask for ACK? 0-no 1-yes - cemi_data->control_1.bits.priority = B11; - cemi_data->control_1.bits.system_broadcast = 0x01; - cemi_data->control_1.bits.repeat = 0x01; // 0 = repeated telegram, 1 = not repeated telegram - cemi_data->control_1.bits.reserved = 0; - cemi_data->control_1.bits.frame_type = 0x01; - cemi_data->control_2.bits.extended_frame_format = 0x00; - cemi_data->control_2.bits.hop_count = 0x06; - cemi_data->control_2.bits.dest_addr_type = 0x01; - cemi_data->source = physaddr; - cemi_data->destination = receiver; - //cemi_data->destination.bytes.high = (area << 3) | line; - //cemi_data->destination.bytes.low = member; - cemi_data->data_len = data_len; - cemi_data->pci.apci = (ct & 0x0C) >> 2; -//cemi_data->pci.apci = KNX_COT_NCD_ACK; - cemi_data->pci.tpci_seq_number = 0x00; - cemi_data->pci.tpci_comm_type = KNX_COT_UDP; // Type of communication: DATA PACKAGE or CONTROL DATA -//cemi_data->pci.tpci_comm_type = KNX_COT_NCD; // Type of communication: DATA PACKAGE or CONTROL DATA - memcpy(cemi_data->data, data, data_len); -//cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((KNX_COT_NCD_ACK & 0x03) << 6); - cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((ct & 0x03) << 6); - -#if SEND_CHECKSUM - // Calculate checksum, which is just XOR of all bytes - uint8_t cs = buf[0] ^ buf[1]; - for (uint32_t i = 2; i < len - 1; ++i) - { - cs ^= buf[i]; - } - buf[len - 1] = cs; -#endif - -#ifdef ESP_KNX_DEBUG - DEBUG_PRINT(F("Sending packet:")); - for (int i = 0; i < len; ++i) - { - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINT(buf[i], 16); - } - DEBUG_PRINTLN(F("")); -#endif - - udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); - udp.write(buf, len); - udp.endPacket(); - -} - -void ESPKNXIP::send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit) -{ - uint8_t buf[] = {(uint8_t)(bit & 0b00000001)}; - send(receiver, ct, 1, buf); -} - -void ESPKNXIP::send_2bit(address_t const &receiver, knx_command_type_t ct, uint8_t twobit) -{ - uint8_t buf[] = {(uint8_t)(twobit & 0b00000011)}; - send(receiver, ct, 1, buf); -} - -void ESPKNXIP::send_4bit(address_t const &receiver, knx_command_type_t ct, uint8_t fourbit) -{ - uint8_t buf[] = {(uint8_t)(fourbit & 0b00001111)}; - send(receiver, ct, 1, buf); -} - -void ESPKNXIP::send_1byte_int(address_t const &receiver, knx_command_type_t ct, int8_t val) -{ - uint8_t buf[] = {0x00, (uint8_t)val}; - send(receiver, ct, 2, buf); -} - -void ESPKNXIP::send_1byte_uint(address_t const &receiver, knx_command_type_t ct, uint8_t val) -{ - uint8_t buf[] = {0x00, val}; - send(receiver, ct, 2, buf); -} - -void ESPKNXIP::send_2byte_int(address_t const &receiver, knx_command_type_t ct, int16_t val) -{ - uint8_t buf[] = {0x00, (uint8_t)(val >> 8), (uint8_t)(val & 0x00FF)}; - send(receiver, ct, 3, buf); -} - -void ESPKNXIP::send_2byte_uint(address_t const &receiver, knx_command_type_t ct, uint16_t val) -{ - uint8_t buf[] = {0x00, (uint8_t)(val >> 8), (uint8_t)(val & 0x00FF)}; - send(receiver, ct, 3, buf); -} - -void ESPKNXIP::send_2byte_float(address_t const &receiver, knx_command_type_t ct, float val) -{ - float v = val * 100.0f; - int e = 0; - for (; v < -2048.0f; v /= 2) - ++e; - for (; v > 2047.0f; v /= 2) - ++e; - long m = (long)round(v) & 0x7FF; - short msb = (short) (e << 3 | m >> 8); - if (val < 0.0f) - msb |= 0x80; - uint8_t buf[] = {0x00, (uint8_t)msb, (uint8_t)m}; - send(receiver, ct, 3, buf); -} - -void ESPKNXIP::send_3byte_time(address_t const &receiver, knx_command_type_t ct, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) -{ - weekday <<= 5; - uint8_t buf[] = {0x00, (uint8_t)(((weekday << 5) & 0xE0) | (hours & 0x1F)), (uint8_t)(minutes & 0x3F), (uint8_t)(seconds & 0x3F)}; - send(receiver, ct, 4, buf); -} - -void ESPKNXIP::send_3byte_date(address_t const &receiver, knx_command_type_t ct, uint8_t day, uint8_t month, uint8_t year) -{ - uint8_t buf[] = {0x00, (uint8_t)(day & 0x1F), (uint8_t)(month & 0x0F), year}; - send(receiver, ct, 4, buf); -} - -void ESPKNXIP::send_3byte_color(address_t const &receiver, knx_command_type_t ct, uint8_t red, uint8_t green, uint8_t blue) -{ - uint8_t buf[] = {0x00, red, green, blue}; - send(receiver, ct, 4, buf); -} - -void ESPKNXIP::send_4byte_int(address_t const &receiver, knx_command_type_t ct, int32_t val) -{ - uint8_t buf[] = {0x00, - (uint8_t)((val & 0xFF000000) >> 24), - (uint8_t)((val & 0x00FF0000) >> 16), - (uint8_t)((val & 0x0000FF00) >> 8), - (uint8_t)((val & 0x000000FF) >> 0)}; - send(receiver, ct, 5, buf); -} - -void ESPKNXIP::send_4byte_uint(address_t const &receiver, knx_command_type_t ct, uint32_t val) -{ - uint8_t buf[] = {0x00, - (uint8_t)((val & 0xFF000000) >> 24), - (uint8_t)((val & 0x00FF0000) >> 16), - (uint8_t)((val & 0x0000FF00) >> 8), - (uint8_t)((val & 0x000000FF) >> 0)}; - send(receiver, ct, 5, buf); -} - -void ESPKNXIP::send_4byte_float(address_t const &receiver, knx_command_type_t ct, float val) -{ - uint8_t buf[] = {0x00, ((uint8_t *)&val)[3], ((uint8_t *)&val)[2], ((uint8_t *)&val)[1], ((uint8_t *)&val)[0]}; - send(receiver, ct, 5, buf); -} - -void ESPKNXIP::send_14byte_string(address_t const &receiver, knx_command_type_t ct, const char *val) -{ - // DPT16 strings are always 14 bytes long, however the data array is one larger due to the telegram structure. - // The first byte needs to be zero, string start after that. - uint8_t buf[15] = {0x00}; - int len = strlen(val); - if (len > 14) - { - len = 14; - } - memcpy(buf+1, val, len); - send(receiver, ct, 15, buf); -} diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip-webserver.cpp b/lib/esp-knx-ip-0.5.2/esp-knx-ip-webserver.cpp deleted file mode 100644 index bdbc013fd..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip-webserver.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#include "esp-knx-ip.h" - -void ESPKNXIP::__handle_root() -{ - String m = F(""); -#if USE_BOOTSTRAP - m += F(""); - m += F(""); -#endif - m += F("
"); - m += F("

ESP KNX

"); - - // Feedback - - if (registered_feedbacks > 0) - { - m += F("

Feedback

"); - for (feedback_id_t i = 0; i < registered_feedbacks; ++i) - { - if (feedbacks[i].cond && !feedbacks[i].cond()) - { - continue; - } - m += F("
"); - m += F("
"); - m += F("
"); - m += feedbacks[i].name; - m += F("
"); - switch (feedbacks[i].type) - { - case FEEDBACK_TYPE_INT: - m += F(""); - m += String(*(int32_t *)feedbacks[i].data); - m += F(""); - break; - case FEEDBACK_TYPE_FLOAT: - m += F(""); - m += feedbacks[i].options.float_options.prefix; - m += String(*(float *)feedbacks[i].data, feedbacks[i].options.float_options.precision); - m += feedbacks[i].options.float_options.suffix; - m += F(""); - break; - case FEEDBACK_TYPE_BOOL: - m += F(""); - m += (*(bool *)feedbacks[i].data) ? F("True") : F("False"); - m += F(""); - break; - case FEEDBACK_TYPE_ACTION: - m += F("
"); - break; - } - m += F("
"); - m += F("
"); - } - } - - if (registered_callbacks > 0) - m += F("

Callbacks

"); - - if (registered_callback_assignments > 0) - { - for (uint8_t i = 0; i < registered_callback_assignments; ++i) - { - // Skip empty slots - if ((callback_assignments[i].slot_flags & SLOT_FLAGS_USED) == 0) - { - continue; - } - // Skip disabled callbacks - if (callbacks[callback_assignments[i].callback_id].cond && !callbacks[callback_assignments[i].callback_id].cond()) - { - continue; - } - address_t &addr = callback_assignments[i].address; - m += F("
"); - m += F("
"); - m += F("
"); - m += addr.ga.area; - m += F("/"); - m += addr.ga.line; - m += F("/"); - m += addr.ga.member; - m += F(""); - m += F(""); - m += callbacks[callback_assignments[i].callback_id].name; - m += F("
"); - m += F("
"); - m += F("
"); - m += F("
"); - } - } - - if (registered_callbacks > 0) - { - m += F("
"); - m += F("
"); - m += F(""); - m += F("
/
"); - m += F(""); - m += F("
/
"); - m += F(""); - m += F("
->
"); - m += F(""); - m += F("
"); - m += F("
"); - m += F("
"); - } - - m += F("

Configuration

"); - - // Physical address - m += F("
"); - m += F("
"); - m += F("
Physical address
"); - m += F(""); - m += F("
.
"); - m += F(""); - m += F("
.
"); - m += F(""); - m += F("
"); - m += F("
"); - m += F("
"); - - if (registered_configs > 0) - { - for (config_id_t i = 0; i < registered_configs; ++i) - { - // Check if this config option has a enable condition and if so check that condition - if (custom_configs[i].cond && !custom_configs[i].cond()) - continue; - - m += F("
"); - m += F("
"); - m += F("
"); - m += custom_configs[i].name; - m += F("
"); - - switch (custom_configs[i].type) - { - case CONFIG_TYPE_STRING: - m += F(""); - break; - case CONFIG_TYPE_INT: - m += F(""); - break; - case CONFIG_TYPE_BOOL: - m += F("
"); - m += F(""); - m += F("
"); - break; - case CONFIG_TYPE_OPTIONS: - { - m += F(""); - break; - } - case CONFIG_TYPE_GA: - address_t a = config_get_ga(i); - m += F(""); - m += F("
/
"); - m += F(""); - m += F("
/
"); - m += F(""); - break; - } - m += F(""); - m += F("
"); - m += F("
"); - m += F("
"); - } - } - -#if !(DISABLE_EEPROM_BUTTONS && DISABLE_RESTORE_BUTTON && DISABLE_REBOOT_BUTTON) - // EEPROM save and restore - m += F("
"); - // Save to EEPROM -#if !DISABLE_EEPROM_BUTTONS - m += F("
"); - m += F("
"); - m += F(""); - m += F(""); - m += F("
"); - m += F("
"); - // Restore from EEPROM - m += F("
"); - m += F("
"); - m += F(""); - m += F(""); - m += F("
"); - m += F("
"); -#endif -#if !DISABLE_RESTORE_BUTTON - // Load Defaults - m += F("
"); - m += F("
"); - m += F(""); - m += F("
"); - m += F("
"); -#endif -#if !DISABLE_REBOOT_BUTTON - // Reboot - m += F("
"); - m += F("
"); - m += F(""); - m += F("
"); - m += F("
"); -#endif - m += F("
"); // row -#endif - - // End of page - m += F("
"); - server->send(200, F("text/html"), m); -} - -void ESPKNXIP::__handle_register() -{ - DEBUG_PRINTLN(F("Register called")); - if (server->hasArg(F("area")) && server->hasArg(F("line")) && server->hasArg(F("member")) && server->hasArg(F("cb"))) - { - uint8_t area = server->arg(F("area")).toInt(); - uint8_t line = server->arg(F("line")).toInt(); - uint8_t member = server->arg(F("member")).toInt(); - callback_id_t cb = (callback_id_t)server->arg(F("cb")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(area); - DEBUG_PRINT(F("/")); - DEBUG_PRINT(line); - DEBUG_PRINT(F("/")); - DEBUG_PRINT(member); - DEBUG_PRINT(F("/")); - DEBUG_PRINT(cb); - DEBUG_PRINTLN(F("")); - - if (area > 31 || line > 7) - { - DEBUG_PRINTLN(F("Area or Line wrong")); - goto end; - } - - if (!__callback_is_id_valid(cb)) - { - DEBUG_PRINTLN(F("Invalid callback id")); - goto end; - } - address_t ga = {.ga={line, area, member}}; - __callback_register_assignment(ga, cb); - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} - -void ESPKNXIP::__handle_delete() -{ - DEBUG_PRINTLN(F("Delete called")); - if (server->hasArg(F("id"))) - { - callback_assignment_id_t id = (callback_assignment_id_t)server->arg(F("id")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(id); - DEBUG_PRINTLN(F("")); - - if (id >= registered_callback_assignments || (callback_assignments[id].slot_flags & SLOT_FLAGS_USED) == 0) - { - DEBUG_PRINTLN(F("ID wrong")); - goto end; - } - - __callback_delete_assignment(id); - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} - -void ESPKNXIP::__handle_set() -{ - DEBUG_PRINTLN(F("Set called")); - if (server->hasArg(F("area")) && server->hasArg(F("line")) && server->hasArg(F("member"))) - { - uint8_t area = server->arg(F("area")).toInt(); - uint8_t line = server->arg(F("line")).toInt(); - uint8_t member = server->arg(F("member")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(area); - DEBUG_PRINT(F(".")); - DEBUG_PRINT(line); - DEBUG_PRINT(F(".")); - DEBUG_PRINT(member); - DEBUG_PRINTLN(F("")); - - if (area > 31 || line > 7) - { - DEBUG_PRINTLN(F("Area or Line wrong")); - goto end; - } - - physaddr.bytes.high = (area << 4) | line; - physaddr.bytes.low = member; - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} - -void ESPKNXIP::__handle_config() -{ - DEBUG_PRINTLN(F("Config called")); - if (server->hasArg(F("id"))) - { - config_id_t id = server->arg(F("id")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(id); - DEBUG_PRINTLN(F("")); - - if (id < 0 || id >= registered_configs) - { - DEBUG_PRINTLN(F("ID wrong")); - goto end; - } - - switch (custom_configs[id].type) - { - case CONFIG_TYPE_STRING: - { - String v = server->arg(F("value")); - if (v.length() >= custom_configs[id].len) - goto end; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_string(id, v); - break; - } - case CONFIG_TYPE_INT: - { - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_int(id, server->arg(F("value")).toInt()); - break; - } - case CONFIG_TYPE_BOOL: - { - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_bool(id, server->arg(F("value")).compareTo(F("on")) == 0); - break; - } - case CONFIG_TYPE_OPTIONS: - { - uint8_t val = (uint8_t)server->arg(F("value")).toInt(); - DEBUG_PRINT(F("Value: ")); - DEBUG_PRINTLN(val); - config_set_options(id, val); - break; - } - case CONFIG_TYPE_GA: - { - uint8_t area = server->arg(F("area")).toInt(); - uint8_t line = server->arg(F("line")).toInt(); - uint8_t member = server->arg(F("member")).toInt(); - if (area > 31 || line > 7) - { - DEBUG_PRINTLN(F("Area or Line wrong")); - goto end; - } - address_t tmp; - tmp.bytes.high = (area << 3) | line; - tmp.bytes.low = member; - __config_set_flags(id, CONFIG_FLAGS_VALUE_SET); - __config_set_ga(id, tmp); - break; - } - } - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} - -void ESPKNXIP::__handle_feedback() -{ -DEBUG_PRINTLN(F("Feedback called")); - if (server->hasArg(F("id"))) - { - config_id_t id = server->arg(F("id")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(id); - DEBUG_PRINTLN(F("")); - - if (id < 0 || id >= registered_feedbacks) - { - DEBUG_PRINTLN(F("ID wrong")); - goto end; - } - - switch (feedbacks[id].type) - { - case FEEDBACK_TYPE_ACTION: - { - feedback_action_fptr_t func = (feedback_action_fptr_t)feedbacks[id].data; - void *arg = feedbacks[id].options.action_options.arg; - func(arg); - break; - } - default: - DEBUG_PRINTLN(F("Feedback has no action")); - break; - } - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} - -#if !DISABLE_RESTORE_BUTTONS -void ESPKNXIP::__handle_restore() -{ - DEBUG_PRINTLN(F("Restore called")); - memcpy(custom_config_data, custom_config_default_data, MAX_CONFIG_SPACE); -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} -#endif - -#if !DISABLE_REBOOT_BUTTONS -void ESPKNXIP::__handle_reboot() -{ - DEBUG_PRINTLN(F("Rebooting!")); - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); - delay(1000); - ESP.restart(); - //while(1); -} -#endif - -#if !DISABLE_EEPROM_BUTTONS -void ESPKNXIP::__handle_eeprom() -{ - DEBUG_PRINTLN(F("EEPROM called")); - if (server->hasArg(F("mode"))) - { - uint8_t mode = server->arg(F("mode")).toInt(); - - DEBUG_PRINT(F("Got args: ")); - DEBUG_PRINT(mode); - DEBUG_PRINTLN(F("")); - - if (mode == 1) - { - // save - save_to_eeprom(); - } - else if (mode == 2) - { - // restore - restore_from_eeprom(); - } - } -end: - server->sendHeader(F("Location"),F(__ROOT_PATH)); - server->send(302); -} -#endif diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip.cpp b/lib/esp-knx-ip-0.5.2/esp-knx-ip.cpp deleted file mode 100644 index 35cbb2161..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#include "esp-knx-ip.h" - -char const *string_defaults[] = -{ - "Do this", - "True", - "False", - "" -}; - -ESPKNXIP::ESPKNXIP() : server(nullptr), - registered_callback_assignments(0), - free_callback_assignment_slots(0), - registered_callbacks(0), - free_callback_slots(0), - registered_configs(0), - registered_feedbacks(0) -{ - DEBUG_PRINTLN(); - DEBUG_PRINTLN("ESPKNXIP starting up"); - // Default physical address is 1.1.0 - physaddr.bytes.high = (/*area*/1 << 4) | /*line*/1; - physaddr.bytes.low = /*member*/0; - memset(callback_assignments, 0, MAX_CALLBACK_ASSIGNMENTS * sizeof(callback_assignment_t)); - memset(callbacks, 0, MAX_CALLBACKS * sizeof(callback_fptr_t)); - memset(custom_config_data, 0, MAX_CONFIG_SPACE * sizeof(uint8_t)); - memset(custom_config_default_data, 0, MAX_CONFIG_SPACE * sizeof(uint8_t)); - memset(custom_configs, 0, MAX_CONFIGS * sizeof(config_t)); -} - -void ESPKNXIP::load() -{ - memcpy(custom_config_default_data, custom_config_data, MAX_CONFIG_SPACE); - EEPROM.begin(EEPROM_SIZE); - restore_from_eeprom(); -} - -void ESPKNXIP::start(ESP8266WebServer *srv) -{ - server = srv; - __start(); -} - -void ESPKNXIP::start() -{ - server = new ESP8266WebServer(80); - __start(); -} - -void ESPKNXIP::__start() -{ - if (server != nullptr) - { - server->on(ROOT_PREFIX, [this](){ - __handle_root(); - }); - server->on(__ROOT_PATH, [this](){ - __handle_root(); - }); - server->on(__REGISTER_PATH, [this](){ - __handle_register(); - }); - server->on(__DELETE_PATH, [this](){ - __handle_delete(); - }); - server->on(__PHYS_PATH, [this](){ - __handle_set(); - }); -#if !DISABLE_EEPROM_BUTTONS - server->on(__EEPROM_PATH, [this](){ - __handle_eeprom(); - }); -#endif - server->on(__CONFIG_PATH, [this](){ - __handle_config(); - }); - server->on(__FEEDBACK_PATH, [this](){ - __handle_feedback(); - }); -#if !DISABLE_RESTORE_BUTTON - server->on(__RESTORE_PATH, [this](){ - __handle_restore(); - }); -#endif -#if !DISABLE_REBOOT_BUTTON - server->on(__REBOOT_PATH, [this](){ - __handle_reboot(); - }); -#endif - server->begin(); - } - udp.beginMulticast(WiFi.localIP(), MULTICAST_IP, MULTICAST_PORT); -} - -void ESPKNXIP::save_to_eeprom() -{ - uint32_t address = 0; - uint64_t magic = EEPROM_MAGIC; - EEPROM.put(address, magic); - address += sizeof(uint64_t); - EEPROM.put(address++, registered_callback_assignments); - for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) - { - EEPROM.put(address, callback_assignments[i].address); - address += sizeof(address_t); - } - for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) - { - EEPROM.put(address, callback_assignments[i].callback_id); - address += sizeof(callback_id_t); - } - EEPROM.put(address, physaddr); - address += sizeof(address_t); - - EEPROM.put(address, custom_config_data); - address += sizeof(custom_config_data); - - EEPROM.commit(); - DEBUG_PRINT("Wrote to EEPROM: 0x"); - DEBUG_PRINTLN(address, HEX); -} - -void ESPKNXIP::restore_from_eeprom() -{ - uint32_t address = 0; - uint64_t magic = 0; - EEPROM.get(address, magic); - if (magic != EEPROM_MAGIC) - { - DEBUG_PRINTLN("No valid magic in EEPROM, aborting restore."); - DEBUG_PRINT("Expected 0x"); - DEBUG_PRINT((unsigned long)(EEPROM_MAGIC >> 32), HEX); - DEBUG_PRINT(" 0x"); - DEBUG_PRINT((unsigned long)(EEPROM_MAGIC), HEX); - DEBUG_PRINT(" got 0x"); - DEBUG_PRINT((unsigned long)(magic >> 32), HEX); - DEBUG_PRINT(" 0x"); - DEBUG_PRINTLN((unsigned long)magic, HEX); - return; - } - address += sizeof(uint64_t); - EEPROM.get(address++, registered_callback_assignments); - for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) - { - EEPROM.get(address, callback_assignments[i].address); - if (callback_assignments[i].address.value != 0) - { - // if address is not 0/0/0 then mark slot as used - callback_assignments[i].slot_flags |= SLOT_FLAGS_USED; - DEBUG_PRINTLN("used slot"); - } - else - { - // if address is 0/0/0, then we found a free slot, yay! - // however, only count those slots, if we have not reached registered_callback_assignments yet - if (i < registered_callback_assignments) - { - DEBUG_PRINTLN("free slot before reaching registered_callback_assignments"); - free_callback_assignment_slots++; - } - else - { - DEBUG_PRINTLN("free slot"); - } - } - address += sizeof(address_t); - } - for (uint8_t i = 0; i < MAX_CALLBACK_ASSIGNMENTS; ++i) - { - EEPROM.get(address, callback_assignments[i].callback_id); - address += sizeof(callback_id_t); - } - EEPROM.get(address, physaddr); - address += sizeof(address_t); - - //EEPROM.get(address, custom_config_data); - //address += sizeof(custom_config_data); - uint32_t conf_offset = address; - for (uint8_t i = 0; i < registered_configs; ++i) - { - // First byte is flags. - config_flags_t flags = CONFIG_FLAGS_NO_FLAGS; - flags = (config_flags_t)EEPROM.read(address); - DEBUG_PRINT("Flag in EEPROM @ "); - DEBUG_PRINT(address - conf_offset); - DEBUG_PRINT(": "); - DEBUG_PRINTLN(flags, BIN); - custom_config_data[custom_configs[i].offset] = flags; - if (flags & CONFIG_FLAGS_VALUE_SET) - { - DEBUG_PRINTLN("Non-default value"); - for (int j = 0; j < custom_configs[i].len - sizeof(uint8_t); ++j) - { - custom_config_data[custom_configs[i].offset + sizeof(uint8_t) + j] = EEPROM.read(address + sizeof(uint8_t) + j); - } - } - - address += custom_configs[i].len; - } - - DEBUG_PRINT("Restored from EEPROM: 0x"); - DEBUG_PRINTLN(address, HEX); -} - -uint16_t ESPKNXIP::__ntohs(uint16_t n) -{ - return (uint16_t)((((uint8_t*)&n)[0] << 8) | (((uint8_t*)&n)[1])); -} - -callback_assignment_id_t ESPKNXIP::__callback_register_assignment(address_t address, callback_id_t id) -{ - if (registered_callback_assignments >= MAX_CALLBACK_ASSIGNMENTS) - return -1; - - if (free_callback_assignment_slots == 0) - { - callback_assignment_id_t aid = registered_callback_assignments; - - callback_assignments[aid].slot_flags |= SLOT_FLAGS_USED; - callback_assignments[aid].address = address; - callback_assignments[aid].callback_id = id; - registered_callback_assignments++; - return aid; - } - else - { - // find the free slot - for (callback_assignment_id_t aid = 0; aid < registered_callback_assignments; ++aid) - { - if (callback_assignments[aid].slot_flags & SLOT_FLAGS_USED) - { - // found a used slot - continue; - } - // and now an empty one - callback_assignments[aid].slot_flags |= SLOT_FLAGS_USED; - callback_assignments[aid].address = address; - callback_assignments[aid].callback_id = id; - - free_callback_assignment_slots--; - return id; - } - } - return -1; -} - -void ESPKNXIP::__callback_delete_assignment(callback_assignment_id_t id) -{ - // TODO this can be optimized if we are deleting the last element - // as then we can decrement registered_callback_assignments - - // clear slot and mark it as empty - callback_assignments[id].slot_flags = SLOT_FLAGS_EMPTY; - callback_assignments[id].address.value = 0; - callback_assignments[id].callback_id = 0; - - if (id == registered_callback_assignments - 1) - { - DEBUG_PRINTLN("last cba deleted"); - // If this is the last callback, we can delete it by decrementing registered_callbacks. - registered_callback_assignments--; - - // However, if the assignment before this slot are also empty, we can decrement even further - // First check if this was also the first element - if (id == 0) - { - DEBUG_PRINTLN("really last cba"); - // If this was the last, then we are done. - return; - } - - id--; - while(true) - { - DEBUG_PRINT("checking "); - DEBUG_PRINTLN((int32_t)id); - if ((callback_assignments[id].slot_flags & SLOT_FLAGS_USED) == 0) - { - DEBUG_PRINTLN("merged free slot"); - // Slot before is empty - free_callback_assignment_slots--; - registered_callback_assignments--; - } - else - { - DEBUG_PRINTLN("aborted on used slot"); - // Slot is used, abort - return; - } - id--; - if (id == CALLBACK_ASSIGNMENT_ID_MAX) - { - DEBUG_PRINTLN("abort on wrap"); - // Wrap around, abort - return; - } - } - } - else - { - DEBUG_PRINTLN("free slot created"); - // there is now one more free slot - free_callback_assignment_slots++; - } -} - -bool ESPKNXIP::__callback_is_id_valid(callback_id_t id) -{ - if (id < registered_callbacks) - return true; - - if (callbacks[id].slot_flags & SLOT_FLAGS_USED) - return true; - - return false; -} - -callback_id_t ESPKNXIP::callback_register(String name, callback_fptr_t cb, void *arg, enable_condition_t cond) -{ - if (registered_callbacks >= MAX_CALLBACKS) - return -1; - - if (free_callback_slots == 0) - { - callback_id_t id = registered_callbacks; - - callbacks[id].slot_flags |= SLOT_FLAGS_USED; - callbacks[id].name = name; - callbacks[id].fkt = cb; - callbacks[id].cond = cond; - callbacks[id].arg = arg; - registered_callbacks++; - return id; - } - else - { - // find the free slot - for (callback_id_t id = 0; id < registered_callbacks; ++id) - { - if (callbacks[id].slot_flags & SLOT_FLAGS_USED) - { - // found a used slot - continue; - } - // and now an empty one - callbacks[id].slot_flags |= SLOT_FLAGS_USED; - callbacks[id].name = name; - callbacks[id].fkt = cb; - callbacks[id].cond = cond; - callbacks[id].arg = arg; - - free_callback_slots--; - return id; - } - } - return -1; -} - -void ESPKNXIP::callback_deregister(callback_id_t id) -{ - if (!__callback_is_id_valid(id)) - return; - - // clear slot and mark it as empty - callbacks[id].slot_flags = SLOT_FLAGS_EMPTY; - callbacks[id].fkt = nullptr; - callbacks[id].cond = nullptr; - callbacks[id].arg = nullptr; - - if (id == registered_callbacks - 1) - { - // If this is the last callback, we can delete it by decrementing registered_callbacks. - registered_callbacks--; - - // However, if the callbacks before this slot are also empty, we can decrement even further - // First check if this was also the first element - if (id == 0) - { - // If this was the last, then we are done. - return; - } - - id--; - while(true) - { - if ((callbacks[id].slot_flags & SLOT_FLAGS_USED) == 0) - { - // Slot is empty - free_callback_slots--; - registered_callbacks--; - } - else - { - // Slot is used, abort - return; - } - id--; - if (id == CALLBACK_ASSIGNMENT_ID_MAX) - { - // Wrap around, abort - return; - } - } - } - else - { - // there is now one more free slot - free_callback_slots++; - } -} - -callback_assignment_id_t ESPKNXIP::callback_assign(callback_id_t id, address_t val) -{ - if (!__callback_is_id_valid(id)) - return -1; - - return __callback_register_assignment(val, id); -} - -void ESPKNXIP::callback_unassign(callback_assignment_id_t id) -{ - if (!__callback_is_id_valid(id)) - return; - - __callback_delete_assignment(id); -} - -/** - * Feedback functions start here - */ - -feedback_id_t ESPKNXIP::feedback_register_int(String name, int32_t *value, enable_condition_t cond) -{ - if (registered_feedbacks >= MAX_FEEDBACKS) - return -1; - - feedback_id_t id = registered_feedbacks; - - feedbacks[id].type = FEEDBACK_TYPE_INT; - feedbacks[id].name = name; - feedbacks[id].cond = cond; - feedbacks[id].data = (void *)value; - - registered_feedbacks++; - - return id; -} - -feedback_id_t ESPKNXIP::feedback_register_float(String name, float *value, uint8_t precision, char const *prefix, char const *suffix, enable_condition_t cond) -{ - if (registered_feedbacks >= MAX_FEEDBACKS) - return -1; - - feedback_id_t id = registered_feedbacks; - - feedbacks[id].type = FEEDBACK_TYPE_FLOAT; - feedbacks[id].name = name; - feedbacks[id].cond = cond; - feedbacks[id].data = (void *)value; - feedbacks[id].options.float_options.precision = precision; - feedbacks[id].options.float_options.prefix = prefix ? strdup(prefix) : STRING_DEFAULT_EMPTY; - feedbacks[id].options.float_options.suffix = suffix ? strdup(suffix) : STRING_DEFAULT_EMPTY; - - registered_feedbacks++; - - return id; -} - -feedback_id_t ESPKNXIP::feedback_register_bool(String name, bool *value, char const *true_text, char const *false_text, enable_condition_t cond) -{ - if (registered_feedbacks >= MAX_FEEDBACKS) - return -1; - - feedback_id_t id = registered_feedbacks; - - feedbacks[id].type = FEEDBACK_TYPE_BOOL; - feedbacks[id].name = name; - feedbacks[id].cond = cond; - feedbacks[id].data = (void *)value; - feedbacks[id].options.bool_options.true_text = true_text ? strdup(true_text) : STRING_DEFAULT_TRUE; - feedbacks[id].options.bool_options.false_text = false_text ? strdup(false_text) : STRING_DEFAULT_FALSE; - - registered_feedbacks++; - - return id; -} - -feedback_id_t ESPKNXIP::feedback_register_action(String name, feedback_action_fptr_t value, const char *btn_text, void *arg, enable_condition_t cond) -{ - if (registered_feedbacks >= MAX_FEEDBACKS) - return -1; - - feedback_id_t id = registered_feedbacks; - - feedbacks[id].type = FEEDBACK_TYPE_ACTION; - feedbacks[id].name = name; - feedbacks[id].cond = cond; - feedbacks[id].data = (void *)value; - feedbacks[id].options.action_options.arg = arg; - feedbacks[id].options.action_options.btn_text = btn_text ? strdup(btn_text) : STRING_DEFAULT_DO_THIS; - - registered_feedbacks++; - - return id; -} - -void ESPKNXIP::loop() -{ - __loop_knx(); - if (server != nullptr) - { - __loop_webserver(); - } -} - -void ESPKNXIP::__loop_webserver() -{ - server->handleClient(); -} - -void ESPKNXIP::__loop_knx() -{ - int read = udp.parsePacket(); - - if (!read) - { - return; - } - DEBUG_PRINTLN(F("")); - DEBUG_PRINT(F("LEN: ")); - DEBUG_PRINTLN(read); - - uint8_t buf[read]; - udp.read(buf, read); - - DEBUG_PRINT(F("Got packet:")); - -#ifdef ESP_KNX_DEBUG - - for (int i = 0; i < read; ++i) - - { - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINT(buf[i], 16); - } - -#endif - - DEBUG_PRINTLN(F("")); - - knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf; - - DEBUG_PRINT(F("ST: 0x")); - DEBUG_PRINTLN(__ntohs(knx_pkt->service_type), 16); - - if (knx_pkt->header_len != 0x06 && knx_pkt->protocol_version != 0x10 && knx_pkt->service_type != KNX_ST_ROUTING_INDICATION) - return; - - cemi_msg_t *cemi_msg = (cemi_msg_t *)knx_pkt->pkt_data; - - DEBUG_PRINT(F("MT: 0x")); - DEBUG_PRINTLN(cemi_msg->message_code, 16); - - if (cemi_msg->message_code != KNX_MT_L_DATA_IND) - return; - - DEBUG_PRINT(F("ADDI: 0x")); - DEBUG_PRINTLN(cemi_msg->additional_info_len, 16); - - cemi_service_t *cemi_data = &cemi_msg->data.service_information; - - if (cemi_msg->additional_info_len > 0) - cemi_data = (cemi_service_t *)(((uint8_t *)cemi_data) + cemi_msg->additional_info_len); - - DEBUG_PRINT(F("C1: 0x")); - DEBUG_PRINTLN(cemi_data->control_1.byte, 16); - - DEBUG_PRINT(F("C2: 0x")); - DEBUG_PRINTLN(cemi_data->control_2.byte, 16); - - DEBUG_PRINT(F("DT: 0x")); - DEBUG_PRINTLN(cemi_data->control_2.bits.dest_addr_type, 16); - - if (cemi_data->control_2.bits.dest_addr_type != 0x01) - return; - - DEBUG_PRINT(F("HC: 0x")); - DEBUG_PRINTLN(cemi_data->control_2.bits.hop_count, 16); - - DEBUG_PRINT(F("EFF: 0x")); - DEBUG_PRINTLN(cemi_data->control_2.bits.extended_frame_format, 16); - - DEBUG_PRINT(F("Source: 0x")); - DEBUG_PRINT(cemi_data->source.bytes.high, 16); - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINTLN(cemi_data->source.bytes.low, 16); - - DEBUG_PRINT(F("Dest: 0x")); - DEBUG_PRINT(cemi_data->destination.bytes.high, 16); - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINTLN(cemi_data->destination.bytes.low, 16); - - knx_command_type_t ct = (knx_command_type_t)(((cemi_data->data[0] & 0xC0) >> 6) | ((cemi_data->pci.apci & 0x03) << 2)); - - DEBUG_PRINT(F("CT: 0x")); - DEBUG_PRINTLN(ct, 16); - -#ifdef ESP_KNX_DEBUG - for (int i = 0; i < cemi_data->data_len; ++i) - { - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINT(cemi_data->data[i], 16); - } -#endif - - DEBUG_PRINTLN(F("==")); - - // Call callbacks - for (int i = 0; i < registered_callback_assignments; ++i) - { - DEBUG_PRINT(F("Testing: 0x")); - DEBUG_PRINT(callback_assignments[i].address.bytes.high, 16); - DEBUG_PRINT(F(" 0x")); - DEBUG_PRINTLN(callback_assignments[i].address.bytes.low, 16); - if (cemi_data->destination.value == callback_assignments[i].address.value) - { - DEBUG_PRINTLN(F("Found match")); - if (callbacks[callback_assignments[i].callback_id].cond && !callbacks[callback_assignments[i].callback_id].cond()) - { - DEBUG_PRINTLN(F("But it's disabled")); -#if ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS - continue; -#else - return; -#endif - } - uint8_t data[cemi_data->data_len]; - memcpy(data, cemi_data->data, cemi_data->data_len); - data[0] = data[0] & 0x3F; - message_t msg = {}; - msg.ct = ct; - msg.received_on = cemi_data->destination; - msg.data_len = cemi_data->data_len; - msg.data = data; - callbacks[callback_assignments[i].callback_id].fkt(msg, callbacks[callback_assignments[i].callback_id].arg); -#if ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS - continue; -#else - return; -#endif - } - } - - return; -} - -// Global "singleton" object -ESPKNXIP knx; diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h b/lib/esp-knx-ip-0.5.2/esp-knx-ip.h deleted file mode 100644 index 6834a6125..000000000 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h +++ /dev/null @@ -1,600 +0,0 @@ -/** - * esp-knx-ip library for KNX/IP communication on an ESP8266 - * Author: Nico Weichbrodt - * License: MIT - */ - -#ifndef ESP_KNX_IP_H -#define ESP_KNX_IP_H - -/** - * CONFIG - * All MAX_ values must not exceed 255 (1 byte, except MAC_CONFIG_SPACE which can go up to 2 bytes, so 0xffff in theory) and must not be negative! - * Config space is restriced by EEPROM_SIZE (default 1024). - * Required EEPROM size is 8 + MAX_GA_CALLBACKS * 3 + 2 + MAX_CONFIG_SPACE which is 552 by default - */ -#define EEPROM_SIZE 1024 // [Default 1024] -#define MAX_CALLBACK_ASSIGNMENTS 10 // [Default 10] Maximum number of group address callbacks that can be stored -#define MAX_CALLBACKS 10 // [Default 10] Maximum number of callbacks that can be stored -#define MAX_CONFIGS 20 // [Default 20] Maximum number of config items that can be stored -#define MAX_CONFIG_SPACE 0x0200 // [Default 0x0200] Maximum number of bytes that can be stored for custom config - -#define MAX_FEEDBACKS 20 // [Default 20] Maximum number of feedbacks that can be shown - -// Callbacks -#define ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS 1 // [Default 0] Set to 1 to always test all assigned callbacks. This allows for multiple callbacks being assigned to the same address. If disabled, only the first assigned will be called. - -// Webserver related -#define USE_BOOTSTRAP 0 // [Default 1] Set to 1 to enable use of bootstrap CSS for nicer webconfig. CSS is loaded from bootstrapcdn.com. Set to 0 to disable -#define ROOT_PREFIX "/knx" // [Default ""] This gets prepended to all webserver paths, default is empty string "". Set this to "/knx" if you want the config to be available on http:///knx -#define DISABLE_EEPROM_BUTTONS 1 // [Default 0] Set to 1 to disable the EEPROM buttons in the web ui. -#define DISABLE_REBOOT_BUTTON 1 // [Default 0] Set to 1 to disable the reboot button in the web ui. -#define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui. - -// These values normally don't need adjustment -#ifndef MULTICAST_IP -#define MULTICAST_IP IPAddress(224, 0, 23, 12) // [Default IPAddress(224, 0, 23, 12)] -#else -#warning USING CUSTOM MULTICAST_IP -#endif - -#ifndef MULTICAST_PORT -#define MULTICAST_PORT 3671 // [Default 3671] -#else -#warning USING CUSTOM MULTICAST_PORT -#endif - -#define SEND_CHECKSUM 0 - -// Uncomment to enable printing out debug messages. -//#define ESP_KNX_DEBUG -/** - * END CONFIG - */ - -#include "Arduino.h" -#include -#include -#include -#include - -#include "DPT.h" - -#define EEPROM_MAGIC (0xDEADBEEF00000000 + (MAX_CONFIG_SPACE) + (MAX_CALLBACK_ASSIGNMENTS << 16) + (MAX_CALLBACKS << 8)) - -// Define where debug output will be printed. -#ifndef DEBUG_PRINTER -#define DEBUG_PRINTER Serial -#endif - -// Setup debug printing macros. -#ifdef ESP_KNX_DEBUG - #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } - #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } -#else - #define DEBUG_PRINT(...) {} - #define DEBUG_PRINTLN(...) {} -#endif - -#define __ROOT_PATH ROOT_PREFIX"/" -#define __REGISTER_PATH ROOT_PREFIX"/register" -#define __DELETE_PATH ROOT_PREFIX"/delete" -#define __PHYS_PATH ROOT_PREFIX"/phys" -#define __EEPROM_PATH ROOT_PREFIX"/eeprom" -#define __CONFIG_PATH ROOT_PREFIX"/config" -#define __FEEDBACK_PATH ROOT_PREFIX"/feedback" -#define __RESTORE_PATH ROOT_PREFIX"/restore" -#define __REBOOT_PATH ROOT_PREFIX"/reboot" - -/** - * Different service types, we are mainly interested in KNX_ST_ROUTING_INDICATION - */ -typedef enum __knx_service_type -{ - KNX_ST_SEARCH_REQUEST = 0x0201, - KNX_ST_SEARCH_RESPONSE = 0x0202, - KNX_ST_DESCRIPTION_REQUEST = 0x0203, - KNX_ST_DESCRIPTION_RESPONSE = 0x0204, - KNX_ST_CONNECT_REQUEST = 0x0205, - KNX_ST_CONNECT_RESPONSE = 0x0206, - KNX_ST_CONNECTIONSTATE_REQUEST = 0x0207, - KNX_ST_CONNECTIONSTATE_RESPONSE = 0x0208, - KNX_ST_DISCONNECT_REQUEST = 0x0209, - KNX_ST_DISCONNECT_RESPONSE = 0x020A, - - KNX_ST_DEVICE_CONFIGURATION_REQUEST = 0x0310, - KNX_ST_DEVICE_CONFIGURATION_ACK = 0x0311, - - KNX_ST_TUNNELING_REQUEST = 0x0420, - KNX_ST_TUNNELING_ACK = 0x0421, - - KNX_ST_ROUTING_INDICATION = 0x0530, - KNX_ST_ROUTING_LOST_MESSAGE = 0x0531, - KNX_ST_ROUTING_BUSY = 0x0532, - -// KNX_ST_RLOG_START = 0x0600, -// KNX_ST_RLOG_END = 0x06FF, - - KNX_ST_REMOTE_DIAGNOSTIC_REQUEST = 0x0740, - KNX_ST_REMOTE_DIAGNOSTIC_RESPONSE = 0x0741, - KNX_ST_REMOTE_BASIC_CONFIGURATION_REQUEST = 0x0742, - KNX_ST_REMOTE_RESET_REQUEST = 0x0743, - -// KNX_ST_OBJSRV_START = 0x0800, -// KNX_ST_OBJSRV_END = 0x08FF, -} knx_service_type_t; - -/** - * Differnt command types, first three are of main interest - */ -typedef enum __knx_command_type -{ - KNX_CT_READ = 0x00, - KNX_CT_ANSWER = 0x01, - KNX_CT_WRITE = 0x02, - KNX_CT_INDIVIDUAL_ADDR_WRITE = 0x03, - KNX_CT_INDIVIDUAL_ADDR_REQUEST = 0x04, - KNX_CT_INDIVIDUAL_ADDR_RESPONSE = 0x05, - KNX_CT_ADC_READ = 0x06, - KNX_CT_ADC_ANSWER = 0x07, - KNX_CT_MEM_READ = 0x08, - KNX_CT_MEM_ANSWER = 0x09, - KNX_CT_MEM_WRITE = 0x0A, -//KNX_CT_UNKNOWN = 0x0B, - KNX_CT_MASK_VERSION_READ = 0x0C, - KNX_CT_MASK_VERSION_RESPONSE = 0x0D, - KNX_CT_RESTART = 0x0E, - KNX_CT_ESCAPE = 0x0F, -} knx_command_type_t; - -/** - * cEMI message types, mainly KNX_MT_L_DATA_IND is interesting - */ -typedef enum __knx_cemi_msg_type -{ - KNX_MT_L_DATA_REQ = 0x11, - KNX_MT_L_DATA_IND = 0x29, - KNX_MT_L_DATA_CON = 0x2E, -} knx_cemi_msg_type_t; - -/** - * TCPI communication type - */ -typedef enum __knx_communication_type { - KNX_COT_UDP = 0x00, // Unnumbered Data Packet - KNX_COT_NDP = 0x01, // Numbered Data Packet - KNX_COT_UCD = 0x02, // Unnumbered Control Data - KNX_COT_NCD = 0x03, // Numbered Control Data -} knx_communication_type_t; - -/** - * acpi for KNX_COT_NCD - */ -typedef enum __knx_cot_ncd_ack_type { - KNX_COT_NCD_ACK = 0x10, // Inform positively reception of the Previouly received telegram - KNX_COT_NCD_NACK = 0x11, // Inform negatively reception of the Previouly received telegram -} knx_cot_ncd_ack_type_t; - -/** - * KNX/IP header - */ -typedef struct __knx_ip_pkt -{ - uint8_t header_len; // Should always be 0x06 - uint8_t protocol_version; // Should be version 1.0, transmitted as 0x10 - uint16_t service_type; // See knx_service_type_t - union - { - struct { - uint8_t first_byte; - uint8_t second_byte; - } bytes; - uint16_t len; - } total_len; // header_len + rest of pkt. This is a bit weird as the spec says this: If the total number of bytes transmitted is greater than 252 bytes, the first “Total Length” byte is set to FF (255). Only in this case the second byte includes additional length information - uint8_t pkt_data[]; // This is of type cemi_msg_t -} knx_ip_pkt_t; - -typedef struct __cemi_addi -{ - uint8_t type_id; - uint8_t len; - uint8_t data[]; -} cemi_addi_t; - -typedef union __address -{ - uint16_t value; - struct - { - uint8_t high; - uint8_t low; - } bytes; - struct __attribute__((packed)) - { - uint8_t line:3; - uint8_t area:5; - uint8_t member; - } ga; - struct __attribute__((packed)) - { - uint8_t line:4; - uint8_t area:4; - uint8_t member; - } pa; - uint8_t array[2]; -} address_t; - -typedef struct __cemi_service -{ - union - { - struct - { - // Struct is reversed due to bit order - uint8_t confirm:1; // 0 = no error, 1 = error - uint8_t ack:1; // 0 = no ack, 1 = ack - uint8_t priority:2; // 0 = system, 1 = high, 2 = urgent/alarm, 3 = normal - uint8_t system_broadcast:1; // 0 = system broadcast, 1 = broadcast - uint8_t repeat:1; // 0 = repeated telegram, 1 = not repeated telegram - uint8_t reserved:1; // always zero - uint8_t frame_type:1; // 0 = extended, 1 = standard - } bits; - uint8_t byte; - } control_1; - union - { - struct - { - // Struct is reversed due to bit order - uint8_t extended_frame_format:4; - uint8_t hop_count:3; - uint8_t dest_addr_type:1; // 0 = individual, 1 = group - } bits; - uint8_t byte; - } control_2; - address_t source; - address_t destination; - uint8_t data_len; // length of data, excluding the tpci byte - struct - { - uint8_t apci:2; // If tpci.comm_type == KNX_COT_UCD or KNX_COT_NCD, then this is apparently control data? - uint8_t tpci_seq_number:4; - uint8_t tpci_comm_type:2; // See knx_communication_type_t - } pci; - uint8_t data[]; -} cemi_service_t; - -typedef struct __cemi_msg -{ - uint8_t message_code; - uint8_t additional_info_len; - union - { -// cemi_addi_t additional_info[]; // Errors in GCC 10.1 - cemi_addi_t additional_info[10]; // Changed to arbitrary number to fix compilation - cemi_service_t service_information; - } data; -} cemi_msg_t; - -typedef enum __config_type -{ - CONFIG_TYPE_UNKNOWN, - CONFIG_TYPE_INT, - CONFIG_TYPE_BOOL, - CONFIG_TYPE_STRING, - CONFIG_TYPE_OPTIONS, - CONFIG_TYPE_GA, -} config_type_t; - -typedef enum __feedback_type -{ - FEEDBACK_TYPE_UNKNOWN, - FEEDBACK_TYPE_INT, - FEEDBACK_TYPE_FLOAT, - FEEDBACK_TYPE_BOOL, - FEEDBACK_TYPE_ACTION, -} feedback_type_t; - -typedef enum __config_flags -{ - CONFIG_FLAGS_NO_FLAGS = 0, - CONFIG_FLAGS_VALUE_SET = 1, -} config_flags_t; - -typedef enum __slot_flags -{ - SLOT_FLAGS_EMPTY = 0, // Empty slots have no flags - SLOT_FLAGS_USED = 1, -} slot_flags_t; - -typedef struct __message -{ - knx_command_type_t ct; - address_t received_on; - uint8_t data_len; - uint8_t *data; -} message_t; - -typedef bool (*enable_condition_t)(void); -typedef void (*callback_fptr_t)(message_t const &msg, void *arg); -typedef void (*feedback_action_fptr_t)(void *arg); - -typedef uint8_t callback_id_t; -#define CALLBACK_ID_MAX UINT8_MAX -typedef uint8_t callback_assignment_id_t; -#define CALLBACK_ASSIGNMENT_ID_MAX UINT8_MAX -typedef uint8_t config_id_t; -typedef uint8_t feedback_id_t; - -typedef struct __option_entry -{ - char const *name; - uint8_t value; -} option_entry_t; - -typedef struct __config -{ - config_type_t type; - String name; - uint8_t offset; - uint8_t len; - enable_condition_t cond; - union { - option_entry_t *options; - } data; -} config_t; - -extern char const *string_defaults[]; -#define STRING_DEFAULT_DO_THIS (string_defaults[0]) -#define STRING_DEFAULT_TRUE (string_defaults[1]) -#define STRING_DEFAULT_FALSE (string_defaults[2]) -#define STRING_DEFAULT_EMPTY (string_defaults[3]) - -typedef struct __feedback_float_options -{ - uint8_t precision; - char const *prefix; - char const *suffix; -} feedback_float_options_t; - -typedef struct __feedback_bool_options -{ - char const *true_text; - char const *false_text; -} feedback_bool_options_t; - -typedef struct __feedback_action_options -{ - void *arg; - char const *btn_text; -} feedback_action_options_t; - -typedef struct __feedback -{ - feedback_type_t type; - String name; - enable_condition_t cond; - void *data; - union { - feedback_bool_options_t bool_options; - feedback_float_options_t float_options; - feedback_action_options_t action_options; - } options; -} feedback_t; - -typedef struct __callback -{ - uint8_t slot_flags; - callback_fptr_t fkt; - enable_condition_t cond; - void *arg; - String name; -} callback_t; - -typedef struct __callback_assignment -{ - uint8_t slot_flags; - address_t address; - callback_id_t callback_id; -} callback_assignment_t; - -// FastPrecisePowf from tasmota/support_float.ino -//extern float FastPrecisePowf(const float x, const float y); - -class ESPKNXIP { - public: - ESPKNXIP(); - void load(); - void start(); - void start(ESP8266WebServer *srv); - void loop(); - - void save_to_eeprom(); - void restore_from_eeprom(); - - callback_id_t callback_register(String name, callback_fptr_t cb, void *arg = nullptr, enable_condition_t cond = nullptr); - callback_assignment_id_t callback_assign(callback_id_t id, address_t val); - void callback_deregister(callback_id_t id); - void callback_unassign(callback_assignment_id_t id); - - void physical_address_set(address_t const &addr); - address_t physical_address_get(); - - // Configuration functions - config_id_t config_register_string(String name, uint8_t len, String _default, enable_condition_t cond = nullptr); - config_id_t config_register_int(String name, int32_t _default, enable_condition_t cond = nullptr); - config_id_t config_register_bool(String name, bool _default, enable_condition_t cond = nullptr); - config_id_t config_register_options(String name, option_entry_t *options, uint8_t _default, enable_condition_t cond = nullptr); - config_id_t config_register_ga(String name, enable_condition_t cond = nullptr); - - String config_get_string(config_id_t id); - int32_t config_get_int(config_id_t id); - bool config_get_bool(config_id_t id); - uint8_t config_get_options(config_id_t id); - address_t config_get_ga(config_id_t id); - - void config_set_string(config_id_t id, String val); - void config_set_int(config_id_t id, int32_t val); - void config_set_bool(config_id_t, bool val); - void config_set_options(config_id_t id, uint8_t val); - void config_set_ga(config_id_t id, address_t const &val); - - // Feedback functions - feedback_id_t feedback_register_int(String name, int32_t *value, enable_condition_t cond = nullptr); - feedback_id_t feedback_register_float(String name, float *value, uint8_t precision = 2, char const *prefix = nullptr, char const *suffix = nullptr, enable_condition_t cond = nullptr); - feedback_id_t feedback_register_bool(String name, bool *value, char const *true_text = nullptr, char const *false_text = nullptr, enable_condition_t cond = nullptr); - feedback_id_t feedback_register_action(String name, feedback_action_fptr_t value, char const *btn_text = nullptr, void *arg = nullptr, enable_condition_t = nullptr); - - // Send functions - void send(address_t const &receiver, knx_command_type_t ct, uint8_t data_len, uint8_t *data); - - void send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit); - void send_2bit(address_t const &receiver, knx_command_type_t ct, uint8_t twobit); - void send_4bit(address_t const &receiver, knx_command_type_t ct, uint8_t fourbit); - void send_1byte_int(address_t const &receiver, knx_command_type_t ct, int8_t val); - void send_1byte_uint(address_t const &receiver, knx_command_type_t ct, uint8_t val); - void send_2byte_int(address_t const &receiver, knx_command_type_t ct, int16_t val); - void send_2byte_uint(address_t const &receiver, knx_command_type_t ct, uint16_t val); - void send_2byte_float(address_t const &receiver, knx_command_type_t ct, float val); - void send_3byte_time(address_t const &receiver, knx_command_type_t ct, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds); - void send_3byte_time(address_t const &receiver, knx_command_type_t ct, time_of_day_t const &time) { send_3byte_time(receiver, ct, time.weekday, time.hours, time.minutes, time.seconds); } - void send_3byte_date(address_t const &receiver, knx_command_type_t ct, uint8_t day, uint8_t month, uint8_t year); - void send_3byte_date(address_t const &receiver, knx_command_type_t ct, date_t const &date) { send_3byte_date(receiver, ct, date.day, date.month, date.year); } - void send_3byte_color(address_t const &receiver, knx_command_type_t ct, uint8_t red, uint8_t green, uint8_t blue); - void send_3byte_color(address_t const &receiver, knx_command_type_t ct, color_t const &color) { send_3byte_color(receiver, ct, color.red, color.green, color.blue); } - void send_4byte_int(address_t const &receiver, knx_command_type_t ct, int32_t val); - void send_4byte_uint(address_t const &receiver, knx_command_type_t ct, uint32_t val); - void send_4byte_float(address_t const &receiver, knx_command_type_t ct, float val); - void send_14byte_string(address_t const &receiver, knx_command_type_t ct, const char *val); - - void write_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_WRITE, bit); } - void write_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_WRITE, twobit); } - void write_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_WRITE, fourbit); } - void write_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_WRITE, val); } - void write_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_WRITE, val); } - void write_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_WRITE, val); } - void write_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_WRITE, val); } - void write_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_WRITE, val); } - void write_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_WRITE, weekday, hours, minutes, seconds); } - void write_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_WRITE, time.weekday, time.hours, time.minutes, time.seconds); } - void write_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_WRITE, day, month, year); } - void write_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_WRITE, date.day, date.month, date.year); } - void write_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_WRITE, red, green, blue); } - void write_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_WRITE, color); } - void write_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_WRITE, val); } - void write_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_WRITE, val); } - void write_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_WRITE, val);} - void write_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_WRITE, val); } - - void answer_1bit(address_t const &receiver, uint8_t bit) { send_1bit(receiver, KNX_CT_ANSWER, bit); } - void answer_2bit(address_t const &receiver, uint8_t twobit) { send_2bit(receiver, KNX_CT_ANSWER, twobit); } - void answer_4bit(address_t const &receiver, uint8_t fourbit) { send_4bit(receiver, KNX_CT_ANSWER, fourbit); } - void answer_1byte_int(address_t const &receiver, int8_t val) { send_1byte_int(receiver, KNX_CT_ANSWER, val); } - void answer_1byte_uint(address_t const &receiver, uint8_t val) { send_1byte_uint(receiver, KNX_CT_ANSWER, val); } - void answer_2byte_int(address_t const &receiver, int16_t val) { send_2byte_int(receiver, KNX_CT_ANSWER, val); } - void answer_2byte_uint(address_t const &receiver, uint16_t val) { send_2byte_uint(receiver, KNX_CT_ANSWER, val); } - void answer_2byte_float(address_t const &receiver, float val) { send_2byte_float(receiver, KNX_CT_ANSWER, val); } - void answer_3byte_time(address_t const &receiver, uint8_t weekday, uint8_t hours, uint8_t minutes, uint8_t seconds) { send_3byte_time(receiver, KNX_CT_ANSWER, weekday, hours, minutes, seconds); } - void answer_3byte_time(address_t const &receiver, time_of_day_t const &time) { send_3byte_time(receiver, KNX_CT_ANSWER, time.weekday, time.hours, time.minutes, time.seconds); } - void answer_3byte_date(address_t const &receiver, uint8_t day, uint8_t month, uint8_t year) { send_3byte_date(receiver, KNX_CT_ANSWER, day, month, year); } - void answer_3byte_date(address_t const &receiver, date_t const &date) { send_3byte_date(receiver, KNX_CT_ANSWER, date.day, date.month, date.year); } - void answer_3byte_color(address_t const &receiver, uint8_t red, uint8_t green, uint8_t blue) { send_3byte_color(receiver, KNX_CT_ANSWER, red, green, blue); } - void answer_3byte_color(address_t const &receiver, color_t const &color) { send_3byte_color(receiver, KNX_CT_ANSWER, color); } - void answer_4byte_int(address_t const &receiver, int32_t val) { send_4byte_int(receiver, KNX_CT_ANSWER, val); } - void answer_4byte_uint(address_t const &receiver, uint32_t val) { send_4byte_uint(receiver, KNX_CT_ANSWER, val); } - void answer_4byte_float(address_t const &receiver, float val) { send_4byte_float(receiver, KNX_CT_ANSWER, val);} - void answer_14byte_string(address_t const &receiver, const char *val) { send_14byte_string(receiver, KNX_CT_ANSWER, val); } - - bool data_to_bool(uint8_t *data); - int8_t data_to_1byte_int(uint8_t *data); - uint8_t data_to_1byte_uint(uint8_t *data); - int16_t data_to_2byte_int(uint8_t *data); - uint16_t data_to_2byte_uint(uint8_t *data); - float data_to_2byte_float(uint8_t *data); - color_t data_to_3byte_color(uint8_t *data); - time_of_day_t data_to_3byte_time(uint8_t *data); - date_t data_to_3byte_data(uint8_t *data); - int32_t data_to_4byte_int(uint8_t *data); - uint32_t data_to_4byte_uint(uint8_t *data); - float data_to_4byte_float(uint8_t *data); - - static address_t GA_to_address(uint8_t area, uint8_t line, uint8_t member) - { - // Yes, the order is correct, see the struct definition above - address_t tmp = {.ga={line, area, member}}; - return tmp; - } - - static address_t PA_to_address(uint8_t area, uint8_t line, uint8_t member) - { - // Yes, the order is correct, see the struct definition above - address_t tmp = {.pa={line, area, member}}; - return tmp; - } - - private: - void __start(); - - void __loop_knx(); - - // Webserver functions - void __loop_webserver(); - void __handle_root(); - void __handle_register(); - void __handle_delete(); - void __handle_set(); -#if !DISABLE_EEPROM_BUTTONS - void __handle_eeprom(); -#endif - void __handle_config(); - void __handle_feedback(); -#if !DISABLE_RESTORE_BUTTONS - void __handle_restore(); -#endif -#if !DISABLE_REBOOT_BUTTONS - void __handle_reboot(); -#endif - - void __config_set_flags(config_id_t id, config_flags_t flags); - - void __config_set_string(config_id_t id, String &val); - void __config_set_int(config_id_t id, int32_t val); - void __config_set_bool(config_id_t id, bool val); - void __config_set_options(config_id_t id, uint8_t val); - void __config_set_ga(config_id_t id, address_t const &val); - - bool __callback_is_id_valid(callback_id_t id); - - callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id); - void __callback_delete_assignment(callback_assignment_id_t id); - - //static inline float pow(float a, float b) { return FastPrecisePowf(a, b); } - - ESP8266WebServer *server; - address_t physaddr; - - WiFiUDP udp; - - callback_assignment_id_t registered_callback_assignments; - callback_assignment_id_t free_callback_assignment_slots; - callback_assignment_t callback_assignments[MAX_CALLBACK_ASSIGNMENTS]; - - callback_id_t registered_callbacks; - callback_id_t free_callback_slots; - callback_t callbacks[MAX_CALLBACKS]; - - config_id_t registered_configs; - uint8_t custom_config_data[MAX_CONFIG_SPACE]; - uint8_t custom_config_default_data[MAX_CONFIG_SPACE]; - config_t custom_configs[MAX_CONFIGS]; - - feedback_id_t registered_feedbacks; - feedback_t feedbacks[MAX_FEEDBACKS]; - - uint16_t __ntohs(uint16_t); -}; - -// Global "singleton" object -extern ESPKNXIP knx; - -#endif diff --git a/lib/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino b/lib/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino deleted file mode 100644 index 02621bbc6..000000000 --- a/lib/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This is an example showing a simple environment sensor based on a BME280 attached via I2C. - * This sketch was tested on a WeMos D1 mini - */ - -#include -#include - -// WiFi config here -const char* ssid = "myssid"; -const char* pass = "mypassword"; - -#define LED_PIN D4 -#define UPDATE_INTERVAL 10000 - -unsigned long next_change = 0; - -float last_temp = 0.0; -float last_hum = 0.0; -float last_pres = 0.0; - -config_id_t temp_ga, hum_ga, pres_ga; -config_id_t hostname_id; -config_id_t update_rate_id, send_rate_id; -config_id_t enable_sending_id; -config_id_t enable_reading_id; - -Adafruit_BME280 bme; - -void setup() { - pinMode(LED_PIN, OUTPUT); - Serial.begin(115200); - - hostname_id = knx.config_register_string("Hostname", 20, String("env")); - enable_sending_id = knx.config_register_bool("Send on update", true); - update_rate_id = knx.config_register_int("Update rate (ms)", UPDATE_INTERVAL); - temp_ga = knx.config_register_ga("Temperature", show_periodic_options); - hum_ga = knx.config_register_ga("Humidity", show_periodic_options); - pres_ga = knx.config_register_ga("Pressure", show_periodic_options); - - knx.callback_register("Read Temperature", temp_cb); - knx.callback_register("Read Humidity", hum_cb); - knx.callback_register("Read Pressure", pres_cb); - - knx.feedback_register_float("Temperature (°C)", &last_temp); - knx.feedback_register_float("Humidity (%)", &last_hum); - knx.feedback_register_float("Pressure (hPa)", &last_pres, 0); - - // Load previous config from EEPROM - knx.load(); - - // Init sensor - if (!bme.begin(0x76)) { - Serial.println("Could not find a valid BME280 sensor, check wiring!"); - } - - // Init WiFi - WiFi.hostname(knx.config_get_string(hostname_id)); - WiFi.begin(ssid, pass); - - Serial.println(""); - Serial.print("[Connecting]"); - Serial.print(ssid); - - digitalWrite(LED_PIN, LOW); - while (WiFi.status() != WL_CONNECTED) { - digitalWrite(LED_PIN, HIGH); - delay(250); - Serial.print("."); - digitalWrite(LED_PIN, LOW); - delay(250); - } - digitalWrite(LED_PIN, HIGH); - - // Start knx - knx.start(); - - Serial.println(); - Serial.println("Connected to wifi"); - Serial.println(WiFi.localIP()); -} - -void loop() { - knx.loop(); - - unsigned long now = millis(); - - if (next_change < now) - { - next_change = now + knx.config_get_int(update_rate_id); - - last_temp = bme.readTemperature(); - last_hum = bme.readHumidity(); - last_pres = bme.readPressure()/100.0f; - - Serial.print("T: "); - Serial.print(last_temp); - Serial.print("°C H: "); - Serial.print(last_hum); - Serial.print("% P: "); - Serial.print(last_pres); - Serial.println("hPa"); - - if (knx.config_get_bool(enable_sending_id)) - { - knx.write_2byte_float(knx.config_get_ga(temp_ga), last_temp); - knx.write_2byte_float(knx.config_get_ga(hum_ga), last_hum); - knx.write_2byte_float(knx.config_get_ga(pres_ga), last_pres); - } - } - - delay(50); -} - -bool show_periodic_options() -{ - return knx.config_get_bool(enable_sending_id); -} - -bool enable_reading_callback() -{ - return knx.config_get_bool(enable_reading_id); -} - -void temp_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_temp); - break; - } - } -} - -void hum_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_hum); - break; - } - } -} - -void pres_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_pres); - break; - } - } -} diff --git a/lib/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino b/lib/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino deleted file mode 100644 index fc2400b7b..000000000 --- a/lib/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino +++ /dev/null @@ -1,183 +0,0 @@ -#include - -// WiFi config here -const char* ssid = "ssid"; -const char* pass = "pass"; - -// Common -#define LED_PIN 13 - -// For Basic and S20 -#define BTN1_PIN 0 -#define CH1_PIN 12 - -// For 4CH -#define BTN2_PIN 9 -#define CH2_PIN 5 -#define BTN3_PIN 10 -#define CH3_PIN 4 -#define BTN4_PIN 14 -#define CH4_PIN 15 - -typedef enum __type_option -{ - SONOFF_TYPE_NONE = 0, - SONOFF_TYPE_BASIC = 1, - SONOFF_TYPE_S20 = 2, - SONOFF_TYPE_4CH = 3, - SONOFF_TYPE_4CH_PRO = 4, -} type_option_t; - -option_entry_t type_options[] = { - {"Sonoff Basic", SONOFF_TYPE_BASIC}, - {"Sonoff S20", SONOFF_TYPE_S20}, - {"Sonoff 4CH", SONOFF_TYPE_4CH}, - {"Sonoff 4CH Pro", SONOFF_TYPE_4CH_PRO}, - {nullptr, 0} -}; - -config_id_t hostname_id; -config_id_t type_id; - -typedef struct __sonoff_channel -{ - int pin; - int btn_pin; - config_id_t status_ga_id; - bool state; - bool last_btn_state; -} sonoff_channel_t; - -sonoff_channel_t channels[] = { - {CH1_PIN, BTN1_PIN, 0, false, false}, - {CH2_PIN, BTN2_PIN, 0, false, false}, - {CH3_PIN, BTN3_PIN, 0, false, false}, - {CH4_PIN, BTN4_PIN, 0, false, false}, -}; - -void setup() -{ - pinMode(LED_PIN, OUTPUT); - pinMode(BTN1_PIN, INPUT_PULLUP); - pinMode(BTN2_PIN, INPUT_PULLUP); - pinMode(BTN3_PIN, INPUT_PULLUP); - pinMode(BTN4_PIN, INPUT_PULLUP); - pinMode(CH1_PIN, OUTPUT); - pinMode(CH2_PIN, OUTPUT); - pinMode(CH3_PIN, OUTPUT); - pinMode(CH4_PIN, OUTPUT); - Serial.begin(115200); - - // Register the config options - hostname_id = knx.config_register_string("Hostname", 20, String("sonoff")); - type_id = knx.config_register_options("Type", type_options, SONOFF_TYPE_BASIC); - - channels[0].status_ga_id = knx.config_register_ga("Channel 1 Status GA"); - channels[1].status_ga_id = knx.config_register_ga("Channel 2 Status GA", is_4ch_or_4ch_pro); - channels[2].status_ga_id = knx.config_register_ga("Channel 3 Status GA", is_4ch_or_4ch_pro); - channels[3].status_ga_id = knx.config_register_ga("Channel 4 Status GA", is_4ch_or_4ch_pro); - - knx.callback_register("Channel 1", channel_cb, &channels[0]); - knx.callback_register("Channel 2", channel_cb, &channels[1], is_4ch_or_4ch_pro); - knx.callback_register("Channel 3", channel_cb, &channels[2], is_4ch_or_4ch_pro); - knx.callback_register("Channel 4", channel_cb, &channels[3], is_4ch_or_4ch_pro); - - knx.feedback_register_bool("Channel 1 is on", &(channels[0].state)); - knx.feedback_register_action("Toogle channel 1", toggle_chan, &channels[0]); - knx.feedback_register_bool("Channel 2 is on", &(channels[1].state), is_4ch_or_4ch_pro); - knx.feedback_register_action("Toogle channel 2", toggle_chan, &channels[1], is_4ch_or_4ch_pro); - knx.feedback_register_bool("Channel 3 is on", &(channels[2].state), is_4ch_or_4ch_pro); - knx.feedback_register_action("Toogle channel 3", toggle_chan, &channels[2], is_4ch_or_4ch_pro); - knx.feedback_register_bool("Channel 4 is on", &(channels[3].state), is_4ch_or_4ch_pro); - knx.feedback_register_action("Toogle channel 4", toggle_chan, &channels[3], is_4ch_or_4ch_pro); - - knx.load(); - - // Init WiFi - WiFi.hostname(knx.config_get_string(hostname_id)); - WiFi.begin(ssid, pass); - - Serial.println(""); - Serial.print("[Connecting]"); - Serial.print(ssid); - - digitalWrite(LED_PIN, LOW); - while (WiFi.status() != WL_CONNECTED) { - digitalWrite(LED_PIN, HIGH); - delay(500); - Serial.print("."); - digitalWrite(LED_PIN, LOW); - } - digitalWrite(LED_PIN, HIGH); - - // Start knx - knx.start(); - - Serial.println(); - Serial.println("Connected to wifi"); - Serial.println(WiFi.localIP()); -} - -void loop() -{ - knx.loop(); - - // Check local buttons - check_button(&channels[0]); - if (is_4ch_or_4ch_pro()) - { - check_button(&channels[1]); - check_button(&channels[2]); - check_button(&channels[3]); - } - - delay(50); -} - -bool is_basic_or_s20() -{ - uint8_t type = knx.config_get_options(type_id); - return type == SONOFF_TYPE_BASIC || type == SONOFF_TYPE_S20; -} - -bool is_4ch_or_4ch_pro() -{ - uint8_t type = knx.config_get_options(type_id); - return type == SONOFF_TYPE_4CH ||type == SONOFF_TYPE_4CH_PRO; -} - -void check_button(sonoff_channel_t *chan) -{ - bool state_now = digitalRead(chan->btn_pin) == HIGH ? true : false; - if (state_now != chan->last_btn_state && state_now == LOW) - { - chan->state = !chan->state; - digitalWrite(chan->pin, chan->state ? HIGH : LOW); - knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); - } - chan->last_btn_state = state_now; -} - -void toggle_chan(void *arg) -{ - sonoff_channel_t *chan = (sonoff_channel_t *)arg; - chan->state = !chan->state; - digitalWrite(chan->pin, chan->state ? HIGH : LOW); - knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); -} - -void channel_cb(message_t const &msg, void *arg) -{ - sonoff_channel_t *chan = (sonoff_channel_t *)arg; - switch (msg.ct) - { - case KNX_CT_WRITE: - chan->state = msg.data[0]; - Serial.println(chan->state ? "Toggle on" : "Toggle off"); - digitalWrite(chan->pin, chan->state ? HIGH : LOW); - knx.write_1bit(knx.config_get_ga(chan->status_ga_id), chan->state); - break; - case KNX_CT_READ: - knx.answer_1bit(msg.received_on, chan->state); - } -} diff --git a/lib/esp-knx-ip-0.5.2/examples/static-config/static-config.ino b/lib/esp-knx-ip-0.5.2/examples/static-config/static-config.ino deleted file mode 100644 index 54472dda3..000000000 --- a/lib/esp-knx-ip-0.5.2/examples/static-config/static-config.ino +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This is an example showing a simple environment sensor based on a BME280 attached via I2C. - * It shows, how the library can used to statically configure a device without a webserver for config. - * This sketch was tested on a WeMos D1 mini - */ - -#include -#include - -// WiFi config here -const char* ssid = "myssid"; -const char* pass = "mypassword"; - -#define LED_PIN D4 -#define UPDATE_INTERVAL 10000 - -unsigned long next_change = 0; - -float last_temp = 0.0; -float last_hum = 0.0; -float last_pres = 0.0; - -Adafruit_BME280 bme; - -// Group addresses to send to (1/1/1, 1/1/2 and 1/1/3) -address_t temp_ga = knx.GA_to_address(1, 1, 1); -address_t hum_ga = knx.GA_to_address(1, 1, 2); -address_t pres_ga = knx.GA_to_address(1, 1, 3); - -void setup() { - pinMode(LED_PIN, OUTPUT); - Serial.begin(115200); - - callback_id_t temp_cb_id = knx.callback_register("Read Temperature", temp_cb); - callback_id_t hum_cb_id =knx.callback_register("Read Humidity", hum_cb); - callback_id_t pres_cb_id =knx.callback_register("Read Pressure", pres_cb); - - // Assign callbacks to group addresses (2/1/1, 2/1/2, 2/1/3) - knx.callback_assign(temp_cb_id, knx.GA_to_address(2, 1, 1)); - knx.callback_assign(hum_cb_id, knx.GA_to_address(2, 1, 2)); - knx.callback_assign(pres_cb_id, knx.GA_to_address(2, 1, 3)); - - // Set physical address (1.1.1) - knx.physical_address_set(knx.PA_to_address(1, 1, 1)); - - // Do not call knx.load() for static config, it will try to load config from EEPROM which we don't have here - - // Init sensor - if (!bme.begin(0x76)) { - Serial.println("Could not find a valid BME280 sensor, check wiring!"); - } - - // Init WiFi - WiFi.hostname("env"); - WiFi.begin(ssid, pass); - - Serial.println(""); - Serial.print("[Connecting]"); - Serial.print(ssid); - - digitalWrite(LED_PIN, LOW); - while (WiFi.status() != WL_CONNECTED) { - digitalWrite(LED_PIN, HIGH); - delay(250); - Serial.print("."); - digitalWrite(LED_PIN, LOW); - delay(250); - } - digitalWrite(LED_PIN, HIGH); - - // Start knx, disable webserver by passing nullptr - knx.start(nullptr); - - Serial.println(); - Serial.println("Connected to wifi"); - Serial.println(WiFi.localIP()); -} - -void loop() { - knx.loop(); - - unsigned long now = millis(); - - if (next_change < now) - { - next_change = now + UPDATE_INTERVAL; - - last_temp = bme.readTemperature(); - last_hum = bme.readHumidity(); - last_pres = bme.readPressure()/100.0f; - - Serial.print("T: "); - Serial.print(last_temp); - Serial.print("°C H: "); - Serial.print(last_hum); - Serial.print("% P: "); - Serial.print(last_pres); - Serial.println("hPa"); - - knx.write_2byte_float(temp_ga, last_temp); - knx.write_2byte_float(hum_ga, last_hum); - knx.write_2byte_float(pres_ga, last_pres); - } - - delay(50); -} - -void temp_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_temp); - break; - } - } -} - -void hum_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_hum); - break; - } - } -} - -void pres_cb(message_t const &msg, void *arg) -{ - switch (msg.ct) - { - case KNX_CT_READ: - { - knx.answer_2byte_float(msg.received_on, last_pres); - break; - } - } -} diff --git a/lib/esp-knx-ip-0.5.2/keywords.txt b/lib/esp-knx-ip-0.5.2/keywords.txt deleted file mode 100644 index 59836ef05..000000000 --- a/lib/esp-knx-ip-0.5.2/keywords.txt +++ /dev/null @@ -1,107 +0,0 @@ -# datatypes -address_t KEYWORD1 DATA_TYPE -message_t KEYWORD1 DATA_TYPE -callback_id_t KEYWORD1 DATA_TYPE -callback_assignment_id_t KEYWORD1 DATA_TYPE -option_entry_t KEYWORD1 DATA_TYPE -config_id_t KEYWORD1 DATA_TYPE -enable_condition_t KEYWORD1 DATA_TYPE -callback_fptr_t KEYWORD1 DATA_TYPE -feedback_action_fptr_t KEYWORD1 DATA_TYPE -knx_command_type_t KEYWORD1 DATA_TYPE - -# methods -setup KEYWORD2 -loop KEYWORD2 -GA_to_address KEYWORD2 -PA_to_address KEYWORD2 -callback_register KEYWORD2 -callback_assign KEYWORD2 -callback_deregister KEYWORD2 -callback_unassign KEYWORD2 -physical_address_set KEYWORD2 -physical_address_get KEYWORD2 -config_register_string KEYWORD2 -config_register_int KEYWORD2 -config_register_bool KEYWORD2 -config_register_options KEYWORD2 -config_register_ga KEYWORD2 -config_get_string KEYWORD2 -config_get_int KEYWORD2 -config_get_bool KEYWORD2 -config_get_options KEYWORD2 -config_get_ga KEYWORD2 -config_set_string KEYWORD2 -config_set_int KEYWORD2 -config_set_bool KEYWORD2 -config_set_options KEYWORD2 -config_set_ga KEYWORD2 -feedback_register_int KEYWORD2 -feedback_register_float KEYWORD2 -feedback_register_bool KEYWORD2 -feedback_register_action KEYWORD2 -send_1bit KEYWORD2 -send_2bit KEYWORD2 -send_4bit KEYWORD2 -send_1byte_int KEYWORD2 -send_1byte_uint KEYWORD2 -send_2byte_int KEYWORD2 -send_2byte_uint KEYWORD2 -send_2byte_float KEYWORD2 -send_3byte_time KEYWORD2 -send_3byte_time KEYWORD2 -send_3byte_date KEYWORD2 -send_3byte_date KEYWORD2 -send_3byte_color KEYWORD2 -send_3byte_color KEYWORD2 -send_4byte_int KEYWORD2 -send_4byte_uint KEYWORD2 -send_4byte_float KEYWORD2 -send_14byte_string KEYWORD2 -write_1bit KEYWORD2 -write_2bit KEYWORD2 -write_4bit KEYWORD2 -write_1byte_int KEYWORD2 -write_1byte_uint KEYWORD2 -write_2byte_int KEYWORD2 -write_2byte_uint KEYWORD2 -write_2byte_float KEYWORD2 -write_3byte_time KEYWORD2 -write_3byte_time KEYWORD2 -write_3byte_date KEYWORD2 -write_3byte_date KEYWORD2 -write_3byte_color KEYWORD2 -write_3byte_color KEYWORD2 -write_4byte_int KEYWORD2 -write_4byte_uint KEYWORD2 -write_4byte_float KEYWORD2 -write_14byte_string KEYWORD2 -answer_1bit KEYWORD2 -answer_2bit KEYWORD2 -answer_4bit KEYWORD2 -answer_1byte_int KEYWORD2 -answer_1byte_uint KEYWORD2 -answer_2byte_int KEYWORD2 -answer_2byte_uint KEYWORD2 -answer_2byte_float KEYWORD2 -answer_3byte_time KEYWORD2 -answer_3byte_time KEYWORD2 -answer_3byte_date KEYWORD2 -answer_3byte_date KEYWORD2 -answer_3byte_color KEYWORD2 -answer_3byte_color KEYWORD2 -answer_4byte_int KEYWORD2 -answer_4byte_uint KEYWORD2 -answer_4byte_float KEYWORD2 -answer_14byte_string KEYWORD2 - -data_to_1byte_int KEYWORD2 -data_to_2byte_int KEYWORD2 -data_to_2byte_float KEYWORD2 -data_to_4byte_float KEYWORD2 -data_to_3byte_color KEYWORD2 -data_to_3byte_time KEYWORD2 -data_to_3byte_data KEYWORD2 - -# constants -knx LITERAL1 diff --git a/lib/esp-knx-ip-0.5.2/library.properties b/lib/esp-knx-ip-0.5.2/library.properties deleted file mode 100644 index f3b86de9c..000000000 --- a/lib/esp-knx-ip-0.5.2/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name=ESP KNX IP Library -version=0.5.2 -author=Nico Weichbrodt -maintainer=Nico Weichbrodt -sentence=ESP8266 library for KNX/IP communication. -paragraph=Build your own IoT devices with KNX/IP connectivity! -category=Communication -url=https://github.com/envy/esp-knx-ip -architectures=esp8266 -includes=esp-knx-ip.h From af6fe55a1350e7fa8fdd151b60a036e1a54ee2f6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 13:34:25 +0100 Subject: [PATCH 32/38] Update platformio_override_sample.ini --- platformio_override_sample.ini | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 9bd30b21f..299452daf 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -82,20 +82,19 @@ shared_libdeps_dir = lib ; *** If you dont know what it is all about, do not change lib_extra_dirs = ; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! - lib_basic + lib/lib_basic ; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled - lib_i2c + lib/lib_i2c ; *** Displays. Disable if you dont have any Display activated - lib_display +; lib/lib_display ; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated - lib_ssl +; lib/lib_ssl ; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable -; lib_audio +; lib/lib_audio ; *** RF 433 stuff (not RF Bridge). Recommended to disable - lib_rf +; lib/lib_rf ; *** Mostly not used functions. Recommended to disable -; lib_div - +; lib/lib_div [core] ; Activate only (one set) if you want to override the standard core defined in platformio.ini !!! From e454c54e6dd0c1c31ae43bd53f0f35cf28bccb1e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 26 Oct 2020 12:51:06 +0000 Subject: [PATCH 33/38] move libs in folder lib --- .../AT24C256_512/Eeprom24C128_256.cpp | 0 .../AT24C256_512/Eeprom24C128_256.h | 0 .../AT24C256_512/Eeprom24C512.cpp | 0 lib/{ => default}/AT24C256_512/Eeprom24C512.h | 0 .../AT24C256_512/library.properties | 0 .../PubSubClient-EspEasy-2.7.12/.gitignore | 0 .../PubSubClient-EspEasy-2.7.12/.travis.yml | 0 .../PubSubClient-EspEasy-2.7.12/CHANGES.txt | 0 .../PubSubClient-EspEasy-2.7.12/LICENSE.txt | 0 .../PubSubClient-EspEasy-2.7.12/README.md | 0 .../examples/mqtt_auth/mqtt_auth.ino | 0 .../examples/mqtt_basic/mqtt_basic.ino | 0 .../examples/mqtt_esp8266/mqtt_esp8266.ino | 0 .../mqtt_large_message/mqtt_large_message.ino | 0 .../mqtt_publish_in_callback.ino | 0 .../mqtt_reconnect_nonblocking.ino | 0 .../examples/mqtt_stream/mqtt_stream.ino | 0 .../PubSubClient-EspEasy-2.7.12/keywords.txt | 0 .../PubSubClient-EspEasy-2.7.12/library.json | 0 .../library.properties | 0 .../src/PubSubClient.cpp | 0 .../src/PubSubClient.h | 0 .../tests/.gitignore | 0 .../tests/Makefile | 0 .../tests/README.md | 0 .../tests/src/connect_spec.cpp | 0 .../tests/src/keepalive_spec.cpp | 0 .../tests/src/lib/Arduino.h | 0 .../tests/src/lib/BDDTest.cpp | 0 .../tests/src/lib/BDDTest.h | 0 .../tests/src/lib/Buffer.cpp | 0 .../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 | 0 .../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 | 0 .../tests/src/subscribe_spec.cpp | 0 .../tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 0 .../testcases/mqtt_publish_in_callback.py | 0 .../tests/testcases/settings.py | 0 .../tests/testsuite.py | 0 .../TasmotaSerial-3.1.0/README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../TasmotaSerial-3.1.0/keywords.txt | 0 .../TasmotaSerial-3.1.0/library.json | 0 .../TasmotaSerial-3.1.0/library.properties | 0 .../TasmotaSerial-3.1.0/src/TasmotaSerial.cpp | 0 .../TasmotaSerial-3.1.0/src/TasmotaSerial.h | 0 .../UdpListener/library.properties | 0 .../UdpListener/src/UdpListener.h | 0 .../generator/generator.c | 0 .../generator/remapping.xlsx | Bin .../Unishox-1.0-shadinger/library.properties | 0 .../Unishox-1.0-shadinger/python/unishox.py | 0 .../Unishox-1.0-shadinger/src/unishox.cpp | 0 .../Unishox-1.0-shadinger/src/unishox.h | 0 lib/{ => default}/headers/DPT.h | 0 lib/{ => default}/headers/esp-knx-ip.h | 0 lib/{ => default}/headers/readme.txt | 0 .../jsmn-shadinger-1.0/README.md | 0 .../jsmn-shadinger-1.0/library.properties | 0 .../jsmn-shadinger-1.0/src/JsonGenerator.cpp | 0 .../jsmn-shadinger-1.0/src/JsonGenerator.h | 0 .../jsmn-shadinger-1.0/src/JsonParser.cpp | 0 .../jsmn-shadinger-1.0/src/JsonParser.h | 0 .../jsmn-shadinger-1.0/src/jsmn.cpp | 0 .../jsmn-shadinger-1.0/src/jsmn.h | 0 .../jsmn-shadinger-1.0/test/test-json.cpp | 0 .../.github/workflows/pr-or-master-push.yml | 0 .../lib_audio}/ESP8266Audio/LICENSE | 0 .../lib_audio}/ESP8266Audio/README.md | 0 .../examples/MixerSample/MixerSample.ino | 0 .../ESP8266Audio/examples/MixerSample/viola.h | 0 .../PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino | 0 .../examples/PlayAACFromPROGMEM/homer.aac | Bin .../examples/PlayAACFromPROGMEM/sampleaac.h | 0 .../PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino | 0 .../PlayFLACFromPROGMEMToDAC.ino | 0 .../PlayFLACFromPROGMEMToDAC/sample.h | 0 .../PlayMIDIFromLittleFS.ino | 0 .../PlayMIDIFromLittleFS/data/1mgm.sf2 | Bin .../PlayMIDIFromLittleFS/data/furelise.mid | Bin .../PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino | 0 .../examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 | Bin .../PlayMIDIFromSPIFFS/data/furelise.mid | Bin .../PlayMODFromPROGMEMToDAC.ino | 0 .../examples/PlayMODFromPROGMEMToDAC/enigma.h | 0 .../PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino | 0 .../PlayMP3FromSPIFFS/data/pno-cs.mp3 | Bin .../PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino | 0 .../PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino | 0 .../data/gs-16b-2c-44100hz.opus | Bin .../PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino | 0 .../PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino | 0 .../examples/PlayWAVFromPROGMEM/viola.h | 0 .../StreamMP3FromHTTP/StreamMP3FromHTTP.ino | 0 .../Schema_Spiram.png | Bin .../StreamMP3FromHTTP_SPIRAM.ino | 0 .../TalkingClockI2S/TalkingClockI2S.ino | 0 .../examples/WebRadio/WebRadio.ino | 0 .../ESP8266Audio/examples/WebRadio/web.cpp | 0 .../ESP8266Audio/examples/WebRadio/web.h | 0 .../lib_audio}/ESP8266Audio/keywords.txt | 0 .../lib_audio}/ESP8266Audio/library.json | 0 .../ESP8266Audio/library.properties | 0 .../ESP8266Audio/src/AudioFileSource.h | 0 .../src/AudioFileSourceBuffer.cpp | 0 .../ESP8266Audio/src/AudioFileSourceBuffer.h | 0 .../ESP8266Audio/src/AudioFileSourceFATFS.h | 0 .../ESP8266Audio/src/AudioFileSourceFS.cpp | 0 .../ESP8266Audio/src/AudioFileSourceFS.h | 0 .../src/AudioFileSourceHTTPStream.cpp | 0 .../src/AudioFileSourceHTTPStream.h | 0 .../src/AudioFileSourceICYStream.cpp | 0 .../src/AudioFileSourceICYStream.h | 0 .../ESP8266Audio/src/AudioFileSourceID3.cpp | 0 .../ESP8266Audio/src/AudioFileSourceID3.h | 0 .../src/AudioFileSourceLittleFS.h | 0 .../src/AudioFileSourcePROGMEM.cpp | 0 .../ESP8266Audio/src/AudioFileSourcePROGMEM.h | 0 .../ESP8266Audio/src/AudioFileSourceSD.cpp | 0 .../ESP8266Audio/src/AudioFileSourceSD.h | 0 .../ESP8266Audio/src/AudioFileSourceSPIFFS.h | 0 .../src/AudioFileSourceSPIRAMBuffer.cpp | 0 .../src/AudioFileSourceSPIRAMBuffer.h | 0 .../ESP8266Audio/src/AudioFileSourceSTDIO.cpp | 0 .../ESP8266Audio/src/AudioFileSourceSTDIO.h | 0 .../ESP8266Audio/src/AudioFileStream.cpp | 0 .../ESP8266Audio/src/AudioFileStream.h | 0 .../ESP8266Audio/src/AudioGenerator.h | 0 .../ESP8266Audio/src/AudioGeneratorAAC.cpp | 0 .../ESP8266Audio/src/AudioGeneratorAAC.h | 0 .../ESP8266Audio/src/AudioGeneratorFLAC.cpp | 0 .../ESP8266Audio/src/AudioGeneratorFLAC.h | 0 .../ESP8266Audio/src/AudioGeneratorMIDI.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMIDI.h | 0 .../ESP8266Audio/src/AudioGeneratorMOD.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMOD.h | 0 .../ESP8266Audio/src/AudioGeneratorMP3.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMP3.h | 0 .../ESP8266Audio/src/AudioGeneratorMP3a.cpp | 0 .../ESP8266Audio/src/AudioGeneratorMP3a.h | 0 .../ESP8266Audio/src/AudioGeneratorOpus.cpp | 0 .../ESP8266Audio/src/AudioGeneratorOpus.h | 0 .../ESP8266Audio/src/AudioGeneratorRTTTL.cpp | 0 .../ESP8266Audio/src/AudioGeneratorRTTTL.h | 0 .../ESP8266Audio/src/AudioGeneratorTalkie.cpp | 0 .../ESP8266Audio/src/AudioGeneratorTalkie.h | 0 .../ESP8266Audio/src/AudioGeneratorWAV.cpp | 0 .../ESP8266Audio/src/AudioGeneratorWAV.h | 0 .../ESP8266Audio/src/AudioLogger.cpp | 0 .../lib_audio}/ESP8266Audio/src/AudioLogger.h | 0 .../lib_audio}/ESP8266Audio/src/AudioOutput.h | 0 .../ESP8266Audio/src/AudioOutputBuffer.cpp | 0 .../ESP8266Audio/src/AudioOutputBuffer.h | 0 .../src/AudioOutputFilterDecimate.cpp | 0 .../src/AudioOutputFilterDecimate.h | 0 .../ESP8266Audio/src/AudioOutputI2S.cpp | 0 .../ESP8266Audio/src/AudioOutputI2S.h | 0 .../ESP8266Audio/src/AudioOutputI2SNoDAC.cpp | 0 .../ESP8266Audio/src/AudioOutputI2SNoDAC.h | 0 .../ESP8266Audio/src/AudioOutputMixer.cpp | 0 .../ESP8266Audio/src/AudioOutputMixer.h | 0 .../ESP8266Audio/src/AudioOutputNull.h | 0 .../ESP8266Audio/src/AudioOutputSPDIF.cpp | 0 .../ESP8266Audio/src/AudioOutputSPDIF.h | 0 .../ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp | 0 .../ESP8266Audio/src/AudioOutputSPIFFSWAV.h | 0 .../ESP8266Audio/src/AudioOutputSTDIO.cpp | 0 .../ESP8266Audio/src/AudioOutputSTDIO.h | 0 .../ESP8266Audio/src/AudioOutputSerialWAV.cpp | 0 .../ESP8266Audio/src/AudioOutputSerialWAV.h | 0 .../lib_audio}/ESP8266Audio/src/AudioStatus.h | 0 .../src/driver/SinglePinI2SDriver.cpp | 0 .../src/driver/SinglePinI2SDriver.h | 0 .../ESP8266Audio/src/libflac/AUTHORS | 0 .../ESP8266Audio/src/libflac/COPYING.FDL | 0 .../ESP8266Audio/src/libflac/COPYING.GPL | 0 .../ESP8266Audio/src/libflac/COPYING.LGPL | 0 .../ESP8266Audio/src/libflac/COPYING.Xiph | 0 .../ESP8266Audio/src/libflac/FLAC/assert.h | 0 .../ESP8266Audio/src/libflac/FLAC/callback.h | 0 .../ESP8266Audio/src/libflac/FLAC/export.h | 0 .../ESP8266Audio/src/libflac/FLAC/format.h | 0 .../ESP8266Audio/src/libflac/FLAC/metadata.h | 0 .../ESP8266Audio/src/libflac/FLAC/ordinals.h | 0 .../src/libflac/FLAC/stream_decoder.h | 0 .../ESP8266Audio/src/libflac/README | 0 .../ESP8266Audio/src/libflac/README.ESP8266 | 0 .../ESP8266Audio/src/libflac/bitmath.c | 0 .../ESP8266Audio/src/libflac/bitreader.c | 0 .../ESP8266Audio/src/libflac/config.h | 0 .../lib_audio}/ESP8266Audio/src/libflac/cpu.c | 0 .../lib_audio}/ESP8266Audio/src/libflac/crc.c | 0 .../ESP8266Audio/src/libflac/fixed.c | 0 .../ESP8266Audio/src/libflac/float.c | 0 .../ESP8266Audio/src/libflac/format.c | 0 .../lib_audio}/ESP8266Audio/src/libflac/lpc.c | 0 .../lib_audio}/ESP8266Audio/src/libflac/md5.c | 0 .../ESP8266Audio/src/libflac/memory.c | 0 .../src/libflac/private/bitmath.h | 0 .../src/libflac/private/bitreader.h | 0 .../ESP8266Audio/src/libflac/private/cpu.h | 0 .../ESP8266Audio/src/libflac/private/crc.h | 0 .../ESP8266Audio/src/libflac/private/fixed.h | 0 .../ESP8266Audio/src/libflac/private/float.h | 0 .../ESP8266Audio/src/libflac/private/format.h | 0 .../ESP8266Audio/src/libflac/private/lpc.h | 0 .../ESP8266Audio/src/libflac/private/macros.h | 0 .../ESP8266Audio/src/libflac/private/md5.h | 0 .../ESP8266Audio/src/libflac/private/memory.h | 0 .../src/libflac/private/metadata.h | 0 .../ESP8266Audio/src/libflac/private/window.h | 0 .../ESP8266Audio/src/libflac/protected/all.h | 0 .../src/libflac/protected/stream_decoder.h | 0 .../src/libflac/protected/stream_encoder.h | 0 .../ESP8266Audio/src/libflac/share/alloc.h | 0 .../ESP8266Audio/src/libflac/share/compat.h | 0 .../ESP8266Audio/src/libflac/share/endswap.h | 0 .../ESP8266Audio/src/libflac/share/getopt.h | 0 .../ESP8266Audio/src/libflac/share/macros.h | 0 .../ESP8266Audio/src/libflac/share/private.h | 0 .../ESP8266Audio/src/libflac/share/safe_str.h | 0 .../ESP8266Audio/src/libflac/share/utf8.h | 0 .../ESP8266Audio/src/libflac/stream_decoder.c | 0 .../ESP8266Audio/src/libflac/window.c | 0 .../ESP8266Audio/src/libhelix-aac/aaccommon.h | 0 .../ESP8266Audio/src/libhelix-aac/aacdec.c | 0 .../ESP8266Audio/src/libhelix-aac/aacdec.h | 0 .../ESP8266Audio/src/libhelix-aac/aactabs.c | 0 .../ESP8266Audio/src/libhelix-aac/assembly.h | 0 .../ESP8266Audio/src/libhelix-aac/bitstream.c | 0 .../ESP8266Audio/src/libhelix-aac/bitstream.h | 0 .../ESP8266Audio/src/libhelix-aac/buffers.c | 0 .../ESP8266Audio/src/libhelix-aac/coder.h | 0 .../ESP8266Audio/src/libhelix-aac/dct4.c | 0 .../ESP8266Audio/src/libhelix-aac/decelmnt.c | 0 .../ESP8266Audio/src/libhelix-aac/dequant.c | 0 .../ESP8266Audio/src/libhelix-aac/fft.c | 0 .../ESP8266Audio/src/libhelix-aac/filefmt.c | 0 .../ESP8266Audio/src/libhelix-aac/huffman.c | 0 .../ESP8266Audio/src/libhelix-aac/hufftabs.c | 0 .../ESP8266Audio/src/libhelix-aac/imdct.c | 0 .../ESP8266Audio/src/libhelix-aac/noiseless.c | 0 .../ESP8266Audio/src/libhelix-aac/pns.c | 0 .../ESP8266Audio/src/libhelix-aac/readme.txt | 0 .../ESP8266Audio/src/libhelix-aac/sbr.c | 0 .../ESP8266Audio/src/libhelix-aac/sbr.h | 0 .../ESP8266Audio/src/libhelix-aac/sbrfft.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrfreq.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhfadj.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhfgen.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrhuff.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrimdct.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrmath.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrqmf.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrside.c | 0 .../ESP8266Audio/src/libhelix-aac/sbrtabs.c | 0 .../ESP8266Audio/src/libhelix-aac/statname.h | 0 .../ESP8266Audio/src/libhelix-aac/stproc.c | 0 .../ESP8266Audio/src/libhelix-aac/tns.c | 0 .../ESP8266Audio/src/libhelix-aac/trigtabs.c | 0 .../ESP8266Audio/src/libhelix-mp3/LICENSE.txt | 0 .../ESP8266Audio/src/libhelix-mp3/RCSL.txt | 0 .../ESP8266Audio/src/libhelix-mp3/RPSL.txt | 0 .../ESP8266Audio/src/libhelix-mp3/assembly.h | 0 .../ESP8266Audio/src/libhelix-mp3/bitstream.c | 0 .../ESP8266Audio/src/libhelix-mp3/buffers.c | 0 .../ESP8266Audio/src/libhelix-mp3/coder.h | 0 .../ESP8266Audio/src/libhelix-mp3/dct32.c | 0 .../ESP8266Audio/src/libhelix-mp3/dequant.c | 0 .../ESP8266Audio/src/libhelix-mp3/dqchan.c | 0 .../ESP8266Audio/src/libhelix-mp3/huffman.c | 0 .../ESP8266Audio/src/libhelix-mp3/hufftabs.c | 0 .../ESP8266Audio/src/libhelix-mp3/imdct.c | 0 .../ESP8266Audio/src/libhelix-mp3/mp3common.h | 0 .../ESP8266Audio/src/libhelix-mp3/mp3dec.c | 0 .../ESP8266Audio/src/libhelix-mp3/mp3dec.h | 0 .../ESP8266Audio/src/libhelix-mp3/mp3tabs.c | 0 .../src/libhelix-mp3/mpadecobjfixpt.h | 0 .../ESP8266Audio/src/libhelix-mp3/player.h | 0 .../ESP8266Audio/src/libhelix-mp3/polyphase.c | 0 .../ESP8266Audio/src/libhelix-mp3/scalfact.c | 0 .../ESP8266Audio/src/libhelix-mp3/statname.h | 0 .../ESP8266Audio/src/libhelix-mp3/stproc.c | 0 .../ESP8266Audio/src/libhelix-mp3/subband.c | 0 .../ESP8266Audio/src/libhelix-mp3/trigtabs.c | 0 .../ESP8266Audio/src/libmad/CHANGES | 0 .../ESP8266Audio/src/libmad/COPYING | 0 .../ESP8266Audio/src/libmad/COPYRIGHT | 0 .../ESP8266Audio/src/libmad/CREDITS | 0 .../ESP8266Audio/src/libmad/D.dat.h | 0 .../ESP8266Audio/src/libmad/LICENSE | 0 .../lib_audio}/ESP8266Audio/src/libmad/README | 0 .../ESP8266Audio/src/libmad/README.ESP8266 | 0 .../lib_audio}/ESP8266Audio/src/libmad/TODO | 0 .../ESP8266Audio/src/libmad/VERSION | 0 .../lib_audio}/ESP8266Audio/src/libmad/bit.c | 0 .../lib_audio}/ESP8266Audio/src/libmad/bit.h | 0 .../ESP8266Audio/src/libmad/config.h | 0 .../ESP8266Audio/src/libmad/decoder.c | 0 .../ESP8266Audio/src/libmad/decoder.h | 0 .../ESP8266Audio/src/libmad/fixed.c | 0 .../ESP8266Audio/src/libmad/fixed.h | 0 .../ESP8266Audio/src/libmad/frame.c | 0 .../ESP8266Audio/src/libmad/frame.h | 0 .../ESP8266Audio/src/libmad/global.h | 0 .../ESP8266Audio/src/libmad/huffman.c | 0 .../ESP8266Audio/src/libmad/huffman.h | 0 .../ESP8266Audio/src/libmad/imdct_s.dat.h | 0 .../ESP8266Audio/src/libmad/layer3.c | 0 .../ESP8266Audio/src/libmad/layer3.h | 0 .../lib_audio}/ESP8266Audio/src/libmad/mad.h | 0 .../ESP8266Audio/src/libmad/mad.h.sed | 0 .../ESP8266Audio/src/libmad/qc_table.dat.h | 0 .../ESP8266Audio/src/libmad/rq_table.dat.h | 0 .../ESP8266Audio/src/libmad/sf_table.dat.h | 0 .../ESP8266Audio/src/libmad/stream.c | 0 .../ESP8266Audio/src/libmad/stream.h | 0 .../ESP8266Audio/src/libmad/synth.c | 0 .../ESP8266Audio/src/libmad/synth.h | 0 .../ESP8266Audio/src/libmad/timer.c | 0 .../ESP8266Audio/src/libmad/timer.h | 0 .../ESP8266Audio/src/libmad/version.c | 0 .../ESP8266Audio/src/libmad/version.h | 0 .../ESP8266Audio/src/libogg/AUTHORS | 0 .../ESP8266Audio/src/libogg/CHANGES | 0 .../ESP8266Audio/src/libogg/COPYING | 0 .../ESP8266Audio/src/libogg/README.esp8266.md | 0 .../ESP8266Audio/src/libogg/README.md | 0 .../ESP8266Audio/src/libogg/bitwise.c | 0 .../ESP8266Audio/src/libogg/config.h | 0 .../ESP8266Audio/src/libogg/crctable.h | 0 .../ESP8266Audio/src/libogg/framing.c | 0 .../lib_audio}/ESP8266Audio/src/libogg/ogg.pc | 0 .../src/libogg/ogg/config_types.h | 0 .../ESP8266Audio/src/libogg/ogg/ogg.h | 0 .../ESP8266Audio/src/libogg/ogg/os_types.h | 0 .../ESP8266Audio/src/libopus/AUTHORS | 0 .../ESP8266Audio/src/libopus/COPYING | 0 .../ESP8266Audio/src/libopus/ChangeLog | 0 .../ESP8266Audio/src/libopus/INSTALL | 0 .../lib_audio}/ESP8266Audio/src/libopus/NEWS | 0 .../ESP8266Audio/src/libopus/README | 0 .../ESP8266Audio/src/libopus/analysis.h | 0 .../src/libopus/celt/_kiss_fft_guts.h | 0 .../ESP8266Audio/src/libopus/celt/arch.h | 0 .../ESP8266Audio/src/libopus/celt/bands.c | 0 .../ESP8266Audio/src/libopus/celt/bands.h | 0 .../ESP8266Audio/src/libopus/celt/celt.c | 0 .../ESP8266Audio/src/libopus/celt/celt.h | 0 .../src/libopus/celt/celt_decoder.c | 0 .../src/libopus/celt/celt_encoder.c | 0 .../ESP8266Audio/src/libopus/celt/celt_lpc.c | 0 .../ESP8266Audio/src/libopus/celt/celt_lpc.h | 0 .../src/libopus/celt/cpu_support.h | 0 .../ESP8266Audio/src/libopus/celt/cwrs.c | 0 .../ESP8266Audio/src/libopus/celt/cwrs.h | 0 .../ESP8266Audio/src/libopus/celt/ecintrin.h | 0 .../ESP8266Audio/src/libopus/celt/entcode.c | 0 .../ESP8266Audio/src/libopus/celt/entcode.h | 0 .../ESP8266Audio/src/libopus/celt/entdec.c | 0 .../ESP8266Audio/src/libopus/celt/entdec.h | 0 .../ESP8266Audio/src/libopus/celt/entenc.c | 0 .../ESP8266Audio/src/libopus/celt/entenc.h | 0 .../src/libopus/celt/fixed_debug.h | 0 .../src/libopus/celt/fixed_generic.h | 0 .../src/libopus/celt/float_cast.h | 0 .../ESP8266Audio/src/libopus/celt/kiss_fft.c | 0 .../ESP8266Audio/src/libopus/celt/kiss_fft.h | 0 .../ESP8266Audio/src/libopus/celt/laplace.c | 0 .../ESP8266Audio/src/libopus/celt/laplace.h | 0 .../ESP8266Audio/src/libopus/celt/mathops.c | 0 .../ESP8266Audio/src/libopus/celt/mathops.h | 0 .../ESP8266Audio/src/libopus/celt/mdct.c | 0 .../ESP8266Audio/src/libopus/celt/mdct.h | 0 .../ESP8266Audio/src/libopus/celt/mfrngcod.h | 0 .../ESP8266Audio/src/libopus/celt/modes.c | 0 .../ESP8266Audio/src/libopus/celt/modes.h | 0 .../src/libopus/celt/os_support.h | 0 .../ESP8266Audio/src/libopus/celt/pitch.c | 0 .../ESP8266Audio/src/libopus/celt/pitch.h | 0 .../src/libopus/celt/quant_bands.c | 0 .../src/libopus/celt/quant_bands.h | 0 .../ESP8266Audio/src/libopus/celt/rate.c | 0 .../ESP8266Audio/src/libopus/celt/rate.h | 0 .../src/libopus/celt/stack_alloc.h | 0 .../src/libopus/celt/static_modes_fixed.h | 0 .../src/libopus/celt/static_modes_float.h | 0 .../ESP8266Audio/src/libopus/celt/vq.c | 0 .../ESP8266Audio/src/libopus/celt/vq.h | 0 .../ESP8266Audio/src/libopus/config.h | 0 .../ESP8266Audio/src/libopus/mapping_matrix.c | 0 .../ESP8266Audio/src/libopus/mapping_matrix.h | 0 .../lib_audio}/ESP8266Audio/src/libopus/mlp.h | 0 .../ESP8266Audio/src/libopus/opus.c | 0 .../ESP8266Audio/src/libopus/opus.h | 0 .../ESP8266Audio/src/libopus/opus.pc | 0 .../ESP8266Audio/src/libopus/opus_custom.h | 0 .../ESP8266Audio/src/libopus/opus_decoder.c | 0 .../ESP8266Audio/src/libopus/opus_defines.h | 0 .../ESP8266Audio/src/libopus/opus_encoder.c | 0 .../src/libopus/opus_multistream.c | 0 .../src/libopus/opus_multistream.h | 0 .../src/libopus/opus_multistream_decoder.c | 0 .../src/libopus/opus_multistream_encoder.c | 0 .../ESP8266Audio/src/libopus/opus_private.h | 0 .../src/libopus/opus_projection.h | 0 .../src/libopus/opus_projection_decoder.c | 0 .../src/libopus/opus_projection_encoder.c | 0 .../ESP8266Audio/src/libopus/opus_types.h | 0 .../ESP8266Audio/src/libopus/repacketizer.c | 0 .../ESP8266Audio/src/libopus/silk/A2NLSF.c | 0 .../ESP8266Audio/src/libopus/silk/API.h | 0 .../ESP8266Audio/src/libopus/silk/CNG.c | 0 .../src/libopus/silk/HP_variable_cutoff.c | 0 .../ESP8266Audio/src/libopus/silk/Inlines.h | 0 .../src/libopus/silk/LPC_analysis_filter.c | 0 .../ESP8266Audio/src/libopus/silk/LPC_fit.c | 0 .../src/libopus/silk/LPC_inv_pred_gain.c | 0 .../src/libopus/silk/LP_variable_cutoff.c | 0 .../src/libopus/silk/MacroCount.h | 0 .../src/libopus/silk/MacroDebug.h | 0 .../ESP8266Audio/src/libopus/silk/NLSF2A.c | 0 .../ESP8266Audio/src/libopus/silk/NLSF_VQ.c | 0 .../src/libopus/silk/NLSF_VQ_weights_laroia.c | 0 .../src/libopus/silk/NLSF_decode.c | 0 .../src/libopus/silk/NLSF_del_dec_quant.c | 0 .../src/libopus/silk/NLSF_encode.c | 0 .../src/libopus/silk/NLSF_stabilize.c | 0 .../src/libopus/silk/NLSF_unpack.c | 0 .../ESP8266Audio/src/libopus/silk/NSQ.c | 0 .../ESP8266Audio/src/libopus/silk/NSQ.h | 0 .../src/libopus/silk/NSQ_del_dec.c | 0 .../ESP8266Audio/src/libopus/silk/PLC.c | 0 .../ESP8266Audio/src/libopus/silk/PLC.h | 0 .../src/libopus/silk/SigProc_FIX.h | 0 .../ESP8266Audio/src/libopus/silk/VAD.c | 0 .../src/libopus/silk/VQ_WMat_EC.c | 0 .../src/libopus/silk/ana_filt_bank_1.c | 0 .../src/libopus/silk/biquad_alt.c | 0 .../src/libopus/silk/bwexpander.c | 0 .../src/libopus/silk/bwexpander_32.c | 0 .../src/libopus/silk/check_control_input.c | 0 .../src/libopus/silk/code_signs.c | 0 .../ESP8266Audio/src/libopus/silk/control.h | 0 .../src/libopus/silk/control_SNR.c | 0 .../libopus/silk/control_audio_bandwidth.c | 0 .../src/libopus/silk/control_codec.c | 0 .../ESP8266Audio/src/libopus/silk/debug.c | 0 .../ESP8266Audio/src/libopus/silk/debug.h | 0 .../ESP8266Audio/src/libopus/silk/dec_API.c | 0 .../src/libopus/silk/decode_core.c | 0 .../src/libopus/silk/decode_frame.c | 0 .../src/libopus/silk/decode_indices.c | 0 .../src/libopus/silk/decode_parameters.c | 0 .../src/libopus/silk/decode_pitch.c | 0 .../src/libopus/silk/decode_pulses.c | 0 .../src/libopus/silk/decoder_set_fs.c | 0 .../ESP8266Audio/src/libopus/silk/define.h | 0 .../ESP8266Audio/src/libopus/silk/enc_API.c | 0 .../src/libopus/silk/encode_indices.c | 0 .../src/libopus/silk/encode_pulses.c | 0 .../ESP8266Audio/src/libopus/silk/errors.h | 0 .../silk/fixed/LTP_analysis_filter_FIX.c | 0 .../silk/fixed/LTP_analysis_filter_FIX.lo | 0 .../silk/fixed/LTP_analysis_filter_FIX.o | Bin .../libopus/silk/fixed/LTP_scale_ctrl_FIX.c | 0 .../libopus/silk/fixed/LTP_scale_ctrl_FIX.lo | 0 .../libopus/silk/fixed/LTP_scale_ctrl_FIX.o | Bin .../silk/fixed/apply_sine_window_FIX.c | 0 .../silk/fixed/apply_sine_window_FIX.lo | 0 .../silk/fixed/apply_sine_window_FIX.o | Bin .../src/libopus/silk/fixed/autocorr_FIX.c | 0 .../src/libopus/silk/fixed/autocorr_FIX.lo | 0 .../src/libopus/silk/fixed/autocorr_FIX.o | Bin .../libopus/silk/fixed/burg_modified_FIX.c | 0 .../libopus/silk/fixed/burg_modified_FIX.lo | 0 .../libopus/silk/fixed/burg_modified_FIX.o | Bin .../src/libopus/silk/fixed/corrMatrix_FIX.c | 0 .../src/libopus/silk/fixed/corrMatrix_FIX.lo | 0 .../src/libopus/silk/fixed/corrMatrix_FIX.o | Bin .../src/libopus/silk/fixed/encode_frame_FIX.c | 0 .../libopus/silk/fixed/encode_frame_FIX.lo | 0 .../src/libopus/silk/fixed/encode_frame_FIX.o | Bin .../src/libopus/silk/fixed/find_LPC_FIX.c | 0 .../src/libopus/silk/fixed/find_LPC_FIX.lo | 0 .../src/libopus/silk/fixed/find_LPC_FIX.o | Bin .../src/libopus/silk/fixed/find_LTP_FIX.c | 0 .../src/libopus/silk/fixed/find_LTP_FIX.lo | 0 .../src/libopus/silk/fixed/find_LTP_FIX.o | Bin .../libopus/silk/fixed/find_pitch_lags_FIX.c | 0 .../libopus/silk/fixed/find_pitch_lags_FIX.lo | 0 .../libopus/silk/fixed/find_pitch_lags_FIX.o | Bin .../libopus/silk/fixed/find_pred_coefs_FIX.c | 0 .../libopus/silk/fixed/find_pred_coefs_FIX.lo | 0 .../libopus/silk/fixed/find_pred_coefs_FIX.o | Bin .../src/libopus/silk/fixed/k2a_FIX.c | 0 .../src/libopus/silk/fixed/k2a_FIX.lo | 0 .../src/libopus/silk/fixed/k2a_FIX.o | Bin .../src/libopus/silk/fixed/k2a_Q16_FIX.c | 0 .../src/libopus/silk/fixed/k2a_Q16_FIX.lo | 0 .../src/libopus/silk/fixed/k2a_Q16_FIX.o | Bin .../src/libopus/silk/fixed/main_FIX.h | 0 .../silk/fixed/noise_shape_analysis_FIX.c | 0 .../silk/fixed/noise_shape_analysis_FIX.lo | 0 .../silk/fixed/noise_shape_analysis_FIX.o | Bin .../silk/fixed/pitch_analysis_core_FIX.c | 0 .../silk/fixed/pitch_analysis_core_FIX.lo | 0 .../silk/fixed/pitch_analysis_core_FIX.o | Bin .../libopus/silk/fixed/process_gains_FIX.c | 0 .../libopus/silk/fixed/process_gains_FIX.lo | 0 .../libopus/silk/fixed/process_gains_FIX.o | Bin .../silk/fixed/regularize_correlations_FIX.c | 0 .../silk/fixed/regularize_correlations_FIX.lo | 0 .../silk/fixed/regularize_correlations_FIX.o | Bin .../silk/fixed/residual_energy16_FIX.c | 0 .../silk/fixed/residual_energy16_FIX.lo | 0 .../silk/fixed/residual_energy16_FIX.o | Bin .../libopus/silk/fixed/residual_energy_FIX.c | 0 .../libopus/silk/fixed/residual_energy_FIX.lo | 0 .../libopus/silk/fixed/residual_energy_FIX.o | Bin .../src/libopus/silk/fixed/schur64_FIX.c | 0 .../src/libopus/silk/fixed/schur64_FIX.lo | 0 .../src/libopus/silk/fixed/schur64_FIX.o | Bin .../src/libopus/silk/fixed/schur_FIX.c | 0 .../src/libopus/silk/fixed/schur_FIX.lo | 0 .../src/libopus/silk/fixed/schur_FIX.o | Bin .../src/libopus/silk/fixed/structs_FIX.h | 0 .../src/libopus/silk/fixed/vector_ops_FIX.c | 0 .../src/libopus/silk/fixed/vector_ops_FIX.lo | 0 .../src/libopus/silk/fixed/vector_ops_FIX.o | Bin .../silk/fixed/warped_autocorrelation_FIX.c | 0 .../silk/fixed/warped_autocorrelation_FIX.lo | 0 .../silk/fixed/warped_autocorrelation_FIX.o | Bin .../src/libopus/silk/gain_quant.c | 0 .../src/libopus/silk/init_decoder.c | 0 .../src/libopus/silk/init_encoder.c | 0 .../src/libopus/silk/inner_prod_aligned.c | 0 .../src/libopus/silk/interpolate.c | 0 .../ESP8266Audio/src/libopus/silk/lin2log.c | 0 .../ESP8266Audio/src/libopus/silk/log2lin.c | 0 .../ESP8266Audio/src/libopus/silk/macros.h | 0 .../ESP8266Audio/src/libopus/silk/main.h | 0 .../src/libopus/silk/pitch_est_defines.h | 0 .../src/libopus/silk/pitch_est_tables.c | 0 .../src/libopus/silk/process_NLSFs.c | 0 .../src/libopus/silk/quant_LTP_gains.c | 0 .../ESP8266Audio/src/libopus/silk/resampler.c | 0 .../src/libopus/silk/resampler_down2.c | 0 .../src/libopus/silk/resampler_down2_3.c | 0 .../src/libopus/silk/resampler_private.h | 0 .../src/libopus/silk/resampler_private_AR2.c | 0 .../libopus/silk/resampler_private_IIR_FIR.c | 0 .../libopus/silk/resampler_private_down_FIR.c | 0 .../libopus/silk/resampler_private_up2_HQ.c | 0 .../src/libopus/silk/resampler_rom.c | 0 .../src/libopus/silk/resampler_rom.h | 0 .../src/libopus/silk/resampler_structs.h | 0 .../src/libopus/silk/shell_coder.c | 0 .../ESP8266Audio/src/libopus/silk/sigm_Q15.c | 0 .../ESP8266Audio/src/libopus/silk/sort.c | 0 .../src/libopus/silk/stereo_LR_to_MS.c | 0 .../src/libopus/silk/stereo_MS_to_LR.c | 0 .../src/libopus/silk/stereo_decode_pred.c | 0 .../src/libopus/silk/stereo_encode_pred.c | 0 .../src/libopus/silk/stereo_find_predictor.c | 0 .../src/libopus/silk/stereo_quant_pred.c | 0 .../ESP8266Audio/src/libopus/silk/structs.h | 0 .../src/libopus/silk/sum_sqr_shift.c | 0 .../src/libopus/silk/table_LSF_cos.c | 0 .../ESP8266Audio/src/libopus/silk/tables.h | 0 .../src/libopus/silk/tables_LTP.c | 0 .../src/libopus/silk/tables_NLSF_CB_NB_MB.c | 0 .../src/libopus/silk/tables_NLSF_CB_WB.c | 0 .../src/libopus/silk/tables_gain.c | 0 .../src/libopus/silk/tables_other.c | 0 .../src/libopus/silk/tables_pitch_lag.c | 0 .../libopus/silk/tables_pulses_per_block.c | 0 .../src/libopus/silk/tuning_parameters.h | 0 .../ESP8266Audio/src/libopus/silk/typedef.h | 0 .../ESP8266Audio/src/libopus/tansig_table.h | 0 .../ESP8266Audio/src/libtinysoundfont/LICENSE | 0 .../src/libtinysoundfont/README.ESP8266 | 0 .../src/libtinysoundfont/README.md | 0 .../ESP8266Audio/src/libtinysoundfont/tsf.h | 0 .../ESP8266Audio/src/opusfile/AUTHORS | 0 .../ESP8266Audio/src/opusfile/COPYING | 0 .../src/opusfile/README.esp8266.md | 0 .../ESP8266Audio/src/opusfile/README.md | 0 .../ESP8266Audio/src/opusfile/config.h | 0 .../ESP8266Audio/src/opusfile/info.c | 0 .../ESP8266Audio/src/opusfile/internal.c | 0 .../ESP8266Audio/src/opusfile/internal.h | 0 .../ESP8266Audio/src/opusfile/opusfile.c | 0 .../ESP8266Audio/src/opusfile/opusfile.h | 0 .../ESP8266Audio/src/opusfile/opusfile.pc | 0 .../ESP8266Audio/src/opusfile/stream.c | 0 .../lib_audio}/ESP8266Audio/src/spiram-fast.h | 0 .../lib_audio}/ESP8266Audio/tests/common.sh | 0 .../ESP8266Audio/tests/host/Arduino.h | 0 .../ESP8266Audio/tests/host/Makefile | 0 .../ESP8266Audio/tests/host/Serial.cpp | 0 .../ESP8266Audio/tests/host/aac.cpp | 0 .../ESP8266Audio/tests/host/midi.cpp | 0 .../ESP8266Audio/tests/host/mp3.cpp | 0 .../ESP8266Audio/tests/host/opus.cpp | 0 .../ESP8266Audio/tests/host/pgmspace.h | 0 .../ESP8266Audio/tests/host/test_8u_16.wav | Bin .../ESP8266Audio/tests/host/wav.cpp | 0 .../lib_audio}/ESP8266SAM/README.md | 0 .../ESP8266SAM/examples/Speak/Speak.ino | 0 .../lib_audio}/ESP8266SAM/library.json | 0 .../lib_audio}/ESP8266SAM/library.properties | 0 .../lib_audio}/ESP8266SAM/src/ESP8266SAM.cpp | 0 .../lib_audio}/ESP8266SAM/src/ESP8266SAM.h | 0 .../lib_audio}/ESP8266SAM/src/ReciterTabs.h | 0 .../lib_audio}/ESP8266SAM/src/RenderTabs.h | 0 .../lib_audio}/ESP8266SAM/src/SamData.h | 0 .../lib_audio}/ESP8266SAM/src/SamTabs.h | 0 .../lib_audio}/ESP8266SAM/src/reciter.c | 0 .../lib_audio}/ESP8266SAM/src/reciter.h | 0 .../lib_audio}/ESP8266SAM/src/render.c | 0 .../lib_audio}/ESP8266SAM/src/render.h | 0 .../lib_audio}/ESP8266SAM/src/sam.c | 0 .../lib_audio}/ESP8266SAM/src/sam.h | 0 .../lib_audio}/ESP8266SAM/src/samdebug.c | 0 .../lib_audio}/ESP8266SAM/src/samdebug.h | 0 .../lib_basic}/C2Programmer-1.0.0/README.md | 0 .../C2Programmer-1.0.0/keywords.txt | 0 .../C2Programmer-1.0.0/library.json | 0 .../C2Programmer-1.0.0/library.properties | 0 .../lib_basic}/C2Programmer-1.0.0/src/c2.cpp | 0 .../lib_basic}/C2Programmer-1.0.0/src/c2.h | 0 .../lib_basic}/C2Programmer-1.0.0/src/ihx.cpp | 0 .../lib_basic}/C2Programmer-1.0.0/src/ihx.h | 0 .../.github/CONTRIBUTING.md | 0 .../.github/Contributors.md | 0 .../.github/issue_template.md | 0 .../IRremoteESP8266-2.7.11/.gitignore | 0 .../IRremoteESP8266-2.7.11/.gitmodules | 0 .../IRremoteESP8266-2.7.11/.style.yapf | 0 .../IRremoteESP8266-2.7.11/.travis.yml | 0 .../IRremoteESP8266-2.7.11/CPPLINT.cfg | 0 .../IRremoteESP8266-2.7.11/Doxyfile | 0 .../IRremoteESP8266-2.7.11/LICENSE.txt | 0 .../IRremoteESP8266-2.7.11/README.md | 0 .../IRremoteESP8266-2.7.11/README_fr.md | 0 .../IRremoteESP8266-2.7.11/ReleaseNotes.md | 0 .../SupportedProtocols.md | 0 .../IRremoteESP8266-2.7.11/docs/README.md | 0 .../IRremoteESP8266-2.7.11/docs/README_fr.md | 0 .../IRremoteESP8266-2.7.11/docs/_config.yml | 0 .../docs/doxygen/html/IRac_8cpp.html | 0 .../docs/doxygen/html/IRac_8h.html | 0 .../docs/doxygen/html/IRac_8h_source.html | 0 .../docs/doxygen/html/IRrecv_8cpp.html | 0 .../docs/doxygen/html/IRrecv_8h.html | 0 .../docs/doxygen/html/IRrecv_8h_source.html | 0 .../docs/doxygen/html/IRremoteESP8266_8h.html | 0 .../html/IRremoteESP8266_8h_source.html | 0 .../docs/doxygen/html/IRsend_8cpp.html | 0 .../docs/doxygen/html/IRsend_8h.html | 0 .../docs/doxygen/html/IRsend_8h_source.html | 0 .../docs/doxygen/html/IRtext_8cpp.html | 0 .../docs/doxygen/html/IRtext_8h.html | 0 .../docs/doxygen/html/IRtext_8h_source.html | 0 .../docs/doxygen/html/IRtimer_8cpp.html | 0 .../docs/doxygen/html/IRtimer_8h.html | 0 .../docs/doxygen/html/IRtimer_8h_source.html | 0 .../docs/doxygen/html/IRutils_8cpp.html | 0 .../docs/doxygen/html/IRutils_8h.html | 0 .../docs/doxygen/html/IRutils_8h_source.html | 0 .../docs/doxygen/html/README_8md.html | 0 .../docs/doxygen/html/annotated.html | 0 .../docs/doxygen/html/bc_s.png | Bin .../docs/doxygen/html/bdwn.png | Bin .../html/classIRAirwellAc-members.html | 0 .../docs/doxygen/html/classIRAirwellAc.html | 0 .../html/classIRAirwellAc__coll__graph.map | 0 .../html/classIRAirwellAc__coll__graph.md5 | 0 .../html/classIRAirwellAc__coll__graph.png | Bin .../doxygen/html/classIRAmcorAc-members.html | 0 .../docs/doxygen/html/classIRAmcorAc.html | 0 .../html/classIRAmcorAc__coll__graph.map | 0 .../html/classIRAmcorAc__coll__graph.md5 | 0 .../html/classIRAmcorAc__coll__graph.png | Bin .../doxygen/html/classIRArgoAC-members.html | 0 .../docs/doxygen/html/classIRArgoAC.html | 0 .../html/classIRArgoAC__coll__graph.map | 0 .../html/classIRArgoAC__coll__graph.md5 | 0 .../html/classIRArgoAC__coll__graph.png | Bin .../html/classIRCarrierAc64-members.html | 0 .../docs/doxygen/html/classIRCarrierAc64.html | 0 .../html/classIRCarrierAc64__coll__graph.map | 0 .../html/classIRCarrierAc64__coll__graph.md5 | 0 .../html/classIRCarrierAc64__coll__graph.png | Bin .../doxygen/html/classIRCoolixAC-members.html | 0 .../docs/doxygen/html/classIRCoolixAC.html | 0 .../html/classIRCoolixAC__coll__graph.map | 0 .../html/classIRCoolixAC__coll__graph.md5 | 0 .../html/classIRCoolixAC__coll__graph.png | Bin .../doxygen/html/classIRCoronaAc-members.html | 0 .../docs/doxygen/html/classIRCoronaAc.html | 0 .../html/classIRCoronaAc__coll__graph.map | 0 .../html/classIRCoronaAc__coll__graph.md5 | 0 .../html/classIRCoronaAc__coll__graph.png | Bin .../html/classIRDaikin128-members.html | 0 .../docs/doxygen/html/classIRDaikin128.html | 0 .../html/classIRDaikin128__coll__graph.map | 0 .../html/classIRDaikin128__coll__graph.md5 | 0 .../html/classIRDaikin128__coll__graph.png | Bin .../html/classIRDaikin152-members.html | 0 .../docs/doxygen/html/classIRDaikin152.html | 0 .../html/classIRDaikin152__coll__graph.map | 0 .../html/classIRDaikin152__coll__graph.md5 | 0 .../html/classIRDaikin152__coll__graph.png | Bin .../html/classIRDaikin160-members.html | 0 .../docs/doxygen/html/classIRDaikin160.html | 0 .../html/classIRDaikin160__coll__graph.map | 0 .../html/classIRDaikin160__coll__graph.md5 | 0 .../html/classIRDaikin160__coll__graph.png | Bin .../html/classIRDaikin176-members.html | 0 .../docs/doxygen/html/classIRDaikin176.html | 0 .../html/classIRDaikin176__coll__graph.map | 0 .../html/classIRDaikin176__coll__graph.md5 | 0 .../html/classIRDaikin176__coll__graph.png | Bin .../doxygen/html/classIRDaikin2-members.html | 0 .../docs/doxygen/html/classIRDaikin2.html | 0 .../html/classIRDaikin216-members.html | 0 .../docs/doxygen/html/classIRDaikin216.html | 0 .../html/classIRDaikin216__coll__graph.map | 0 .../html/classIRDaikin216__coll__graph.md5 | 0 .../html/classIRDaikin216__coll__graph.png | Bin .../html/classIRDaikin2__coll__graph.map | 0 .../html/classIRDaikin2__coll__graph.md5 | 0 .../html/classIRDaikin2__coll__graph.png | Bin .../doxygen/html/classIRDaikin64-members.html | 0 .../docs/doxygen/html/classIRDaikin64.html | 0 .../html/classIRDaikin64__coll__graph.map | 0 .../html/classIRDaikin64__coll__graph.md5 | 0 .../html/classIRDaikin64__coll__graph.png | Bin .../html/classIRDaikinESP-members.html | 0 .../docs/doxygen/html/classIRDaikinESP.html | 0 .../html/classIRDaikinESP__coll__graph.map | 0 .../html/classIRDaikinESP__coll__graph.md5 | 0 .../html/classIRDaikinESP__coll__graph.png | Bin .../html/classIRDelonghiAc-members.html | 0 .../docs/doxygen/html/classIRDelonghiAc.html | 0 .../html/classIRDelonghiAc__coll__graph.map | 0 .../html/classIRDelonghiAc__coll__graph.md5 | 0 .../html/classIRDelonghiAc__coll__graph.png | Bin .../html/classIRElectraAc-members.html | 0 .../docs/doxygen/html/classIRElectraAc.html | 0 .../html/classIRElectraAc__coll__graph.map | 0 .../html/classIRElectraAc__coll__graph.md5 | 0 .../html/classIRElectraAc__coll__graph.png | Bin .../html/classIRFujitsuAC-members.html | 0 .../docs/doxygen/html/classIRFujitsuAC.html | 0 .../html/classIRFujitsuAC__coll__graph.map | 0 .../html/classIRFujitsuAC__coll__graph.md5 | 0 .../html/classIRFujitsuAC__coll__graph.png | Bin .../html/classIRGoodweatherAc-members.html | 0 .../doxygen/html/classIRGoodweatherAc.html | 0 .../classIRGoodweatherAc__coll__graph.map | 0 .../classIRGoodweatherAc__coll__graph.md5 | 0 .../classIRGoodweatherAc__coll__graph.png | Bin .../doxygen/html/classIRGreeAC-members.html | 0 .../docs/doxygen/html/classIRGreeAC.html | 0 .../html/classIRGreeAC__coll__graph.map | 0 .../html/classIRGreeAC__coll__graph.md5 | 0 .../html/classIRGreeAC__coll__graph.png | Bin .../doxygen/html/classIRHaierAC-members.html | 0 .../docs/doxygen/html/classIRHaierAC.html | 0 .../html/classIRHaierACYRW02-members.html | 0 .../doxygen/html/classIRHaierACYRW02.html | 0 .../html/classIRHaierACYRW02__coll__graph.map | 0 .../html/classIRHaierACYRW02__coll__graph.md5 | 0 .../html/classIRHaierACYRW02__coll__graph.png | Bin .../html/classIRHaierAC__coll__graph.map | 0 .../html/classIRHaierAC__coll__graph.md5 | 0 .../html/classIRHaierAC__coll__graph.png | Bin .../html/classIRHitachiAc-members.html | 0 .../docs/doxygen/html/classIRHitachiAc.html | 0 .../html/classIRHitachiAc1-members.html | 0 .../docs/doxygen/html/classIRHitachiAc1.html | 0 .../html/classIRHitachiAc1__coll__graph.map | 0 .../html/classIRHitachiAc1__coll__graph.md5 | 0 .../html/classIRHitachiAc1__coll__graph.png | Bin .../html/classIRHitachiAc3-members.html | 0 .../docs/doxygen/html/classIRHitachiAc3.html | 0 .../html/classIRHitachiAc344-members.html | 0 .../doxygen/html/classIRHitachiAc344.html | 0 .../html/classIRHitachiAc344__coll__graph.map | 0 .../html/classIRHitachiAc344__coll__graph.md5 | 0 .../html/classIRHitachiAc344__coll__graph.png | Bin .../classIRHitachiAc344__inherit__graph.map | 0 .../classIRHitachiAc344__inherit__graph.md5 | 0 .../classIRHitachiAc344__inherit__graph.png | Bin .../html/classIRHitachiAc3__coll__graph.map | 0 .../html/classIRHitachiAc3__coll__graph.md5 | 0 .../html/classIRHitachiAc3__coll__graph.png | Bin .../html/classIRHitachiAc424-members.html | 0 .../doxygen/html/classIRHitachiAc424.html | 0 .../html/classIRHitachiAc424__coll__graph.map | 0 .../html/classIRHitachiAc424__coll__graph.md5 | 0 .../html/classIRHitachiAc424__coll__graph.png | Bin .../classIRHitachiAc424__inherit__graph.map | 0 .../classIRHitachiAc424__inherit__graph.md5 | 0 .../classIRHitachiAc424__inherit__graph.png | Bin .../html/classIRHitachiAc__coll__graph.map | 0 .../html/classIRHitachiAc__coll__graph.md5 | 0 .../html/classIRHitachiAc__coll__graph.png | Bin .../html/classIRKelvinatorAC-members.html | 0 .../doxygen/html/classIRKelvinatorAC.html | 0 .../html/classIRKelvinatorAC__coll__graph.map | 0 .../html/classIRKelvinatorAC__coll__graph.md5 | 0 .../html/classIRKelvinatorAC__coll__graph.png | Bin .../doxygen/html/classIRLgAc-members.html | 0 .../docs/doxygen/html/classIRLgAc.html | 0 .../doxygen/html/classIRLgAc__coll__graph.map | 0 .../doxygen/html/classIRLgAc__coll__graph.md5 | 0 .../doxygen/html/classIRLgAc__coll__graph.png | Bin .../doxygen/html/classIRMideaAC-members.html | 0 .../docs/doxygen/html/classIRMideaAC.html | 0 .../html/classIRMideaAC__coll__graph.map | 0 .../html/classIRMideaAC__coll__graph.md5 | 0 .../html/classIRMideaAC__coll__graph.png | Bin .../html/classIRMitsubishi112-members.html | 0 .../doxygen/html/classIRMitsubishi112.html | 0 .../classIRMitsubishi112__coll__graph.map | 0 .../classIRMitsubishi112__coll__graph.md5 | 0 .../classIRMitsubishi112__coll__graph.png | Bin .../html/classIRMitsubishi136-members.html | 0 .../doxygen/html/classIRMitsubishi136.html | 0 .../classIRMitsubishi136__coll__graph.map | 0 .../classIRMitsubishi136__coll__graph.md5 | 0 .../classIRMitsubishi136__coll__graph.png | Bin .../html/classIRMitsubishiAC-members.html | 0 .../doxygen/html/classIRMitsubishiAC.html | 0 .../html/classIRMitsubishiAC__coll__graph.map | 0 .../html/classIRMitsubishiAC__coll__graph.md5 | 0 .../html/classIRMitsubishiAC__coll__graph.png | Bin .../classIRMitsubishiHeavy152Ac-members.html | 0 .../html/classIRMitsubishiHeavy152Ac.html | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.map | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.md5 | 0 ...assIRMitsubishiHeavy152Ac__coll__graph.png | Bin .../classIRMitsubishiHeavy88Ac-members.html | 0 .../html/classIRMitsubishiHeavy88Ac.html | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.map | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.md5 | 0 ...lassIRMitsubishiHeavy88Ac__coll__graph.png | Bin .../html/classIRNeoclimaAc-members.html | 0 .../docs/doxygen/html/classIRNeoclimaAc.html | 0 .../html/classIRNeoclimaAc__coll__graph.map | 0 .../html/classIRNeoclimaAc__coll__graph.md5 | 0 .../html/classIRNeoclimaAc__coll__graph.png | Bin .../html/classIRPanasonicAc-members.html | 0 .../docs/doxygen/html/classIRPanasonicAc.html | 0 .../html/classIRPanasonicAc__coll__graph.map | 0 .../html/classIRPanasonicAc__coll__graph.md5 | 0 .../html/classIRPanasonicAc__coll__graph.png | Bin .../html/classIRSamsungAc-members.html | 0 .../docs/doxygen/html/classIRSamsungAc.html | 0 .../html/classIRSamsungAc__coll__graph.map | 0 .../html/classIRSamsungAc__coll__graph.md5 | 0 .../html/classIRSamsungAc__coll__graph.png | Bin .../doxygen/html/classIRSanyoAc-members.html | 0 .../docs/doxygen/html/classIRSanyoAc.html | 0 .../html/classIRSanyoAc__coll__graph.map | 0 .../html/classIRSanyoAc__coll__graph.md5 | 0 .../html/classIRSanyoAc__coll__graph.png | Bin .../doxygen/html/classIRSharpAc-members.html | 0 .../docs/doxygen/html/classIRSharpAc.html | 0 .../html/classIRSharpAc__coll__graph.map | 0 .../html/classIRSharpAc__coll__graph.md5 | 0 .../html/classIRSharpAc__coll__graph.png | Bin .../doxygen/html/classIRTcl112Ac-members.html | 0 .../docs/doxygen/html/classIRTcl112Ac.html | 0 .../html/classIRTcl112Ac__coll__graph.map | 0 .../html/classIRTcl112Ac__coll__graph.md5 | 0 .../html/classIRTcl112Ac__coll__graph.png | Bin .../html/classIRTechnibelAc-members.html | 0 .../docs/doxygen/html/classIRTechnibelAc.html | 0 .../html/classIRTechnibelAc__coll__graph.map | 0 .../html/classIRTechnibelAc__coll__graph.md5 | 0 .../html/classIRTechnibelAc__coll__graph.png | Bin .../doxygen/html/classIRTecoAc-members.html | 0 .../docs/doxygen/html/classIRTecoAc.html | 0 .../html/classIRTecoAc__coll__graph.map | 0 .../html/classIRTecoAc__coll__graph.md5 | 0 .../html/classIRTecoAc__coll__graph.png | Bin .../html/classIRToshibaAC-members.html | 0 .../docs/doxygen/html/classIRToshibaAC.html | 0 .../html/classIRToshibaAC__coll__graph.map | 0 .../html/classIRToshibaAC__coll__graph.md5 | 0 .../html/classIRToshibaAC__coll__graph.png | Bin .../html/classIRTranscoldAc-members.html | 0 .../docs/doxygen/html/classIRTranscoldAc.html | 0 .../html/classIRTranscoldAc__coll__graph.map | 0 .../html/classIRTranscoldAc__coll__graph.md5 | 0 .../html/classIRTranscoldAc__coll__graph.png | Bin .../html/classIRTrotecESP-members.html | 0 .../docs/doxygen/html/classIRTrotecESP.html | 0 .../html/classIRTrotecESP__coll__graph.map | 0 .../html/classIRTrotecESP__coll__graph.md5 | 0 .../html/classIRTrotecESP__coll__graph.png | Bin .../doxygen/html/classIRVestelAc-members.html | 0 .../docs/doxygen/html/classIRVestelAc.html | 0 .../html/classIRVestelAc__coll__graph.map | 0 .../html/classIRVestelAc__coll__graph.md5 | 0 .../html/classIRVestelAc__coll__graph.png | Bin .../doxygen/html/classIRVoltas-members.html | 0 .../docs/doxygen/html/classIRVoltas.html | 0 .../html/classIRVoltas__coll__graph.map | 0 .../html/classIRVoltas__coll__graph.md5 | 0 .../html/classIRVoltas__coll__graph.png | Bin .../html/classIRWhirlpoolAc-members.html | 0 .../docs/doxygen/html/classIRWhirlpoolAc.html | 0 .../html/classIRWhirlpoolAc__coll__graph.map | 0 .../html/classIRWhirlpoolAc__coll__graph.md5 | 0 .../html/classIRWhirlpoolAc__coll__graph.png | Bin .../docs/doxygen/html/classIRac-members.html | 0 .../docs/doxygen/html/classIRac.html | 0 .../doxygen/html/classIRac__coll__graph.map | 0 .../doxygen/html/classIRac__coll__graph.md5 | 0 .../doxygen/html/classIRac__coll__graph.png | Bin .../doxygen/html/classIRrecv-members.html | 0 .../docs/doxygen/html/classIRrecv.html | 0 .../doxygen/html/classIRrecv__coll__graph.map | 0 .../doxygen/html/classIRrecv__coll__graph.md5 | 0 .../doxygen/html/classIRrecv__coll__graph.png | Bin .../doxygen/html/classIRsend-members.html | 0 .../docs/doxygen/html/classIRsend.html | 0 .../doxygen/html/classIRtimer-members.html | 0 .../docs/doxygen/html/classIRtimer.html | 0 .../doxygen/html/classTimerMs-members.html | 0 .../docs/doxygen/html/classTimerMs.html | 0 .../html/classdecode__results-members.html | 0 .../doxygen/html/classdecode__results.html | 0 .../docs/doxygen/html/classes.html | 0 .../docs/doxygen/html/closed.png | Bin .../docs/doxygen/html/de-CH_8h.html | 0 .../docs/doxygen/html/de-CH_8h_source.html | 0 .../docs/doxygen/html/de-DE_8h.html | 0 .../docs/doxygen/html/de-DE_8h_source.html | 0 .../docs/doxygen/html/defaults_8h.html | 0 .../docs/doxygen/html/defaults_8h_source.html | 0 .../docs/doxygen/html/deprecated.html | 0 .../dir_49e56c817e5e54854c35e136979f97ca.html | 0 .../dir_68267d1309a1af8e8297ef4c3efbcdba.html | 0 .../dir_84fe998d1eb06414cc389ad334e77e63.html | 0 .../docs/doxygen/html/doc.png | Bin .../docs/doxygen/html/doxygen.css | 0 .../docs/doxygen/html/doxygen.png | Bin .../docs/doxygen/html/doxygen__index_8md.html | 0 .../docs/doxygen/html/dynsections.js | 0 .../docs/doxygen/html/en-AU_8h.html | 0 .../docs/doxygen/html/en-AU_8h_source.html | 0 .../docs/doxygen/html/en-IE_8h.html | 0 .../docs/doxygen/html/en-IE_8h_source.html | 0 .../docs/doxygen/html/en-UK_8h.html | 0 .../docs/doxygen/html/en-UK_8h_source.html | 0 .../docs/doxygen/html/en-US_8h.html | 0 .../docs/doxygen/html/en-US_8h_source.html | 0 .../docs/doxygen/html/es-ES_8h.html | 0 .../docs/doxygen/html/es-ES_8h_source.html | 0 .../docs/doxygen/html/files.html | 0 .../docs/doxygen/html/folderclosed.png | Bin .../docs/doxygen/html/folderopen.png | Bin .../docs/doxygen/html/fr-FR_8h.html | 0 .../docs/doxygen/html/fr-FR_8h_source.html | 0 .../docs/doxygen/html/functions.html | 0 .../docs/doxygen/html/functions_a.html | 0 .../docs/doxygen/html/functions_b.html | 0 .../docs/doxygen/html/functions_c.html | 0 .../docs/doxygen/html/functions_d.html | 0 .../docs/doxygen/html/functions_e.html | 0 .../docs/doxygen/html/functions_f.html | 0 .../docs/doxygen/html/functions_func.html | 0 .../docs/doxygen/html/functions_func_a.html | 0 .../docs/doxygen/html/functions_func_b.html | 0 .../docs/doxygen/html/functions_func_c.html | 0 .../docs/doxygen/html/functions_func_d.html | 0 .../docs/doxygen/html/functions_func_e.html | 0 .../docs/doxygen/html/functions_func_f.html | 0 .../docs/doxygen/html/functions_func_g.html | 0 .../docs/doxygen/html/functions_func_h.html | 0 .../docs/doxygen/html/functions_func_i.html | 0 .../docs/doxygen/html/functions_func_k.html | 0 .../docs/doxygen/html/functions_func_l.html | 0 .../docs/doxygen/html/functions_func_m.html | 0 .../docs/doxygen/html/functions_func_n.html | 0 .../docs/doxygen/html/functions_func_o.html | 0 .../docs/doxygen/html/functions_func_p.html | 0 .../docs/doxygen/html/functions_func_r.html | 0 .../docs/doxygen/html/functions_func_s.html | 0 .../docs/doxygen/html/functions_func_t.html | 0 .../docs/doxygen/html/functions_func_u.html | 0 .../docs/doxygen/html/functions_func_v.html | 0 .../docs/doxygen/html/functions_func_w.html | 0 .../docs/doxygen/html/functions_func_~.html | 0 .../docs/doxygen/html/functions_g.html | 0 .../docs/doxygen/html/functions_h.html | 0 .../docs/doxygen/html/functions_i.html | 0 .../docs/doxygen/html/functions_k.html | 0 .../docs/doxygen/html/functions_l.html | 0 .../docs/doxygen/html/functions_m.html | 0 .../docs/doxygen/html/functions_n.html | 0 .../docs/doxygen/html/functions_o.html | 0 .../docs/doxygen/html/functions_p.html | 0 .../docs/doxygen/html/functions_q.html | 0 .../docs/doxygen/html/functions_r.html | 0 .../docs/doxygen/html/functions_rela.html | 0 .../docs/doxygen/html/functions_s.html | 0 .../docs/doxygen/html/functions_t.html | 0 .../docs/doxygen/html/functions_u.html | 0 .../docs/doxygen/html/functions_v.html | 0 .../docs/doxygen/html/functions_vars.html | 0 .../docs/doxygen/html/functions_vars_a.html | 0 .../docs/doxygen/html/functions_vars_b.html | 0 .../docs/doxygen/html/functions_vars_c.html | 0 .../docs/doxygen/html/functions_vars_d.html | 0 .../docs/doxygen/html/functions_vars_e.html | 0 .../docs/doxygen/html/functions_vars_f.html | 0 .../docs/doxygen/html/functions_vars_h.html | 0 .../docs/doxygen/html/functions_vars_i.html | 0 .../docs/doxygen/html/functions_vars_l.html | 0 .../docs/doxygen/html/functions_vars_m.html | 0 .../docs/doxygen/html/functions_vars_n.html | 0 .../docs/doxygen/html/functions_vars_o.html | 0 .../docs/doxygen/html/functions_vars_p.html | 0 .../docs/doxygen/html/functions_vars_q.html | 0 .../docs/doxygen/html/functions_vars_r.html | 0 .../docs/doxygen/html/functions_vars_s.html | 0 .../docs/doxygen/html/functions_vars_t.html | 0 .../docs/doxygen/html/functions_vars_u.html | 0 .../docs/doxygen/html/functions_vars_v.html | 0 .../docs/doxygen/html/functions_vars_w.html | 0 .../docs/doxygen/html/functions_vars_x.html | 0 .../docs/doxygen/html/functions_vars_z.html | 0 .../docs/doxygen/html/functions_w.html | 0 .../docs/doxygen/html/functions_x.html | 0 .../docs/doxygen/html/functions_z.html | 0 .../docs/doxygen/html/functions_~.html | 0 .../docs/doxygen/html/globals.html | 0 .../docs/doxygen/html/globals_a.html | 0 .../docs/doxygen/html/globals_c.html | 0 .../docs/doxygen/html/globals_d.html | 0 .../docs/doxygen/html/globals_e.html | 0 .../docs/doxygen/html/globals_enum.html | 0 .../docs/doxygen/html/globals_eval.html | 0 .../docs/doxygen/html/globals_f.html | 0 .../docs/doxygen/html/globals_func.html | 0 .../docs/doxygen/html/globals_g.html | 0 .../docs/doxygen/html/globals_h.html | 0 .../docs/doxygen/html/globals_i.html | 0 .../docs/doxygen/html/globals_j.html | 0 .../docs/doxygen/html/globals_k.html | 0 .../docs/doxygen/html/globals_l.html | 0 .../docs/doxygen/html/globals_m.html | 0 .../docs/doxygen/html/globals_n.html | 0 .../docs/doxygen/html/globals_p.html | 0 .../docs/doxygen/html/globals_r.html | 0 .../docs/doxygen/html/globals_s.html | 0 .../docs/doxygen/html/globals_t.html | 0 .../docs/doxygen/html/globals_type.html | 0 .../docs/doxygen/html/globals_u.html | 0 .../docs/doxygen/html/globals_v.html | 0 .../docs/doxygen/html/globals_vars.html | 0 .../docs/doxygen/html/globals_vars_i.html | 0 .../docs/doxygen/html/globals_vars_k.html | 0 .../docs/doxygen/html/globals_w.html | 0 .../docs/doxygen/html/globals_x.html | 0 .../docs/doxygen/html/globals_y.html | 0 .../docs/doxygen/html/globals_z.html | 0 .../docs/doxygen/html/graph_legend.html | 0 .../docs/doxygen/html/graph_legend.md5 | 0 .../docs/doxygen/html/graph_legend.png | Bin .../docs/doxygen/html/hierarchy.html | 0 .../docs/doxygen/html/i18n_8h.html | 0 .../docs/doxygen/html/i18n_8h_source.html | 0 .../docs/doxygen/html/index.html | 0 .../docs/doxygen/html/inherit_graph_0.map | 0 .../docs/doxygen/html/inherit_graph_0.md5 | 0 .../docs/doxygen/html/inherit_graph_0.png | Bin .../docs/doxygen/html/inherit_graph_1.map | 0 .../docs/doxygen/html/inherit_graph_1.md5 | 0 .../docs/doxygen/html/inherit_graph_1.png | Bin .../docs/doxygen/html/inherit_graph_10.map | 0 .../docs/doxygen/html/inherit_graph_10.md5 | 0 .../docs/doxygen/html/inherit_graph_10.png | Bin .../docs/doxygen/html/inherit_graph_11.map | 0 .../docs/doxygen/html/inherit_graph_11.md5 | 0 .../docs/doxygen/html/inherit_graph_11.png | Bin .../docs/doxygen/html/inherit_graph_12.map | 0 .../docs/doxygen/html/inherit_graph_12.md5 | 0 .../docs/doxygen/html/inherit_graph_12.png | Bin .../docs/doxygen/html/inherit_graph_13.map | 0 .../docs/doxygen/html/inherit_graph_13.md5 | 0 .../docs/doxygen/html/inherit_graph_13.png | Bin .../docs/doxygen/html/inherit_graph_14.map | 0 .../docs/doxygen/html/inherit_graph_14.md5 | 0 .../docs/doxygen/html/inherit_graph_14.png | Bin .../docs/doxygen/html/inherit_graph_15.map | 0 .../docs/doxygen/html/inherit_graph_15.md5 | 0 .../docs/doxygen/html/inherit_graph_15.png | Bin .../docs/doxygen/html/inherit_graph_16.map | 0 .../docs/doxygen/html/inherit_graph_16.md5 | 0 .../docs/doxygen/html/inherit_graph_16.png | Bin .../docs/doxygen/html/inherit_graph_17.map | 0 .../docs/doxygen/html/inherit_graph_17.md5 | 0 .../docs/doxygen/html/inherit_graph_17.png | Bin .../docs/doxygen/html/inherit_graph_18.map | 0 .../docs/doxygen/html/inherit_graph_18.md5 | 0 .../docs/doxygen/html/inherit_graph_18.png | Bin .../docs/doxygen/html/inherit_graph_19.map | 0 .../docs/doxygen/html/inherit_graph_19.md5 | 0 .../docs/doxygen/html/inherit_graph_19.png | Bin .../docs/doxygen/html/inherit_graph_2.map | 0 .../docs/doxygen/html/inherit_graph_2.md5 | 0 .../docs/doxygen/html/inherit_graph_2.png | Bin .../docs/doxygen/html/inherit_graph_20.map | 0 .../docs/doxygen/html/inherit_graph_20.md5 | 0 .../docs/doxygen/html/inherit_graph_20.png | Bin .../docs/doxygen/html/inherit_graph_21.map | 0 .../docs/doxygen/html/inherit_graph_21.md5 | 0 .../docs/doxygen/html/inherit_graph_21.png | Bin .../docs/doxygen/html/inherit_graph_22.map | 0 .../docs/doxygen/html/inherit_graph_22.md5 | 0 .../docs/doxygen/html/inherit_graph_22.png | Bin .../docs/doxygen/html/inherit_graph_23.map | 0 .../docs/doxygen/html/inherit_graph_23.md5 | 0 .../docs/doxygen/html/inherit_graph_23.png | Bin .../docs/doxygen/html/inherit_graph_24.map | 0 .../docs/doxygen/html/inherit_graph_24.md5 | 0 .../docs/doxygen/html/inherit_graph_24.png | Bin .../docs/doxygen/html/inherit_graph_25.map | 0 .../docs/doxygen/html/inherit_graph_25.md5 | 0 .../docs/doxygen/html/inherit_graph_25.png | Bin .../docs/doxygen/html/inherit_graph_26.map | 0 .../docs/doxygen/html/inherit_graph_26.md5 | 0 .../docs/doxygen/html/inherit_graph_26.png | Bin .../docs/doxygen/html/inherit_graph_27.map | 0 .../docs/doxygen/html/inherit_graph_27.md5 | 0 .../docs/doxygen/html/inherit_graph_27.png | Bin .../docs/doxygen/html/inherit_graph_28.map | 0 .../docs/doxygen/html/inherit_graph_28.md5 | 0 .../docs/doxygen/html/inherit_graph_28.png | Bin .../docs/doxygen/html/inherit_graph_29.map | 0 .../docs/doxygen/html/inherit_graph_29.md5 | 0 .../docs/doxygen/html/inherit_graph_29.png | Bin .../docs/doxygen/html/inherit_graph_3.map | 0 .../docs/doxygen/html/inherit_graph_3.md5 | 0 .../docs/doxygen/html/inherit_graph_3.png | Bin .../docs/doxygen/html/inherit_graph_30.map | 0 .../docs/doxygen/html/inherit_graph_30.md5 | 0 .../docs/doxygen/html/inherit_graph_30.png | Bin .../docs/doxygen/html/inherit_graph_31.map | 0 .../docs/doxygen/html/inherit_graph_31.md5 | 0 .../docs/doxygen/html/inherit_graph_31.png | Bin .../docs/doxygen/html/inherit_graph_32.map | 0 .../docs/doxygen/html/inherit_graph_32.md5 | 0 .../docs/doxygen/html/inherit_graph_32.png | Bin .../docs/doxygen/html/inherit_graph_33.map | 0 .../docs/doxygen/html/inherit_graph_33.md5 | 0 .../docs/doxygen/html/inherit_graph_33.png | Bin .../docs/doxygen/html/inherit_graph_34.map | 0 .../docs/doxygen/html/inherit_graph_34.md5 | 0 .../docs/doxygen/html/inherit_graph_34.png | Bin .../docs/doxygen/html/inherit_graph_35.map | 0 .../docs/doxygen/html/inherit_graph_35.md5 | 0 .../docs/doxygen/html/inherit_graph_35.png | Bin .../docs/doxygen/html/inherit_graph_36.map | 0 .../docs/doxygen/html/inherit_graph_36.md5 | 0 .../docs/doxygen/html/inherit_graph_36.png | Bin .../docs/doxygen/html/inherit_graph_37.map | 0 .../docs/doxygen/html/inherit_graph_37.md5 | 0 .../docs/doxygen/html/inherit_graph_37.png | Bin .../docs/doxygen/html/inherit_graph_38.map | 0 .../docs/doxygen/html/inherit_graph_38.md5 | 0 .../docs/doxygen/html/inherit_graph_38.png | Bin .../docs/doxygen/html/inherit_graph_39.map | 0 .../docs/doxygen/html/inherit_graph_39.md5 | 0 .../docs/doxygen/html/inherit_graph_39.png | Bin .../docs/doxygen/html/inherit_graph_4.map | 0 .../docs/doxygen/html/inherit_graph_4.md5 | 0 .../docs/doxygen/html/inherit_graph_4.png | Bin .../docs/doxygen/html/inherit_graph_40.map | 0 .../docs/doxygen/html/inherit_graph_40.md5 | 0 .../docs/doxygen/html/inherit_graph_40.png | Bin .../docs/doxygen/html/inherit_graph_41.map | 0 .../docs/doxygen/html/inherit_graph_41.md5 | 0 .../docs/doxygen/html/inherit_graph_41.png | Bin .../docs/doxygen/html/inherit_graph_42.map | 0 .../docs/doxygen/html/inherit_graph_42.md5 | 0 .../docs/doxygen/html/inherit_graph_42.png | Bin .../docs/doxygen/html/inherit_graph_43.map | 0 .../docs/doxygen/html/inherit_graph_43.md5 | 0 .../docs/doxygen/html/inherit_graph_43.png | Bin .../docs/doxygen/html/inherit_graph_44.map | 0 .../docs/doxygen/html/inherit_graph_44.md5 | 0 .../docs/doxygen/html/inherit_graph_44.png | Bin .../docs/doxygen/html/inherit_graph_45.map | 0 .../docs/doxygen/html/inherit_graph_45.md5 | 0 .../docs/doxygen/html/inherit_graph_45.png | Bin .../docs/doxygen/html/inherit_graph_46.map | 0 .../docs/doxygen/html/inherit_graph_46.md5 | 0 .../docs/doxygen/html/inherit_graph_46.png | Bin .../docs/doxygen/html/inherit_graph_47.map | 0 .../docs/doxygen/html/inherit_graph_47.md5 | 0 .../docs/doxygen/html/inherit_graph_47.png | Bin .../docs/doxygen/html/inherit_graph_48.map | 0 .../docs/doxygen/html/inherit_graph_48.md5 | 0 .../docs/doxygen/html/inherit_graph_48.png | Bin .../docs/doxygen/html/inherit_graph_49.map | 0 .../docs/doxygen/html/inherit_graph_49.md5 | 0 .../docs/doxygen/html/inherit_graph_49.png | Bin .../docs/doxygen/html/inherit_graph_5.map | 0 .../docs/doxygen/html/inherit_graph_5.md5 | 0 .../docs/doxygen/html/inherit_graph_5.png | Bin .../docs/doxygen/html/inherit_graph_50.map | 0 .../docs/doxygen/html/inherit_graph_50.md5 | 0 .../docs/doxygen/html/inherit_graph_50.png | Bin .../docs/doxygen/html/inherit_graph_51.map | 0 .../docs/doxygen/html/inherit_graph_51.md5 | 0 .../docs/doxygen/html/inherit_graph_51.png | Bin .../docs/doxygen/html/inherit_graph_52.map | 0 .../docs/doxygen/html/inherit_graph_52.md5 | 0 .../docs/doxygen/html/inherit_graph_52.png | Bin .../docs/doxygen/html/inherit_graph_53.map | 0 .../docs/doxygen/html/inherit_graph_53.md5 | 0 .../docs/doxygen/html/inherit_graph_53.png | Bin .../docs/doxygen/html/inherit_graph_54.map | 0 .../docs/doxygen/html/inherit_graph_54.md5 | 0 .../docs/doxygen/html/inherit_graph_54.png | Bin .../docs/doxygen/html/inherit_graph_55.map | 0 .../docs/doxygen/html/inherit_graph_55.md5 | 0 .../docs/doxygen/html/inherit_graph_55.png | Bin .../docs/doxygen/html/inherit_graph_56.map | 0 .../docs/doxygen/html/inherit_graph_56.md5 | 0 .../docs/doxygen/html/inherit_graph_56.png | Bin .../docs/doxygen/html/inherit_graph_57.map | 0 .../docs/doxygen/html/inherit_graph_57.md5 | 0 .../docs/doxygen/html/inherit_graph_57.png | Bin .../docs/doxygen/html/inherit_graph_58.map | 0 .../docs/doxygen/html/inherit_graph_58.md5 | 0 .../docs/doxygen/html/inherit_graph_58.png | Bin .../docs/doxygen/html/inherit_graph_59.map | 0 .../docs/doxygen/html/inherit_graph_59.md5 | 0 .../docs/doxygen/html/inherit_graph_59.png | Bin .../docs/doxygen/html/inherit_graph_6.map | 0 .../docs/doxygen/html/inherit_graph_6.md5 | 0 .../docs/doxygen/html/inherit_graph_6.png | Bin .../docs/doxygen/html/inherit_graph_60.map | 0 .../docs/doxygen/html/inherit_graph_60.md5 | 0 .../docs/doxygen/html/inherit_graph_60.png | Bin .../docs/doxygen/html/inherit_graph_61.map | 0 .../docs/doxygen/html/inherit_graph_61.md5 | 0 .../docs/doxygen/html/inherit_graph_61.png | Bin .../docs/doxygen/html/inherit_graph_62.map | 0 .../docs/doxygen/html/inherit_graph_62.md5 | 0 .../docs/doxygen/html/inherit_graph_62.png | Bin .../docs/doxygen/html/inherit_graph_63.map | 0 .../docs/doxygen/html/inherit_graph_63.md5 | 0 .../docs/doxygen/html/inherit_graph_63.png | Bin .../docs/doxygen/html/inherit_graph_64.map | 0 .../docs/doxygen/html/inherit_graph_64.md5 | 0 .../docs/doxygen/html/inherit_graph_64.png | Bin .../docs/doxygen/html/inherit_graph_65.map | 0 .../docs/doxygen/html/inherit_graph_65.md5 | 0 .../docs/doxygen/html/inherit_graph_65.png | Bin .../docs/doxygen/html/inherit_graph_66.map | 0 .../docs/doxygen/html/inherit_graph_66.md5 | 0 .../docs/doxygen/html/inherit_graph_66.png | Bin .../docs/doxygen/html/inherit_graph_67.map | 0 .../docs/doxygen/html/inherit_graph_67.md5 | 0 .../docs/doxygen/html/inherit_graph_67.png | Bin .../docs/doxygen/html/inherit_graph_68.map | 0 .../docs/doxygen/html/inherit_graph_68.md5 | 0 .../docs/doxygen/html/inherit_graph_68.png | Bin .../docs/doxygen/html/inherit_graph_7.map | 0 .../docs/doxygen/html/inherit_graph_7.md5 | 0 .../docs/doxygen/html/inherit_graph_7.png | Bin .../docs/doxygen/html/inherit_graph_8.map | 0 .../docs/doxygen/html/inherit_graph_8.md5 | 0 .../docs/doxygen/html/inherit_graph_8.png | Bin .../docs/doxygen/html/inherit_graph_9.map | 0 .../docs/doxygen/html/inherit_graph_9.md5 | 0 .../docs/doxygen/html/inherit_graph_9.png | Bin .../docs/doxygen/html/inherits.html | 0 .../docs/doxygen/html/ir__Airwell_8cpp.html | 0 .../docs/doxygen/html/ir__Airwell_8h.html | 0 .../doxygen/html/ir__Airwell_8h_source.html | 0 .../docs/doxygen/html/ir__Aiwa_8cpp.html | 0 .../docs/doxygen/html/ir__Amcor_8cpp.html | 0 .../docs/doxygen/html/ir__Amcor_8h.html | 0 .../doxygen/html/ir__Amcor_8h_source.html | 0 .../docs/doxygen/html/ir__Argo_8cpp.html | 0 .../docs/doxygen/html/ir__Argo_8h.html | 0 .../docs/doxygen/html/ir__Argo_8h_source.html | 0 .../docs/doxygen/html/ir__Carrier_8cpp.html | 0 .../docs/doxygen/html/ir__Carrier_8h.html | 0 .../doxygen/html/ir__Carrier_8h_source.html | 0 .../docs/doxygen/html/ir__Coolix_8cpp.html | 0 .../docs/doxygen/html/ir__Coolix_8h.html | 0 .../doxygen/html/ir__Coolix_8h_source.html | 0 .../docs/doxygen/html/ir__Corona_8cpp.html | 0 .../docs/doxygen/html/ir__Corona_8h.html | 0 .../doxygen/html/ir__Corona_8h_source.html | 0 .../docs/doxygen/html/ir__Daikin_8cpp.html | 0 .../docs/doxygen/html/ir__Daikin_8h.html | 0 .../doxygen/html/ir__Daikin_8h_source.html | 0 .../docs/doxygen/html/ir__Delonghi_8cpp.html | 0 .../docs/doxygen/html/ir__Delonghi_8h.html | 0 .../doxygen/html/ir__Delonghi_8h_source.html | 0 .../docs/doxygen/html/ir__Denon_8cpp.html | 0 .../docs/doxygen/html/ir__Dish_8cpp.html | 0 .../docs/doxygen/html/ir__Doshisha_8cpp.html | 0 .../docs/doxygen/html/ir__Electra_8cpp.html | 0 .../docs/doxygen/html/ir__Electra_8h.html | 0 .../doxygen/html/ir__Electra_8h_source.html | 0 .../docs/doxygen/html/ir__Epson_8cpp.html | 0 .../docs/doxygen/html/ir__Fujitsu_8cpp.html | 0 .../docs/doxygen/html/ir__Fujitsu_8h.html | 0 .../doxygen/html/ir__Fujitsu_8h_source.html | 0 .../docs/doxygen/html/ir__GICable_8cpp.html | 0 .../doxygen/html/ir__GlobalCache_8cpp.html | 0 .../doxygen/html/ir__Goodweather_8cpp.html | 0 .../docs/doxygen/html/ir__Goodweather_8h.html | 0 .../html/ir__Goodweather_8h_source.html | 0 .../docs/doxygen/html/ir__Gree_8cpp.html | 0 .../docs/doxygen/html/ir__Gree_8h.html | 0 .../docs/doxygen/html/ir__Gree_8h_source.html | 0 .../docs/doxygen/html/ir__Haier_8cpp.html | 0 .../docs/doxygen/html/ir__Haier_8h.html | 0 .../doxygen/html/ir__Haier_8h_source.html | 0 .../docs/doxygen/html/ir__Hitachi_8cpp.html | 0 .../docs/doxygen/html/ir__Hitachi_8h.html | 0 .../doxygen/html/ir__Hitachi_8h_source.html | 0 .../docs/doxygen/html/ir__Inax_8cpp.html | 0 .../docs/doxygen/html/ir__JVC_8cpp.html | 0 .../doxygen/html/ir__Kelvinator_8cpp.html | 0 .../docs/doxygen/html/ir__Kelvinator_8h.html | 0 .../html/ir__Kelvinator_8h_source.html | 0 .../docs/doxygen/html/ir__LG_8cpp.html | 0 .../docs/doxygen/html/ir__LG_8h.html | 0 .../docs/doxygen/html/ir__LG_8h_source.html | 0 .../docs/doxygen/html/ir__Lasertag_8cpp.html | 0 .../docs/doxygen/html/ir__Lego_8cpp.html | 0 .../docs/doxygen/html/ir__Lutron_8cpp.html | 0 .../docs/doxygen/html/ir__MWM_8cpp.html | 0 .../docs/doxygen/html/ir__Magiquest_8cpp.html | 0 .../docs/doxygen/html/ir__Magiquest_8h.html | 0 .../doxygen/html/ir__Magiquest_8h_source.html | 0 .../docs/doxygen/html/ir__Metz_8cpp.html | 0 .../docs/doxygen/html/ir__Midea_8cpp.html | 0 .../docs/doxygen/html/ir__Midea_8h.html | 0 .../doxygen/html/ir__Midea_8h_source.html | 0 .../html/ir__MitsubishiHeavy_8cpp.html | 0 .../doxygen/html/ir__MitsubishiHeavy_8h.html | 0 .../html/ir__MitsubishiHeavy_8h_source.html | 0 .../doxygen/html/ir__Mitsubishi_8cpp.html | 0 .../docs/doxygen/html/ir__Mitsubishi_8h.html | 0 .../html/ir__Mitsubishi_8h_source.html | 0 .../doxygen/html/ir__Multibrackets_8cpp.html | 0 .../docs/doxygen/html/ir__NEC_8cpp.html | 0 .../docs/doxygen/html/ir__NEC_8h.html | 0 .../docs/doxygen/html/ir__NEC_8h_source.html | 0 .../docs/doxygen/html/ir__Neoclima_8cpp.html | 0 .../docs/doxygen/html/ir__Neoclima_8h.html | 0 .../doxygen/html/ir__Neoclima_8h_source.html | 0 .../docs/doxygen/html/ir__Nikai_8cpp.html | 0 .../docs/doxygen/html/ir__Panasonic_8cpp.html | 0 .../docs/doxygen/html/ir__Panasonic_8h.html | 0 .../doxygen/html/ir__Panasonic_8h_source.html | 0 .../docs/doxygen/html/ir__Pioneer_8cpp.html | 0 .../docs/doxygen/html/ir__Pronto_8cpp.html | 0 .../docs/doxygen/html/ir__RC5__RC6_8cpp.html | 0 .../docs/doxygen/html/ir__RCMM_8cpp.html | 0 .../docs/doxygen/html/ir__Samsung_8cpp.html | 0 .../docs/doxygen/html/ir__Samsung_8h.html | 0 .../doxygen/html/ir__Samsung_8h_source.html | 0 .../docs/doxygen/html/ir__Sanyo_8cpp.html | 0 .../docs/doxygen/html/ir__Sanyo_8h.html | 0 .../doxygen/html/ir__Sanyo_8h_source.html | 0 .../docs/doxygen/html/ir__Sharp_8cpp.html | 0 .../docs/doxygen/html/ir__Sharp_8h.html | 0 .../doxygen/html/ir__Sharp_8h_source.html | 0 .../docs/doxygen/html/ir__Sherwood_8cpp.html | 0 .../docs/doxygen/html/ir__Sony_8cpp.html | 0 .../docs/doxygen/html/ir__Symphony_8cpp.html | 0 .../docs/doxygen/html/ir__Tcl_8cpp.html | 0 .../docs/doxygen/html/ir__Tcl_8h.html | 0 .../docs/doxygen/html/ir__Tcl_8h_source.html | 0 .../docs/doxygen/html/ir__Technibel_8cpp.html | 0 .../docs/doxygen/html/ir__Technibel_8h.html | 0 .../doxygen/html/ir__Technibel_8h_source.html | 0 .../docs/doxygen/html/ir__Teco_8cpp.html | 0 .../docs/doxygen/html/ir__Teco_8h.html | 0 .../docs/doxygen/html/ir__Teco_8h_source.html | 0 .../docs/doxygen/html/ir__Toshiba_8cpp.html | 0 .../docs/doxygen/html/ir__Toshiba_8h.html | 0 .../doxygen/html/ir__Toshiba_8h_source.html | 0 .../docs/doxygen/html/ir__Transcold_8cpp.html | 0 .../docs/doxygen/html/ir__Transcold_8h.html | 0 .../doxygen/html/ir__Transcold_8h_source.html | 0 .../docs/doxygen/html/ir__Trotec_8cpp.html | 0 .../docs/doxygen/html/ir__Trotec_8h.html | 0 .../doxygen/html/ir__Trotec_8h_source.html | 0 .../docs/doxygen/html/ir__Vestel_8cpp.html | 0 .../docs/doxygen/html/ir__Vestel_8h.html | 0 .../doxygen/html/ir__Vestel_8h_source.html | 0 .../docs/doxygen/html/ir__Voltas_8cpp.html | 0 .../docs/doxygen/html/ir__Voltas_8h.html | 0 .../doxygen/html/ir__Voltas_8h_source.html | 0 .../docs/doxygen/html/ir__Whirlpool_8cpp.html | 0 .../docs/doxygen/html/ir__Whirlpool_8h.html | 0 .../doxygen/html/ir__Whirlpool_8h_source.html | 0 .../docs/doxygen/html/ir__Whynter_8cpp.html | 0 .../docs/doxygen/html/ir__Zepeal_8cpp.html | 0 .../docs/doxygen/html/it-IT_8h.html | 0 .../docs/doxygen/html/it-IT_8h_source.html | 0 .../docs/doxygen/html/jquery.js | 0 .../doxygen/html/md_src_locale_README.html | 0 .../docs/doxygen/html/menu.js | 0 .../docs/doxygen/html/menudata.js | 0 .../docs/doxygen/html/namespaceIRAcUtils.html | 0 .../docs/doxygen/html/namespaceirutils.html | 0 .../docs/doxygen/html/namespacemembers.html | 0 .../doxygen/html/namespacemembers_enum.html | 0 .../doxygen/html/namespacemembers_func.html | 0 .../docs/doxygen/html/namespaces.html | 0 .../docs/doxygen/html/namespacestdAc.html | 0 .../docs/doxygen/html/nav_f.png | Bin .../docs/doxygen/html/nav_g.png | Bin .../docs/doxygen/html/nav_h.png | Bin .../docs/doxygen/html/open.png | Bin .../docs/doxygen/html/pages.html | 0 .../docs/doxygen/html/search/all_0.html | 0 .../docs/doxygen/html/search/all_0.js | 0 .../docs/doxygen/html/search/all_1.html | 0 .../docs/doxygen/html/search/all_1.js | 0 .../docs/doxygen/html/search/all_10.html | 0 .../docs/doxygen/html/search/all_10.js | 0 .../docs/doxygen/html/search/all_11.html | 0 .../docs/doxygen/html/search/all_11.js | 0 .../docs/doxygen/html/search/all_12.html | 0 .../docs/doxygen/html/search/all_12.js | 0 .../docs/doxygen/html/search/all_13.html | 0 .../docs/doxygen/html/search/all_13.js | 0 .../docs/doxygen/html/search/all_14.html | 0 .../docs/doxygen/html/search/all_14.js | 0 .../docs/doxygen/html/search/all_15.html | 0 .../docs/doxygen/html/search/all_15.js | 0 .../docs/doxygen/html/search/all_16.html | 0 .../docs/doxygen/html/search/all_16.js | 0 .../docs/doxygen/html/search/all_17.html | 0 .../docs/doxygen/html/search/all_17.js | 0 .../docs/doxygen/html/search/all_18.html | 0 .../docs/doxygen/html/search/all_18.js | 0 .../docs/doxygen/html/search/all_19.html | 0 .../docs/doxygen/html/search/all_19.js | 0 .../docs/doxygen/html/search/all_1a.html | 0 .../docs/doxygen/html/search/all_1a.js | 0 .../docs/doxygen/html/search/all_1b.html | 0 .../docs/doxygen/html/search/all_1b.js | 0 .../docs/doxygen/html/search/all_2.html | 0 .../docs/doxygen/html/search/all_2.js | 0 .../docs/doxygen/html/search/all_3.html | 0 .../docs/doxygen/html/search/all_3.js | 0 .../docs/doxygen/html/search/all_4.html | 0 .../docs/doxygen/html/search/all_4.js | 0 .../docs/doxygen/html/search/all_5.html | 0 .../docs/doxygen/html/search/all_5.js | 0 .../docs/doxygen/html/search/all_6.html | 0 .../docs/doxygen/html/search/all_6.js | 0 .../docs/doxygen/html/search/all_7.html | 0 .../docs/doxygen/html/search/all_7.js | 0 .../docs/doxygen/html/search/all_8.html | 0 .../docs/doxygen/html/search/all_8.js | 0 .../docs/doxygen/html/search/all_9.html | 0 .../docs/doxygen/html/search/all_9.js | 0 .../docs/doxygen/html/search/all_a.html | 0 .../docs/doxygen/html/search/all_a.js | 0 .../docs/doxygen/html/search/all_b.html | 0 .../docs/doxygen/html/search/all_b.js | 0 .../docs/doxygen/html/search/all_c.html | 0 .../docs/doxygen/html/search/all_c.js | 0 .../docs/doxygen/html/search/all_d.html | 0 .../docs/doxygen/html/search/all_d.js | 0 .../docs/doxygen/html/search/all_e.html | 0 .../docs/doxygen/html/search/all_e.js | 0 .../docs/doxygen/html/search/all_f.html | 0 .../docs/doxygen/html/search/all_f.js | 0 .../docs/doxygen/html/search/classes_0.html | 0 .../docs/doxygen/html/search/classes_0.js | 0 .../docs/doxygen/html/search/classes_1.html | 0 .../docs/doxygen/html/search/classes_1.js | 0 .../docs/doxygen/html/search/classes_2.html | 0 .../docs/doxygen/html/search/classes_2.js | 0 .../docs/doxygen/html/search/classes_3.html | 0 .../docs/doxygen/html/search/classes_3.js | 0 .../docs/doxygen/html/search/classes_4.html | 0 .../docs/doxygen/html/search/classes_4.js | 0 .../docs/doxygen/html/search/classes_5.html | 0 .../docs/doxygen/html/search/classes_5.js | 0 .../docs/doxygen/html/search/classes_6.html | 0 .../docs/doxygen/html/search/classes_6.js | 0 .../docs/doxygen/html/search/classes_7.html | 0 .../docs/doxygen/html/search/classes_7.js | 0 .../docs/doxygen/html/search/classes_8.html | 0 .../docs/doxygen/html/search/classes_8.js | 0 .../docs/doxygen/html/search/classes_9.html | 0 .../docs/doxygen/html/search/classes_9.js | 0 .../docs/doxygen/html/search/close.png | Bin .../docs/doxygen/html/search/enums_0.html | 0 .../docs/doxygen/html/search/enums_0.js | 0 .../docs/doxygen/html/search/enums_1.html | 0 .../docs/doxygen/html/search/enums_1.js | 0 .../docs/doxygen/html/search/enums_2.html | 0 .../docs/doxygen/html/search/enums_2.js | 0 .../docs/doxygen/html/search/enums_3.html | 0 .../docs/doxygen/html/search/enums_3.js | 0 .../docs/doxygen/html/search/enums_4.html | 0 .../docs/doxygen/html/search/enums_4.js | 0 .../docs/doxygen/html/search/enums_5.html | 0 .../docs/doxygen/html/search/enums_5.js | 0 .../docs/doxygen/html/search/enums_6.html | 0 .../docs/doxygen/html/search/enums_6.js | 0 .../docs/doxygen/html/search/enums_7.html | 0 .../docs/doxygen/html/search/enums_7.js | 0 .../docs/doxygen/html/search/enums_8.html | 0 .../docs/doxygen/html/search/enums_8.js | 0 .../docs/doxygen/html/search/enums_9.html | 0 .../docs/doxygen/html/search/enums_9.js | 0 .../doxygen/html/search/enumvalues_0.html | 0 .../docs/doxygen/html/search/enumvalues_0.js | 0 .../doxygen/html/search/enumvalues_1.html | 0 .../docs/doxygen/html/search/enumvalues_1.js | 0 .../doxygen/html/search/enumvalues_10.html | 0 .../docs/doxygen/html/search/enumvalues_10.js | 0 .../doxygen/html/search/enumvalues_11.html | 0 .../docs/doxygen/html/search/enumvalues_11.js | 0 .../doxygen/html/search/enumvalues_12.html | 0 .../docs/doxygen/html/search/enumvalues_12.js | 0 .../doxygen/html/search/enumvalues_13.html | 0 .../docs/doxygen/html/search/enumvalues_13.js | 0 .../doxygen/html/search/enumvalues_14.html | 0 .../docs/doxygen/html/search/enumvalues_14.js | 0 .../doxygen/html/search/enumvalues_15.html | 0 .../docs/doxygen/html/search/enumvalues_15.js | 0 .../doxygen/html/search/enumvalues_2.html | 0 .../docs/doxygen/html/search/enumvalues_2.js | 0 .../doxygen/html/search/enumvalues_3.html | 0 .../docs/doxygen/html/search/enumvalues_3.js | 0 .../doxygen/html/search/enumvalues_4.html | 0 .../docs/doxygen/html/search/enumvalues_4.js | 0 .../doxygen/html/search/enumvalues_5.html | 0 .../docs/doxygen/html/search/enumvalues_5.js | 0 .../doxygen/html/search/enumvalues_6.html | 0 .../docs/doxygen/html/search/enumvalues_6.js | 0 .../doxygen/html/search/enumvalues_7.html | 0 .../docs/doxygen/html/search/enumvalues_7.js | 0 .../doxygen/html/search/enumvalues_8.html | 0 .../docs/doxygen/html/search/enumvalues_8.js | 0 .../doxygen/html/search/enumvalues_9.html | 0 .../docs/doxygen/html/search/enumvalues_9.js | 0 .../doxygen/html/search/enumvalues_a.html | 0 .../docs/doxygen/html/search/enumvalues_a.js | 0 .../doxygen/html/search/enumvalues_b.html | 0 .../docs/doxygen/html/search/enumvalues_b.js | 0 .../doxygen/html/search/enumvalues_c.html | 0 .../docs/doxygen/html/search/enumvalues_c.js | 0 .../doxygen/html/search/enumvalues_d.html | 0 .../docs/doxygen/html/search/enumvalues_d.js | 0 .../doxygen/html/search/enumvalues_e.html | 0 .../docs/doxygen/html/search/enumvalues_e.js | 0 .../doxygen/html/search/enumvalues_f.html | 0 .../docs/doxygen/html/search/enumvalues_f.js | 0 .../docs/doxygen/html/search/files_0.html | 0 .../docs/doxygen/html/search/files_0.js | 0 .../docs/doxygen/html/search/files_1.html | 0 .../docs/doxygen/html/search/files_1.js | 0 .../docs/doxygen/html/search/files_2.html | 0 .../docs/doxygen/html/search/files_2.js | 0 .../docs/doxygen/html/search/files_3.html | 0 .../docs/doxygen/html/search/files_3.js | 0 .../docs/doxygen/html/search/files_4.html | 0 .../docs/doxygen/html/search/files_4.js | 0 .../docs/doxygen/html/search/files_5.html | 0 .../docs/doxygen/html/search/files_5.js | 0 .../docs/doxygen/html/search/functions_0.html | 0 .../docs/doxygen/html/search/functions_0.js | 0 .../docs/doxygen/html/search/functions_1.html | 0 .../docs/doxygen/html/search/functions_1.js | 0 .../doxygen/html/search/functions_10.html | 0 .../docs/doxygen/html/search/functions_10.js | 0 .../doxygen/html/search/functions_11.html | 0 .../docs/doxygen/html/search/functions_11.js | 0 .../doxygen/html/search/functions_12.html | 0 .../docs/doxygen/html/search/functions_12.js | 0 .../doxygen/html/search/functions_13.html | 0 .../docs/doxygen/html/search/functions_13.js | 0 .../doxygen/html/search/functions_14.html | 0 .../docs/doxygen/html/search/functions_14.js | 0 .../doxygen/html/search/functions_15.html | 0 .../docs/doxygen/html/search/functions_15.js | 0 .../doxygen/html/search/functions_16.html | 0 .../docs/doxygen/html/search/functions_16.js | 0 .../doxygen/html/search/functions_17.html | 0 .../docs/doxygen/html/search/functions_17.js | 0 .../docs/doxygen/html/search/functions_2.html | 0 .../docs/doxygen/html/search/functions_2.js | 0 .../docs/doxygen/html/search/functions_3.html | 0 .../docs/doxygen/html/search/functions_3.js | 0 .../docs/doxygen/html/search/functions_4.html | 0 .../docs/doxygen/html/search/functions_4.js | 0 .../docs/doxygen/html/search/functions_5.html | 0 .../docs/doxygen/html/search/functions_5.js | 0 .../docs/doxygen/html/search/functions_6.html | 0 .../docs/doxygen/html/search/functions_6.js | 0 .../docs/doxygen/html/search/functions_7.html | 0 .../docs/doxygen/html/search/functions_7.js | 0 .../docs/doxygen/html/search/functions_8.html | 0 .../docs/doxygen/html/search/functions_8.js | 0 .../docs/doxygen/html/search/functions_9.html | 0 .../docs/doxygen/html/search/functions_9.js | 0 .../docs/doxygen/html/search/functions_a.html | 0 .../docs/doxygen/html/search/functions_a.js | 0 .../docs/doxygen/html/search/functions_b.html | 0 .../docs/doxygen/html/search/functions_b.js | 0 .../docs/doxygen/html/search/functions_c.html | 0 .../docs/doxygen/html/search/functions_c.js | 0 .../docs/doxygen/html/search/functions_d.html | 0 .../docs/doxygen/html/search/functions_d.js | 0 .../docs/doxygen/html/search/functions_e.html | 0 .../docs/doxygen/html/search/functions_e.js | 0 .../docs/doxygen/html/search/functions_f.html | 0 .../docs/doxygen/html/search/functions_f.js | 0 .../docs/doxygen/html/search/mag_sel.png | Bin .../doxygen/html/search/namespaces_0.html | 0 .../docs/doxygen/html/search/namespaces_0.js | 0 .../doxygen/html/search/namespaces_1.html | 0 .../docs/doxygen/html/search/namespaces_1.js | 0 .../docs/doxygen/html/search/nomatches.html | 0 .../docs/doxygen/html/search/pages_0.html | 0 .../docs/doxygen/html/search/pages_0.js | 0 .../docs/doxygen/html/search/pages_1.html | 0 .../docs/doxygen/html/search/pages_1.js | 0 .../docs/doxygen/html/search/pages_2.html | 0 .../docs/doxygen/html/search/pages_2.js | 0 .../docs/doxygen/html/search/related_0.html | 0 .../docs/doxygen/html/search/related_0.js | 0 .../docs/doxygen/html/search/search.css | 0 .../docs/doxygen/html/search/search.js | 0 .../docs/doxygen/html/search/search_l.png | Bin .../docs/doxygen/html/search/search_m.png | Bin .../docs/doxygen/html/search/search_r.png | Bin .../docs/doxygen/html/search/searchdata.js | 0 .../docs/doxygen/html/search/typedefs_0.html | 0 .../docs/doxygen/html/search/typedefs_0.js | 0 .../docs/doxygen/html/search/variables_0.html | 0 .../docs/doxygen/html/search/variables_0.js | 0 .../docs/doxygen/html/search/variables_1.html | 0 .../docs/doxygen/html/search/variables_1.js | 0 .../doxygen/html/search/variables_10.html | 0 .../docs/doxygen/html/search/variables_10.js | 0 .../doxygen/html/search/variables_11.html | 0 .../docs/doxygen/html/search/variables_11.js | 0 .../doxygen/html/search/variables_12.html | 0 .../docs/doxygen/html/search/variables_12.js | 0 .../doxygen/html/search/variables_13.html | 0 .../docs/doxygen/html/search/variables_13.js | 0 .../doxygen/html/search/variables_14.html | 0 .../docs/doxygen/html/search/variables_14.js | 0 .../doxygen/html/search/variables_15.html | 0 .../docs/doxygen/html/search/variables_15.js | 0 .../doxygen/html/search/variables_16.html | 0 .../docs/doxygen/html/search/variables_16.js | 0 .../doxygen/html/search/variables_17.html | 0 .../docs/doxygen/html/search/variables_17.js | 0 .../docs/doxygen/html/search/variables_2.html | 0 .../docs/doxygen/html/search/variables_2.js | 0 .../docs/doxygen/html/search/variables_3.html | 0 .../docs/doxygen/html/search/variables_3.js | 0 .../docs/doxygen/html/search/variables_4.html | 0 .../docs/doxygen/html/search/variables_4.js | 0 .../docs/doxygen/html/search/variables_5.html | 0 .../docs/doxygen/html/search/variables_5.js | 0 .../docs/doxygen/html/search/variables_6.html | 0 .../docs/doxygen/html/search/variables_6.js | 0 .../docs/doxygen/html/search/variables_7.html | 0 .../docs/doxygen/html/search/variables_7.js | 0 .../docs/doxygen/html/search/variables_8.html | 0 .../docs/doxygen/html/search/variables_8.js | 0 .../docs/doxygen/html/search/variables_9.html | 0 .../docs/doxygen/html/search/variables_9.js | 0 .../docs/doxygen/html/search/variables_a.html | 0 .../docs/doxygen/html/search/variables_a.js | 0 .../docs/doxygen/html/search/variables_b.html | 0 .../docs/doxygen/html/search/variables_b.js | 0 .../docs/doxygen/html/search/variables_c.html | 0 .../docs/doxygen/html/search/variables_c.js | 0 .../docs/doxygen/html/search/variables_d.html | 0 .../docs/doxygen/html/search/variables_d.js | 0 .../docs/doxygen/html/search/variables_e.html | 0 .../docs/doxygen/html/search/variables_e.js | 0 .../docs/doxygen/html/search/variables_f.html | 0 .../docs/doxygen/html/search/variables_f.js | 0 .../docs/doxygen/html/splitbar.png | Bin .../html/structCoronaSection-members.html | 0 .../doxygen/html/structCoronaSection.html | 0 .../html/structirparams__t-members.html | 0 .../docs/doxygen/html/structirparams__t.html | 0 .../html/structmatch__result__t-members.html | 0 .../doxygen/html/structmatch__result__t.html | 0 .../html/structstdAc_1_1state__t-members.html | 0 .../doxygen/html/structstdAc_1_1state__t.html | 0 .../docs/doxygen/html/sync_off.png | Bin .../docs/doxygen/html/sync_on.png | Bin .../docs/doxygen/html/tab_a.png | Bin .../docs/doxygen/html/tab_b.png | Bin .../docs/doxygen/html/tab_h.png | Bin .../docs/doxygen/html/tab_s.png | Bin .../docs/doxygen/html/tabs.css | 0 .../docs/doxygen/html/todo.html | 0 .../html/unionAirwellProtocol-members.html | 0 .../doxygen/html/unionAirwellProtocol.html | 0 .../html/unionAmcorProtocol-members.html | 0 .../docs/doxygen/html/unionAmcorProtocol.html | 0 .../html/unionArgoProtocol-members.html | 0 .../docs/doxygen/html/unionArgoProtocol.html | 0 .../html/unionCarrierProtocol-members.html | 0 .../doxygen/html/unionCarrierProtocol.html | 0 .../html/unionCoronaProtocol-members.html | 0 .../doxygen/html/unionCoronaProtocol.html | 0 .../html/unionCoronaProtocol__coll__graph.map | 0 .../html/unionCoronaProtocol__coll__graph.md5 | 0 .../html/unionCoronaProtocol__coll__graph.png | Bin .../html/unionDelonghiProtocol-members.html | 0 .../doxygen/html/unionDelonghiProtocol.html | 0 .../html/unionGreeProtocol-members.html | 0 .../docs/doxygen/html/unionGreeProtocol.html | 0 .../html/unionHaierProtocol-members.html | 0 .../docs/doxygen/html/unionHaierProtocol.html | 0 .../html/unionHaierYRW02Protocol-members.html | 0 .../doxygen/html/unionHaierYRW02Protocol.html | 0 .../html/unionMideaProtocol-members.html | 0 .../docs/doxygen/html/unionMideaProtocol.html | 0 .../html/unionVoltasProtocol-members.html | 0 .../doxygen/html/unionVoltasProtocol.html | 0 .../doxygen/html/unionmagiquest-members.html | 0 .../docs/doxygen/html/unionmagiquest.html | 0 .../docs/doxygen/html/zh-CN_8h.html | 0 .../docs/doxygen/html/zh-CN_8h_source.html | 0 .../docs/doxygen_index.md | 0 .../examples/BlynkIrRemote/BlynkIrRemote.ino | 0 .../examples/BlynkIrRemote/platformio.ini | 0 .../CommonAcControl/CommonAcControl.ino | 0 .../examples/CommonAcControl/platformio.ini | 0 .../ControlSamsungAC/ControlSamsungAC.ino | 0 .../examples/ControlSamsungAC/platformio.ini | 0 .../DumbIRRepeater/DumbIRRepeater.ino | 0 .../examples/DumbIRRepeater/platformio.ini | 0 .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.h | 0 .../examples/IRMQTTServer/IRMQTTServer.ino | 0 .../examples/IRMQTTServer/platformio.ini | 0 .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 0 .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRrecvDumpV3/BaseOTA.h | 0 .../examples/IRrecvDumpV3/IRrecvDumpV3.ino | 0 .../examples/IRrecvDumpV3/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 0 .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 0 .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 0 .../SmartIRRepeater/SmartIRRepeater.ino | 0 .../examples/SmartIRRepeater/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 0 .../examples/TurnOnGreeAC/TurnOnGreeAC.ino | 0 .../examples/TurnOnGreeAC/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 0 .../TurnOnMitsubishiHeavyAc.ino | 0 .../TurnOnMitsubishiHeavyAc/platformio.ini | 0 .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 0 .../examples/TurnOnPanasonicAC/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 0 .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 0 .../examples/Web-AC-control/README.md | 0 .../examples/Web-AC-control/Web-AC-control.h | 0 .../Web-AC-control/Web-AC-control.ino | 0 .../examples/Web-AC-control/data/favicon.ico | Bin .../Web-AC-control/data/level_1_off.svg | 0 .../Web-AC-control/data/level_1_on.svg | 0 .../Web-AC-control/data/level_2_off.svg | 0 .../Web-AC-control/data/level_2_on.svg | 0 .../Web-AC-control/data/level_3_off.svg | 0 .../Web-AC-control/data/level_3_on.svg | 0 .../Web-AC-control/data/level_4_off.svg | 0 .../Web-AC-control/data/level_4_on.svg | 0 .../examples/Web-AC-control/data/ui.html | 0 .../examples/Web-AC-control/data/ui.js | 0 .../examples/Web-AC-control/platformio.ini | 0 .../examples/Web-AC-control/printscreen.png | Bin .../IRremoteESP8266-2.7.11/keywords.txt | 0 .../IRremoteESP8266-2.7.11/library.json | 0 .../IRremoteESP8266-2.7.11/library.properties | 0 .../IRremoteESP8266-2.7.11/platformio.ini | 0 .../IRremoteESP8266-2.7.11/pylintrc | 0 .../IRremoteESP8266-2.7.11/src/CPPLINT.cfg | 0 .../IRremoteESP8266-2.7.11/src/IRac.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRac.h | 0 .../IRremoteESP8266-2.7.11/src/IRrecv.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRrecv.h | 0 .../src/IRremoteESP8266.h | 0 .../IRremoteESP8266-2.7.11/src/IRsend.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRsend.h | 0 .../IRremoteESP8266-2.7.11/src/IRtext.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRtext.h | 0 .../IRremoteESP8266-2.7.11/src/IRtimer.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRtimer.h | 0 .../IRremoteESP8266-2.7.11/src/IRutils.cpp | 0 .../IRremoteESP8266-2.7.11/src/IRutils.h | 0 .../IRremoteESP8266-2.7.11/src/i18n.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Airwell.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Airwell.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Amcor.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Amcor.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Argo.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Argo.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Carrier.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Carrier.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Coolix.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Coolix.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Corona.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Corona.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Daikin.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Daikin.h | 0 .../src/ir_Delonghi.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Delonghi.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Denon.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Dish.cpp | 0 .../src/ir_Doshisha.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Electra.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Electra.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Epson.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Fujitsu.h | 0 .../IRremoteESP8266-2.7.11/src/ir_GICable.cpp | 0 .../src/ir_GlobalCache.cpp | 0 .../src/ir_Goodweather.cpp | 0 .../src/ir_Goodweather.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Gree.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Gree.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Haier.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Haier.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Hitachi.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Inax.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_JVC.cpp | 0 .../src/ir_Kelvinator.cpp | 0 .../src/ir_Kelvinator.h | 0 .../IRremoteESP8266-2.7.11/src/ir_LG.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Lego.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Lutron.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_MWM.cpp | 0 .../src/ir_Magiquest.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Magiquest.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Metz.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Midea.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Midea.h | 0 .../src/ir_Mitsubishi.cpp | 0 .../src/ir_Mitsubishi.h | 0 .../src/ir_MitsubishiHeavy.cpp | 0 .../src/ir_MitsubishiHeavy.h | 0 .../src/ir_Multibrackets.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_NEC.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_NEC.h | 0 .../src/ir_Neoclima.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Neoclima.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Nikai.cpp | 0 .../src/ir_Panasonic.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Panasonic.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Pronto.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_RCMM.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Samsung.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Samsung.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sanyo.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Sharp.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sharp.h | 0 .../src/ir_Sherwood.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Sony.cpp | 0 .../src/ir_Symphony.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Tcl.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Tcl.h | 0 .../src/ir_Technibel.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Technibel.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Teco.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Teco.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Toshiba.h | 0 .../src/ir_Transcold.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Transcold.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Trotec.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Trotec.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Vestel.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Vestel.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Voltas.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Voltas.h | 0 .../src/ir_Whirlpool.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Whirlpool.h | 0 .../IRremoteESP8266-2.7.11/src/ir_Whynter.cpp | 0 .../IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp | 0 .../src/locale/README.md | 0 .../IRremoteESP8266-2.7.11/src/locale/de-CH.h | 0 .../IRremoteESP8266-2.7.11/src/locale/de-DE.h | 0 .../src/locale/defaults.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-AU.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-IE.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-UK.h | 0 .../IRremoteESP8266-2.7.11/src/locale/en-US.h | 0 .../IRremoteESP8266-2.7.11/src/locale/es-ES.h | 0 .../IRremoteESP8266-2.7.11/src/locale/fr-FR.h | 0 .../IRremoteESP8266-2.7.11/src/locale/it-IT.h | 0 .../IRremoteESP8266-2.7.11/src/locale/zh-CN.h | 0 .../IRremoteESP8266-2.7.11/test/IRac_test.cpp | 0 .../test/IRrecv_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/IRsend_test.h | 0 .../test/IRutils_test.cpp | 0 .../IRremoteESP8266-2.7.11/test/Makefile | 0 .../test/ir_Airwell_test.cpp | 0 .../test/ir_Aiwa_test.cpp | 0 .../test/ir_Amcor_test.cpp | 0 .../test/ir_Argo_test.cpp | 0 .../test/ir_Carrier_test.cpp | 0 .../test/ir_Coolix_test.cpp | 0 .../test/ir_Corona_test.cpp | 0 .../test/ir_Daikin_test.cpp | 0 .../test/ir_Delonghi_test.cpp | 0 .../test/ir_Denon_test.cpp | 0 .../test/ir_Dish_test.cpp | 0 .../test/ir_Doshisha_test.cpp | 0 .../test/ir_Electra_test.cpp | 0 .../test/ir_Epson_test.cpp | 0 .../test/ir_Fujitsu_test.cpp | 0 .../test/ir_GICable_test.cpp | 0 .../test/ir_GlobalCache_test.cpp | 0 .../test/ir_Goodweather_test.cpp | 0 .../test/ir_Gree_test.cpp | 0 .../test/ir_Haier_test.cpp | 0 .../test/ir_Hitachi_test.cpp | 0 .../test/ir_Inax_test.cpp | 0 .../test/ir_JVC_test.cpp | 0 .../test/ir_Kelvinator_test.cpp | 0 .../test/ir_LG_test.cpp | 0 .../test/ir_Lasertag_test.cpp | 0 .../test/ir_Lego_test.cpp | 0 .../test/ir_Lutron_test.cpp | 0 .../test/ir_MWM_test.cpp | 0 .../test/ir_Magiquest_test.cpp | 0 .../test/ir_Metz_test.cpp | 0 .../test/ir_Midea_test.cpp | 0 .../test/ir_MitsubishiHeavy_test.cpp | 0 .../test/ir_Mitsubishi_test.cpp | 0 .../test/ir_Multibrackets_test.cpp | 0 .../test/ir_NEC_test.cpp | 0 .../test/ir_Neoclima_test.cpp | 0 .../test/ir_Nikai_test.cpp | 0 .../test/ir_Panasonic_test.cpp | 0 .../test/ir_Pioneer_test.cpp | 0 .../test/ir_Pronto_test.cpp | 0 .../test/ir_RC5_RC6_test.cpp | 0 .../test/ir_RCMM_test.cpp | 0 .../test/ir_Samsung_test.cpp | 0 .../test/ir_Sanyo_test.cpp | 0 .../test/ir_Sharp_test.cpp | 0 .../test/ir_Sherwood_test.cpp | 0 .../test/ir_Sony_test.cpp | 0 .../test/ir_Symphony_test.cpp | 0 .../test/ir_Tcl_test.cpp | 0 .../test/ir_Technibel_test.cpp | 0 .../test/ir_Teco_test.cpp | 0 .../test/ir_Toshiba_test.cpp | 0 .../test/ir_Transcold_test.cpp | 0 .../test/ir_Trotec_test.cpp | 0 .../test/ir_Vestel_test.cpp | 0 .../test/ir_Voltas_test.cpp | 0 .../test/ir_Whirlpool_test.cpp | 0 .../test/ir_Whynter_test.cpp | 0 .../test/ir_Zepeal_test.cpp | 0 .../IRremoteESP8266-2.7.11/tools/Makefile | 0 .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 0 .../tools/auto_analyse_raw_data_test.py | 0 .../tools/gc_decode.cpp | 0 .../tools/generate_irtext_h.sh | 0 .../IRremoteESP8266-2.7.11/tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 .../tools/raw_to_pronto_code.py | 0 .../tools/raw_to_pronto_code_test.py | 0 .../tools/scrape_supported_devices.py | 0 .../NeoPixelBus-2.6.0/.gitattributes | 0 .../NeoPixelBus-2.6.0/.github/FUNDING.yml | 0 .../.github/ISSUE_TEMPLATE/all-others.md | 0 .../.github/ISSUE_TEMPLATE/bug_report.md | 0 .../.github/ISSUE_TEMPLATE/feature_request.md | 0 .../lib_basic}/NeoPixelBus-2.6.0/.gitignore | 0 .../lib_basic}/NeoPixelBus-2.6.0/COPYING | 0 .../lib_basic}/NeoPixelBus-2.6.0/ReadMe.md | 0 .../examples/DotStarTest/DotStarTest.ino | 0 .../NeoPixelBrightness/NeoPixelBrightness.ino | 0 .../examples/NeoPixelGamma/NeoPixelGamma.ino | 0 .../examples/NeoPixelTest/NeoPixelTest.ino | 0 .../NeoPixelAnimation/NeoPixelAnimation.ino | 0 .../NeoPixelCylon/NeoPixelCylon.ino | 0 .../NeoPixelFunFadeInOut.ino | 0 .../NeoPixelFunLoop/NeoPixelFunLoop.ino | 0 .../NeoPixelFunRandomChange.ino | 0 .../NeoPixelRotateLoop/NeoPixelRotateLoop.ino | 0 .../bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino | 0 .../bitmaps/NeoPixelBitmap/Strings.bmp | Bin .../bitmaps/NeoPixelBitmap/StringsW.bmp | Bin .../bitmaps/NeoPixelBufferCylon/Cylon.pdn | Bin .../bitmaps/NeoPixelBufferCylon/CylonGrb.h | 0 .../bitmaps/NeoPixelBufferCylon/CylonGrbw.h | 0 .../NeoPixelBufferCylon.ino | 0 .../NeoPixelBufferShader.ino | 0 .../NeoPixelDibTest/NeoPixelDibTest.ino | 0 .../NeoSegmentBus/NeoSegmentBus.ino | 0 .../NeoSegmentFade/NeoSegmentFade.ino | 0 .../NeoPixelMosaicDump/NeoPixelMosaicDump.ino | 0 .../NeoPixelMosaicTest/NeoPixelMosaicTest.ino | 0 .../NeoPixelRingTopologyTest.ino | 0 .../NeoPixelTilesDump/NeoPixelTilesDump.ino | 0 .../NeoPixelTilesTest/NeoPixelTilesTest.ino | 0 .../NeoPixelTopologyDump.ino | 0 .../NeoPixelTopologyTest.ino | 0 .../extras/curves/circular.png | Bin .../NeoPixelBus-2.6.0/extras/curves/cubic.png | Bin .../extras/curves/different.png | Bin .../extras/curves/exponential.png | Bin .../NeoPixelBus-2.6.0/extras/curves/gamma.png | Bin .../extras/curves/pronounced.png | Bin .../extras/curves/quadratic.png | Bin .../extras/curves/quintic.png | Bin .../extras/curves/sinusoidal.png | Bin .../lib_basic}/NeoPixelBus-2.6.0/keywords.txt | 0 .../lib_basic}/NeoPixelBus-2.6.0/library.json | 0 .../NeoPixelBus-2.6.0/library.properties | 0 .../NeoPixelBus-2.6.0/src/NeoPixelAnimator.h | 0 .../src/NeoPixelBrightnessBus.h | 0 .../NeoPixelBus-2.6.0/src/NeoPixelBus.h | 0 .../src/NeoPixelSegmentBus.h | 0 .../src/internal/DotStarColorFeatures.h | 0 .../src/internal/DotStarGenericMethod.h | 0 .../src/internal/Esp32_i2s.c | 0 .../src/internal/Esp32_i2s.h | 0 .../src/internal/HsbColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/HsbColor.h | 0 .../src/internal/HslColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/HslColor.h | 0 .../src/internal/HtmlColor.cpp | 0 .../src/internal/HtmlColor.h | 0 .../src/internal/HtmlColorNameStrings.cpp | 0 .../src/internal/HtmlColorNameStrings.h | 0 .../src/internal/HtmlColorNames.cpp | 0 .../src/internal/HtmlColorShortNames.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/Layouts.h | 0 .../src/internal/Lpd8806ColorFeatures.h | 0 .../src/internal/Lpd8806GenericMethod.h | 0 .../src/internal/NeoArmMethod.h | 0 .../src/internal/NeoAvrMethod.h | 0 .../src/internal/NeoBitmapFile.h | 0 .../src/internal/NeoBuffer.h | 0 .../src/internal/NeoBufferContext.h | 0 .../src/internal/NeoBufferMethods.h | 0 .../src/internal/NeoColorFeatures.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoDib.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoEase.h | 0 .../src/internal/NeoEsp32I2sMethod.h | 0 .../src/internal/NeoEsp32RmtMethod.cpp | 0 .../src/internal/NeoEsp32RmtMethod.h | 0 .../src/internal/NeoEsp8266DmaMethod.h | 0 .../src/internal/NeoEsp8266UartMethod.cpp | 0 .../src/internal/NeoEsp8266UartMethod.h | 0 .../src/internal/NeoEspBitBangMethod.h | 0 .../src/internal/NeoGamma.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/NeoGamma.h | 0 .../src/internal/NeoHueBlend.h | 0 .../src/internal/NeoMosaic.h | 0 .../src/internal/NeoNrf52xMethod.h | 0 .../src/internal/NeoPixelAnimator.cpp | 0 .../src/internal/NeoPixelAvr.c | 0 .../src/internal/NeoRingTopology.h | 0 .../src/internal/NeoSegmentFeatures.h | 0 .../src/internal/NeoSettings.h | 0 .../src/internal/NeoSpriteSheet.h | 0 .../NeoPixelBus-2.6.0/src/internal/NeoTiles.h | 0 .../src/internal/NeoTm1814ColorFeatures.h | 0 .../src/internal/NeoTopology.h | 0 .../src/internal/P9813ColorFeatures.h | 0 .../src/internal/P9813GenericMethod.h | 0 .../src/internal/RgbColor.cpp | 0 .../NeoPixelBus-2.6.0/src/internal/RgbColor.h | 0 .../src/internal/RgbwColor.cpp | 0 .../src/internal/RgbwColor.h | 0 .../src/internal/SegmentDigit.cpp | 0 .../src/internal/SegmentDigit.h | 0 .../src/internal/TwoWireBitBangImple.h | 0 .../src/internal/TwoWireBitBangImpleAvr.h | 0 .../src/internal/TwoWireSpiImple.h | 0 .../src/internal/Ws2801GenericMethod.h | 0 .../OneWire.cpp | 0 .../OneWire.h | 0 .../README.md | 0 .../DS18x20_Temperature.pde | 0 .../examples/DS2408_Switch/DS2408_Switch.pde | 0 .../examples/DS250x_PROM/DS250x_PROM.pde | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 .../lib_basic}/TasmotaModbus-1.2.0/README.md | 0 .../examples/modbustest/modbustest.ino | 0 .../TasmotaModbus-1.2.0/keywords.txt | 0 .../TasmotaModbus-1.2.0/library.json | 0 .../TasmotaModbus-1.2.0/library.properties | 0 .../TasmotaModbus-1.2.0/src/TasmotaModbus.cpp | 0 .../TasmotaModbus-1.2.0/src/TasmotaModbus.h | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_GFX.cpp | 0 .../Adafruit_GFX.h | 0 .../Adafruit_SPITFT.cpp | 0 .../Adafruit_SPITFT.h | 0 .../Adafruit_SPITFT_Macros.h | 0 .../Fonts/FreeMono12pt7b.h | 0 .../Fonts/FreeMono18pt7b.h | 0 .../Fonts/FreeMono24pt7b.h | 0 .../Fonts/FreeMono9pt7b.h | 0 .../Fonts/FreeMonoBold12pt7b.h | 0 .../Fonts/FreeMonoBold18pt7b.h | 0 .../Fonts/FreeMonoBold24pt7b.h | 0 .../Fonts/FreeMonoBold9pt7b.h | 0 .../Fonts/FreeMonoBoldOblique12pt7b.h | 0 .../Fonts/FreeMonoBoldOblique18pt7b.h | 0 .../Fonts/FreeMonoBoldOblique24pt7b.h | 0 .../Fonts/FreeMonoBoldOblique9pt7b.h | 0 .../Fonts/FreeMonoOblique12pt7b.h | 0 .../Fonts/FreeMonoOblique18pt7b.h | 0 .../Fonts/FreeMonoOblique24pt7b.h | 0 .../Fonts/FreeMonoOblique9pt7b.h | 0 .../Fonts/FreeSans12pt7b.h | 0 .../Fonts/FreeSans18pt7b.h | 0 .../Fonts/FreeSans24pt7b.h | 0 .../Fonts/FreeSans9pt7b.h | 0 .../Fonts/FreeSansBold12pt7b.h | 0 .../Fonts/FreeSansBold18pt7b.h | 0 .../Fonts/FreeSansBold24pt7b.h | 0 .../Fonts/FreeSansBold9pt7b.h | 0 .../Fonts/FreeSansBoldOblique12pt7b.h | 0 .../Fonts/FreeSansBoldOblique18pt7b.h | 0 .../Fonts/FreeSansBoldOblique24pt7b.h | 0 .../Fonts/FreeSansBoldOblique9pt7b.h | 0 .../Fonts/FreeSansOblique12pt7b.h | 0 .../Fonts/FreeSansOblique18pt7b.h | 0 .../Fonts/FreeSansOblique24pt7b.h | 0 .../Fonts/FreeSansOblique9pt7b.h | 0 .../Fonts/FreeSerif12pt7b.h | 0 .../Fonts/FreeSerif18pt7b.h | 0 .../Fonts/FreeSerif24pt7b.h | 0 .../Fonts/FreeSerif9pt7b.h | 0 .../Fonts/FreeSerifBold12pt7b.h | 0 .../Fonts/FreeSerifBold18pt7b.h | 0 .../Fonts/FreeSerifBold24pt7b.h | 0 .../Fonts/FreeSerifBold9pt7b.h | 0 .../Fonts/FreeSerifBoldItalic12pt7b.h | 0 .../Fonts/FreeSerifBoldItalic18pt7b.h | 0 .../Fonts/FreeSerifBoldItalic24pt7b.h | 0 .../Fonts/FreeSerifBoldItalic9pt7b.h | 0 .../Fonts/FreeSerifItalic12pt7b.h | 0 .../Fonts/FreeSerifItalic18pt7b.h | 0 .../Fonts/FreeSerifItalic24pt7b.h | 0 .../Fonts/FreeSerifItalic9pt7b.h | 0 .../Fonts/Org_01.h | 0 .../Fonts/Picopixel.h | 0 .../Fonts/Tiny3x3a2pt7b.h | 0 .../Fonts/TomThumb.h | 0 .../README.md | 0 .../examples/mock_ili9341/mock_ili9341.ino | 0 .../fontconvert/Makefile | 0 .../fontconvert/fontconvert.c | 0 .../fontconvert/fontconvert_win.md | 0 .../fontconvert/makefonts.sh | 0 .../gfxfont.h | 0 .../glcdfont.c | 0 .../library.properties | 0 .../license.txt | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_ILI9341.cpp | 0 .../Adafruit_ILI9341.h | 0 .../README.md | 0 .../breakouttouchpaint/.esp8266.test.skip | 0 .../breakouttouchpaint/breakouttouchpaint.ino | 0 .../fulltest_featherwing/.mega2560.test.skip | 0 .../fulltest_featherwing.ino | 0 .../examples/graphicstest/graphicstest.ino | 0 .../.mega2560.test.skip | 0 .../graphicstest_featherwing.ino | 0 .../examples/onoffbutton/onoffbutton.ino | 0 .../onoffbutton_breakout/.esp8266.test.skip | 0 .../onoffbutton_breakout.ino | 0 .../examples/pictureEmbed/dragon.h | 0 .../examples/pictureEmbed/pictureEmbed.ino | 0 .../examples/spitftbitmap/spitftbitmap.ino | 0 .../examples/touchpaint/touchpaint.ino | 0 .../.mega2560.test.skip | 0 .../touchpaint_featherwing.ino | 0 .../library.properties | 0 .../Adafruit_LEDBackpack.cpp | 0 .../Adafruit_LEDBackpack.h | 0 .../Adafruit_LED_Backpack-1.1.6/README.md | 0 .../Adafruit_LED_Backpack-1.1.6/README.txt | 0 .../examples/HT16K33/HT16K33.ino | 0 .../examples/bargraph24/bargraph24.ino | 0 .../examples/bicolor8x8/bicolor8x8.pde | 0 .../clock_sevenseg_ds1307.ino | 0 .../clock_sevenseg_gps/clock_sevenseg_gps.ino | 0 .../examples/matrix16x8/matrix16x8.ino | 0 .../examples/matrix8x8/matrix8x8.ino | 0 .../minimatrix16x8/minimatrix16x8.ino | 0 .../examples/quadalphanum/quadalphanum.ino | 0 .../quadalphanum_mini/quadalphanum_mini.ino | 0 .../examples/roboface/roboface.pde | 0 .../examples/sevenseg/sevenseg.ino | 0 .../examples/wavface/wavface.pde | 0 .../examples/wavface/wavs/beware_i.wav | Bin .../examples/wavface/wavs/ihunger.wav | Bin .../examples/wavface/wavs/run_cowd.wav | Bin .../library.properties | 0 .../Adafruit_LED_Backpack-1.1.6/license.txt | 0 .../Adafruit_SH1106.cpp | 0 .../Adafruit_SH1106.h | 0 .../Adafruit_SH1106-gemu-1.0/LICENSE.txt | 0 .../Adafruit_SH1106-gemu-1.0/README.md | 0 .../sh1106_128x64_i2c/sh1106_128x64_i2c.ino | 0 .../sh1106_128x64_spi/sh1106_128x64_spi.ino | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Adafruit_SSD1306.cpp | 0 .../Adafruit_SSD1306.h | 0 .../Adafruit_SSD1306-1.3.0-gemu-1.1/README.md | 0 .../OLED_featherwing/OLED_featherwing.ino | 0 .../ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino | 0 .../ssd1306_128x32_spi/ssd1306_128x32_spi.ino | 0 .../ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino | 0 .../ssd1306_128x64_spi/ssd1306_128x64_spi.ino | 0 .../library.properties | 0 .../license.txt | 0 .../Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h | 0 .../Adafruit_SSD1351-gemu-1.0/README.md | 0 .../Adafruit_SSD1351-gemu-1.0/SSD1351.cpp | 0 .../Adafruit_SSD1351-gemu-1.0/SSD1351.h | 0 .../Adafruit_SSD1351-gemu-1.0/Tiger.c | 0 .../Adafruit_SSD1351-gemu-1.0/Tiger.rgb | Bin .../Adafruit_SSD1351-gemu-1.0/keywords.txt | 0 .../library.properties | 0 .../Adafruit_SSD1351-gemu-1.0/spi_register.h | 0 .../Arduino_ST7789.cpp | 0 .../Arduino_ST7789-gemu-1.0/Arduino_ST7789.h | 0 .../Arduino_ST7789-gemu-1.0/README.txt | 0 .../examples/graphicstest/graphicstest.ino | 0 .../Arduino_ST7789-gemu-1.0/keywords.txt | 0 .../library.properties | 0 .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp | 0 .../JaretBurkett_ILI9488-gemu-1.0/ILI9488.h | 0 .../JaretBurkett_ILI9488-gemu-1.0/README.md | 0 .../examples/graphicstest/graphicstest.ino | 0 .../keywords.txt | 0 .../library.properties | 0 .../spi_register.h | 0 .../LiquidCrystal_I2C.cpp | 0 .../LiquidCrystal_I2C.h | 0 .../LiquidCrystal_I2C.o | Bin .../LiquidCrystal_I2C-1.1.3/README.md | 0 .../examples/CustomChars/CustomChars.pde | 0 .../examples/HelloWorld/HelloWorld.pde | 0 .../examples/SerialDisplay/SerialDisplay.pde | 0 .../LiquidCrystal_I2C-1.1.3/keywords.txt | 0 .../LiquidCrystal_I2C-1.1.3/library.json | 0 .../library.properties | 0 .../Xlatb_RA8876-gemu-1.0/RA8876.cpp | 0 .../Xlatb_RA8876-gemu-1.0/RA8876.h | 0 .../Xlatb_RA8876-gemu-1.0/README.md | 0 .../Xlatb_RA8876-gemu-1.0/keywords.txt | 0 .../Xlatb_RA8876-gemu-1.0/library.properties | 0 .../Xlatb_RA8876-gemu-1.0/spi_register.h | 0 .../.gitignore | 0 .../.travis.yml | 0 .../Arduino/epd2in9-demo/epd2in9-demo.ino | 0 .../Arduino/libraries/readme.txt | 0 .../LICENSE | 0 .../Makefile | 0 .../README.md | 0 .../components/epaper-29-ws/component.mk | 0 .../components/epaper-29-ws/epaper-29-ws.c | 0 .../components/epaper-29-ws/epaper-29-ws.h | 0 .../components/epaper-29-ws/epaper_font.c | 0 .../components/epaper-29-ws/epaper_fonts.h | 0 .../components/epaper-29-ws/font16.c | 0 .../components/epaper-29-ws/font20.c | 0 .../components/epaper-29-ws/font8.c | 0 .../components/epaper-29-ws/imagedata.cpp | 0 .../components/epaper-29-ws/imagedata.h | 0 .../docs/Doxyfile | 0 .../docs/Makefile | 0 .../docs/README.md | 0 .../docs/conf.py | 0 .../docs/gen-dxd.py | 0 .../docs/index.rst | 0 .../docs/link-roles.py | 0 .../docs/repo_util.py | 0 .../docs/requirements.txt | 0 .../library.properties | 0 .../main/README.md | 0 .../main/component.mk | 0 .../main/esp-epaper-29-ws.c | 0 .../main/imagedata.c | 0 .../main/imagedata.h | 0 .../pictures/2.9inch_e-Paper_Datasheet.pdf | Bin .../pictures/e-paper-and-esp-sample-image.jpg | Bin .../pictures/e-paper-and-esp-sample-text.jpg | Bin .../pictures/espresif-logo.bmp | Bin .../pictures/image-conversion-setup.png | Bin .../src/epd2in9.cpp | 0 .../src/epd2in9.h | 0 .../src/epd4in2.cpp | 0 .../src/epd4in2.h | 0 .../src/epdif.cpp | 0 .../src/epdif.h | 0 .../src/epdpaint.cpp | 0 .../src/epdpaint.h | 0 .../src/font12.c | 0 .../src/font16.c | 0 .../src/font20.c | 0 .../src/font24.c | 0 .../src/font8.c | 0 .../src/fonts.h | 0 .../src/renderer.cpp | 0 .../src/renderer.h | 0 .../lib_div}/A4988_Stepper/README.adoc | 0 .../lib_div}/A4988_Stepper/keywords.txt | 0 .../lib_div}/A4988_Stepper/library.properties | 0 .../A4988_Stepper/src/A4988_Stepper.cpp | 0 .../A4988_Stepper/src/A4988_Stepper.h | 0 .../lib_div}/ArduinoNTPd/NTPPacket.cpp | 0 .../lib_div}/ArduinoNTPd/NTPPacket.h | 0 .../lib_div}/ArduinoNTPd/NTPServer.cpp | 0 .../lib_div}/ArduinoNTPd/NTPServer.h | 0 .../lib_div}/ArduinoNTPd/library.properties | 0 .../lib_div}/LibTeleinfo/README.md | 0 .../lib_div}/LibTeleinfo/library.json | 0 .../lib_div}/LibTeleinfo/library.properties | 0 .../lib_div}/LibTeleinfo/src/LibTeleinfo.cpp | 0 .../lib_div}/LibTeleinfo/src/LibTeleinfo.h | 0 .../lib_div}/NewPing-1.9.1/README.md | 0 .../NewPing15SensorsTimer.pde | 0 .../NewPing3Sensors/NewPing3Sensors.pde | 0 .../NewPingEventTimer/NewPingEventTimer.pde | 0 .../NewPingExample/NewPingExample.pde | 0 .../NewPingTimerMedian/NewPingTimerMedian.pde | 0 .../examples/TimerExample/TimerExample.pde | 0 .../lib_div}/NewPing-1.9.1/keywords.txt | 0 .../lib_div}/NewPing-1.9.1/library.properties | 0 .../lib_div}/NewPing-1.9.1/src/NewPing.cpp | 0 .../lib_div}/NewPing-1.9.1/src/NewPing.h | 0 .../lib_div}/OpenTherm-0.9.0/LICENSE | 0 .../lib_div}/OpenTherm-0.9.0/README.md | 0 .../lib_div}/OpenTherm-0.9.0/keywords.txt | 0 .../OpenTherm-0.9.0/library.properties | 0 .../OpenTherm-0.9.0/src/OpenTherm.cpp | 0 .../lib_div}/OpenTherm-0.9.0/src/OpenTherm.h | 0 .../lib_div}/esp-knx-ip-0.5.2/LICENSE | 0 .../lib_div}/esp-knx-ip-0.5.2/README.md | 0 .../environment-sensor/environment-sensor.ino | 0 .../examples/sonoff/sonoff.ino | 0 .../examples/static-config/static-config.ino | 0 .../lib_div}/esp-knx-ip-0.5.2/keywords.txt | 0 .../lib_div}/esp-knx-ip-0.5.2/library.json | 0 .../esp-knx-ip-0.5.2/library.properties.off | 0 .../lib_div}/esp-knx-ip-0.5.2/src/DPT.h | 0 .../src/esp-knx-ip-config.cpp | 0 .../src/esp-knx-ip-conversion.cpp | 0 .../esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp | 0 .../src/esp-knx-ip-webserver.cpp | 0 .../esp-knx-ip-0.5.2/src/esp-knx-ip.cpp | 0 .../esp-knx-ip-0.5.2/src/esp-knx-ip.h | 0 .../lib_i2c}/Adafruit_BusIO/.travis.yml | 0 .../Adafruit_BusIO_Register.cpp | 0 .../Adafruit_BusIO/Adafruit_BusIO_Register.h | 0 .../Adafruit_BusIO/Adafruit_I2CDevice.cpp | 0 .../Adafruit_BusIO/Adafruit_I2CDevice.h | 0 .../Adafruit_BusIO/Adafruit_I2CRegister.h | 0 .../Adafruit_BusIO/Adafruit_SPIDevice.cpp | 0 .../Adafruit_BusIO/Adafruit_SPIDevice.h | 0 .../lib_i2c}/Adafruit_BusIO/LICENSE | 0 .../lib_i2c}/Adafruit_BusIO/README.md | 0 .../i2c_address_detect/i2c_address_detect.ino | 0 .../examples/i2c_readwrite/i2c_readwrite.ino | 0 .../examples/i2c_registers/i2c_registers.ino | 0 .../i2corspi_register/i2corspi_register.ino | 0 .../examples/spi_modetest/spi_modetest.ino | 0 .../examples/spi_readwrite/spi_readwrite.ino | 0 .../examples/spi_registers/spi_registers.ino | 0 .../Adafruit_BusIO/library.properties | 0 .../Adafruit_CCS811-1.0.0.14/.travis.yml | 0 .../Adafruit_CCS811.cpp | 0 .../Adafruit_CCS811.h | 0 .../lib_i2c}/Adafruit_CCS811-1.0.0.14/LICENSE | 0 .../Adafruit_CCS811-1.0.0.14/README.md | 0 .../CCS811_OLED_Demo/CCS811_OLED_Demo.ino | 0 .../examples/CCS811_test/CCS811_test.ino | 0 .../library.properties | 0 .../Adafruit_MAX31865.cpp | 0 .../Adafruit_MAX31865.h | 0 .../Adafruit_MAX31865-1.1.0-custom/README.md | 0 .../Adafruit_MAX31865-1.1.0-custom/README.txt | 0 .../examples/max31865/max31865.ino | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../.github/workflows/githubci.yml | 0 .../Adafruit_MCP9808_Tasmota/.gitignore | 0 .../Adafruit_MCP9808.cpp | 0 .../Adafruit_MCP9808.h | 0 .../Adafruit_MCP9808_Tasmota/README.md | 0 .../Adafruit_MCP9808_Tasmota/assets/board.jpg | Bin .../code-of-conduct.md | 0 .../examples/mcp9808test/mcp9808test.ino | 0 .../library.properties | 0 .../Adafruit_MCP9808_Tasmota/license.txt | 0 .../Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp | 0 .../Adafruit_SGP30-1.2.0/Adafruit_SGP30.h | 0 .../lib_i2c}/Adafruit_SGP30-1.2.0/README.md | 0 .../examples/sgp30test/sgp30test.ino | 0 .../Adafruit_SGP30-1.2.0/library.properties | 0 .../lib_i2c}/Adafruit_SGP30-1.2.0/license.txt | 0 .../lib_i2c}/Adafruit_SGP30-1.2.0/travis.yml | 0 .../Adafruit_TSL2591.cpp | 0 .../Adafruit_TSL2591.h | 0 .../library.properties | 0 .../.github/ISSUE_TEMPLATE.md | 0 .../.github/PULL_REQUEST_TEMPLATE.md | 0 .../lib_i2c}/Adafruit_VEML7700/.gitignore | 0 .../lib_i2c}/Adafruit_VEML7700/.travis.yml | 0 .../Adafruit_VEML7700/Adafruit_VEML7700.cpp | 0 .../Adafruit_VEML7700/Adafruit_VEML7700.h | 0 .../lib_i2c}/Adafruit_VEML7700/README.md | 0 .../examples/veml7700_test/veml7700_test.ino | 0 .../Adafruit_VEML7700/library.properties | 0 .../lib_i2c}/Adafruit_VEML7700/license.txt | 0 .../BME680_driver-bme680_v3.5.9/LICENSE | 0 .../BME680_driver-bme680_v3.5.9/README.md | 0 .../Self test/bme680_selftest.c | 0 .../Self test/bme680_selftest.h | 0 .../BME680_driver-bme680_v3.5.9/bme680.c | 0 .../BME680_driver-bme680_v3.5.9/bme680.h | 0 .../BME680_driver-bme680_v3.5.9/bme680_defs.h | 0 .../library.properties | 0 .../lib_i2c}/FT5206_Library/.gitignore | 0 .../lib_i2c}/FT5206_Library/LICENSE | 0 .../lib_i2c}/FT5206_Library/README.md | 0 .../lib_i2c}/FT5206_Library/keywords.txt | 0 .../FT5206_Library/library.properties | 0 .../lib_i2c}/FT5206_Library/src/FT5206.cpp | 0 .../lib_i2c}/FT5206_Library/src/FT5206.h | 0 .../lib_i2c}/FrogmoreScd30/FrogmoreScd30.cpp | 0 .../lib_i2c}/FrogmoreScd30/FrogmoreScd30.h | 0 .../lib_i2c}/FrogmoreScd30/library.properties | 0 {lib_i2c => lib/lib_i2c}/HPMA115S0/LICENSE.md | 0 {lib_i2c => lib/lib_i2c}/HPMA115S0/README.md | 0 .../lib_i2c}/HPMA115S0/example/example.ino | 0 .../lib_i2c}/HPMA115S0/library.properties | 0 .../lib_i2c}/HPMA115S0/src/hpma115S0.cpp | 0 .../lib_i2c}/HPMA115S0/src/hpma115S0.h | 0 .../lib_i2c}/I2Cdevlib-Core/.library.json | 0 .../lib_i2c}/I2Cdevlib-Core/I2Cdev.cpp | 0 .../lib_i2c}/I2Cdevlib-Core/I2Cdev.h | 0 .../lib_i2c}/I2Cdevlib-Core/keywords.txt | 0 .../lib_i2c}/I2Cdevlib-Core/library.json | 0 .../Examples/MPU6050_DMP6/MPU6050_DMP6.ino | 0 .../Processing/MPUTeapot/MPUTeapot.pde | 0 .../Examples/MPU6050_raw/MPU6050_raw.ino | 0 .../lib_i2c}/I2Cdevlib-MPU6050/MPU6050.cpp | 0 .../lib_i2c}/I2Cdevlib-MPU6050/MPU6050.h | 0 .../MPU6050_6Axis_MotionApps20.h | 0 .../MPU6050_9Axis_MotionApps41.h | 0 .../I2Cdevlib-MPU6050/helper_3dmath.h | 0 .../I2Cdevlib-MPU6050/library.properties | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/.gitignore | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/.hgignore | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/.travis.yml | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/COPYING | 0 .../Joba_Tsl2561-2.0.10/COPYING.LESSER | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/README | 0 .../examples/Autogain/Autogain.ino | 0 .../examples/Simple/Simple.ino | 0 .../examples/Testing/Testing.ino | 0 .../examples/Utility/Utility.ino | 0 .../examples/platformio.ini | 0 .../examples/platformio.sh | 0 .../Joba_Tsl2561-2.0.10/lib/readme.txt | 0 .../lib_i2c}/Joba_Tsl2561-2.0.10/library.json | 0 .../Joba_Tsl2561-2.0.10/library.properties | 0 .../Joba_Tsl2561-2.0.10/platformio.ini | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561.cpp | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561.h | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp | 0 .../Joba_Tsl2561-2.0.10/src/Tsl2561Util.h | 0 .../lib_i2c}/LOLIN_HP303B/README.md | 0 .../i2c_background/i2c_background.ino | 0 .../examples/i2c_command/i2c_command.ino | 0 .../examples/i2c_interrupt/i2c_interrupt.ino | 0 .../LOLIN_HP303B/examples/library.properties | 0 .../lib_i2c}/LOLIN_HP303B/keywords.txt | 0 .../lib_i2c}/LOLIN_HP303B/library.properties | 0 .../LOLIN_HP303B/src/LOLIN_HP303B.cpp | 0 .../lib_i2c}/LOLIN_HP303B/src/LOLIN_HP303B.h | 0 .../LOLIN_HP303B/src/util/hp303b_consts.h | 0 .../lib_i2c}/LinkedList-1.2.3/LICENSE.txt | 0 .../lib_i2c}/LinkedList-1.2.3/LinkedList.h | 0 .../lib_i2c}/LinkedList-1.2.3/README.md | 0 .../examples/ClassList/ClassList.pde | 0 .../SimpleIntegerList/SimpleIntegerList.pde | 0 .../lib_i2c}/LinkedList-1.2.3/keywords.txt | 0 .../lib_i2c}/LinkedList-1.2.3/library.json | 0 .../LinkedList-1.2.3/library.properties | 0 .../Mutichannel_Gas_Sensor/License.txt | 0 .../lib_i2c}/Mutichannel_Gas_Sensor/README.md | 0 .../examples/GetVersion/GetVersion.ino | 0 .../examples/I2C_Address/I2C_Address.ino | 0 .../examples/RawData/RawData.ino | 0 .../ReadSensorValue_Grove.ino | 0 .../ReadSensorValue_Xadow.ino | 0 .../UpdateFrimware/UpdateFrimware.ino | 0 .../UpdateFrimware/bootloader_atmega168.h | 0 .../examples/UpdateFrimware/gpl.txt | 0 .../examples/calibration/calibration.ino | 0 .../factory_setting/factory_setting.ino | 0 .../examples/new_firmware/new_firmware.ino | 0 .../Mutichannel_Gas_Sensor/library.json | 0 .../Mutichannel_Gas_Sensor/library.properties | 0 .../src/MutichannelGasSensor.cpp | 0 .../src/MutichannelGasSensor.h | 0 .../mlx90640-library/MLX90640_API.cpp | 0 .../lib_i2c}/mlx90640-library/MLX90640_API.h | 0 .../mlx90640-library/library.properties | 0 .../lib_i2c}/vl53l0x-arduino-1.02/.travis.yml | 0 .../lib_i2c}/vl53l0x-arduino-1.02/LICENSE.txt | 0 .../lib_i2c}/vl53l0x-arduino-1.02/README.md | 0 .../lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.cpp | 0 .../lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.h | 0 .../examples/Continuous/Continuous.ino | 0 .../examples/Single/Single.ino | 0 .../vl53l0x-arduino-1.02/keywords.txt | 0 .../vl53l0x-arduino-1.02/library.properties | 0 .../lib_i2c}/vl53l1x-arduino-1.01/LICENSE.txt | 0 .../lib_i2c}/vl53l1x-arduino-1.01/README.md | 0 .../lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.cpp | 0 .../lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.h | 0 .../examples/Continuous/Continuous.ino | 0 .../ContinuousWithDetails.ino | 0 .../vl53l1x-arduino-1.01/keywords.txt | 0 .../vl53l1x-arduino-1.01/library.properties | 0 {lib_rf => lib/lib_rf}/KeeloqLib/README.md | 0 {lib_rf => lib/lib_rf}/KeeloqLib/keywords.txt | 0 .../lib_rf}/KeeloqLib/library.properties | 0 .../lib_rf}/KeeloqLib/src/KeeloqLib.cpp | 0 .../lib_rf}/KeeloqLib/src/KeeloqLib.h | 0 .../tests/KeeloqLibTest/KeeloqLibTest.ino | 0 {lib_rf => lib/lib_rf}/RF24/.gitignore | 0 {lib_rf => lib/lib_rf}/RF24/CONTRIBUTING.md | 0 {lib_rf => lib/lib_rf}/RF24/Doxyfile | 0 {lib_rf => lib/lib_rf}/RF24/LICENSE | 0 {lib_rf => lib/lib_rf}/RF24/Makefile | 0 {lib_rf => lib/lib_rf}/RF24/README.md | 0 {lib_rf => lib/lib_rf}/RF24/RF24.cpp | 0 {lib_rf => lib/lib_rf}/RF24/RF24.h | 0 {lib_rf => lib/lib_rf}/RF24/RF24_config.h | 0 {lib_rf => lib/lib_rf}/RF24/configure | 0 .../lib_rf}/RF24/doxygen-custom.css | 0 .../GettingStarted/GettingStarted.ino | 0 .../GettingStarted_CallResponse.ino | 0 .../GettingStarted_HandlingData.ino | 0 .../GettingStarted_HandlingFailures.ino | 0 .../RF24/examples/Transfer/Transfer.ino | 0 .../TransferTimeouts/TransferTimeouts.ino | 0 .../RF24/examples/Usage/led_remote/Jamfile | 0 .../examples/Usage/led_remote/led_remote.pde | 0 .../RF24/examples/Usage/nordic_fob/Jamfile | 0 .../examples/Usage/nordic_fob/nordic_fob.pde | 0 .../examples/Usage/pingpair_maple/Jamfile | 0 .../examples/Usage/pingpair_maple/main.cpp | 0 .../Usage/pingpair_maple/pingpair_maple.pde | 0 .../lib_rf}/RF24/examples/Usage/readme.md | 0 .../examples/pingpair_ack/pingpair_ack.ino | 0 .../RF24/examples/pingpair_dyn/Jamfile | 0 .../examples/pingpair_dyn/pingpair_dyn.ino | 0 .../examples/pingpair_irq/pingpair_irq.ino | 0 .../pingpair_irq_simple.ino | 0 .../RF24/examples/pingpair_multi_dyn/Jamfile | 0 .../pingpair_multi_dyn/pingpair_multi_dyn.ino | 0 .../pingpair_sleepy/pingpair_sleepy.ino | 0 .../rf24_ATTiny/rf24ping85/rf24ping85.ino | 0 .../timingSearch3pin/timingSearch3pin.ino | 0 .../lib_rf}/RF24/examples/scanner/Jamfile | 0 .../lib_rf}/RF24/examples/scanner/scanner.ino | 0 .../lib_rf}/RF24/examples/starping/Jamfile | 0 .../RF24/examples/starping/starping.pde | 0 .../RF24/examples_linux/Makefile.examples | 0 .../RF24/examples_linux/extra/Makefile | 0 .../RF24/examples_linux/extra/rpi-hub.cpp | 0 .../RF24/examples_linux/extra/scanner.cpp | 0 .../RF24/examples_linux/gettingstarted.cpp | 0 .../gettingstarted_call_response.cpp | 0 .../RF24/examples_linux/interrupts/Makefile | 0 .../gettingstarted_call_response_int.cpp | 0 .../gettingstarted_call_response_int2.cpp | 0 .../interrupts/pingpair_dyn_int.cpp | 0 .../interrupts/transfer_interrupt.cpp | 0 .../RF24/examples_linux/pingpair_dyn.cpp | 0 .../RF24/examples_linux/pingpair_dyn.py | 0 .../lib_rf}/RF24/examples_linux/readme.md | 0 .../lib_rf}/RF24/examples_linux/transfer.cpp | 0 {lib_rf => lib/lib_rf}/RF24/keywords.txt | 0 {lib_rf => lib/lib_rf}/RF24/library.json | 0 .../lib_rf}/RF24/library.properties | 0 {lib_rf => lib/lib_rf}/RF24/nRF24L01.h | 0 {lib_rf => lib/lib_rf}/RF24/printf.h | 0 .../lib_rf}/RF24/pyRF24/crossunixccompiler.py | 0 {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24.cpp | 0 .../RF24/pyRF24/pyRF24/crossunixccompiler.py | 0 .../lib_rf}/RF24/pyRF24/pyRF24/pyRF24.cpp | 0 .../lib_rf}/RF24/pyRF24/pyRF24/readme.md | 0 .../lib_rf}/RF24/pyRF24/pyRF24/setup.py | 0 .../RF24/pyRF24/pyRF24Mesh/example_master.py | 0 .../RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp | 0 .../lib_rf}/RF24/pyRF24/pyRF24Mesh/setup.py | 0 .../pyRF24Network/examples/helloworld_rx.py | 0 .../pyRF24Network/examples/helloworld_tx.py | 0 .../pyRF24/pyRF24Network/pyRF24Network.cpp | 0 .../RF24/pyRF24/pyRF24Network/setup.py | 0 {lib_rf => lib/lib_rf}/RF24/pyRF24/readme.md | 0 {lib_rf => lib/lib_rf}/RF24/pyRF24/setup.py | 0 {lib_rf => lib/lib_rf}/RF24/tests/README | 0 .../lib_rf}/RF24/tests/native/Jamfile | 0 .../RF24/tests/native/pingpair_irq.pde | 0 .../lib_rf}/RF24/tests/native/printf.h | 0 .../RF24/tests/pingpair_blocking/Jamfile | 0 .../pingpair_blocking/pingpair_blocking.pde | 0 .../RF24/tests/pingpair_blocking/printf.h | 0 .../RF24/tests/pingpair_blocking/runtest.py | 0 .../RF24/tests/pingpair_blocking/runtests.sh | 0 .../RF24/tests/pingpair_blocking/test.ex | 0 .../lib_rf}/RF24/tests/pingpair_test/Jamfile | 0 .../tests/pingpair_test/pingpair_test.pde | 0 .../lib_rf}/RF24/tests/pingpair_test/printf.h | 0 .../RF24/tests/pingpair_test/runtest.py | 0 .../RF24/tests/pingpair_test/runtests.sh | 0 .../lib_rf}/RF24/tests/pingpair_test/test.ex | 0 .../RF24/utility/ATTiny/RF24_arch_config.h | 0 .../lib_rf}/RF24/utility/ATTiny/spi.h | 0 .../lib_rf}/RF24/utility/ATXMegaD3/README.md | 0 .../RF24/utility/ATXMegaD3/RF24_arch_config.h | 0 .../RF24/utility/ATXMegaD3/compatibility.c | 0 .../RF24/utility/ATXMegaD3/compatibility.h | 0 .../lib_rf}/RF24/utility/ATXMegaD3/gpio.cpp | 0 .../lib_rf}/RF24/utility/ATXMegaD3/gpio.h | 0 .../RF24/utility/ATXMegaD3/gpio_helper.c | 0 .../RF24/utility/ATXMegaD3/gpio_helper.h | 0 .../lib_rf}/RF24/utility/ATXMegaD3/includes.h | 0 .../lib_rf}/RF24/utility/ATXMegaD3/spi.cpp | 0 .../lib_rf}/RF24/utility/ATXMegaD3/spi.h | 0 .../RF24/utility/Due/RF24_arch_config.h | 0 .../utility/LittleWire/RF24_arch_config.h | 0 .../RF24/utility/LittleWire/includes.h | 0 .../RF24/utility/MRAA/RF24_arch_config.h | 0 .../lib_rf}/RF24/utility/MRAA/compatibility.c | 0 .../lib_rf}/RF24/utility/MRAA/compatibility.h | 0 .../lib_rf}/RF24/utility/MRAA/gpio.cpp | 0 .../lib_rf}/RF24/utility/MRAA/gpio.h | 0 .../lib_rf}/RF24/utility/MRAA/includes.h | 0 .../lib_rf}/RF24/utility/MRAA/spi.cpp | 0 .../lib_rf}/RF24/utility/MRAA/spi.h | 0 .../RF24/utility/RPi/RF24_arch_config.h | 0 .../lib_rf}/RF24/utility/RPi/bcm2835.c | 0 .../lib_rf}/RF24/utility/RPi/bcm2835.h | 0 .../lib_rf}/RF24/utility/RPi/includes.h | 0 .../lib_rf}/RF24/utility/RPi/interrupt.c | 0 .../lib_rf}/RF24/utility/RPi/interrupt.h | 0 .../lib_rf}/RF24/utility/RPi/spi.cpp | 0 {lib_rf => lib/lib_rf}/RF24/utility/RPi/spi.h | 0 .../RF24/utility/SPIDEV/RF24_arch_config.h | 0 .../RF24/utility/SPIDEV/compatibility.c | 0 .../RF24/utility/SPIDEV/compatibility.h | 0 .../lib_rf}/RF24/utility/SPIDEV/gpio.cpp | 0 .../lib_rf}/RF24/utility/SPIDEV/gpio.h | 0 .../lib_rf}/RF24/utility/SPIDEV/includes.h | 0 .../lib_rf}/RF24/utility/SPIDEV/interrupt.c | 0 .../lib_rf}/RF24/utility/SPIDEV/interrupt.h | 0 .../lib_rf}/RF24/utility/SPIDEV/spi.cpp | 0 .../lib_rf}/RF24/utility/SPIDEV/spi.h | 0 .../RF24/utility/Teensy/RF24_arch_config.h | 0 .../RF24/utility/Template/RF24_arch_config.h | 0 .../RF24/utility/Template/compatibility.h | 0 .../lib_rf}/RF24/utility/Template/gpio.h | 0 .../lib_rf}/RF24/utility/Template/includes.h | 0 .../lib_rf}/RF24/utility/Template/spi.h | 0 .../RF24/utility/wiringPi/RF24_arch_config.h | 0 .../lib_rf}/RF24/utility/wiringPi/includes.h | 0 .../lib_rf}/RF24/utility/wiringPi/spi.cpp | 0 .../lib_rf}/RF24/utility/wiringPi/spi.h | 0 {lib_rf => lib/lib_rf}/RF24/wikidoc.xslt | 0 {lib_rf => lib/lib_rf}/cc1101/README.md | 0 {lib_rf => lib/lib_rf}/cc1101/cc1101.cpp | 0 {lib_rf => lib/lib_rf}/cc1101/cc1101.h | 0 {lib_rf => lib/lib_rf}/cc1101/cc1101.h.txt | 0 {lib_rf => lib/lib_rf}/cc1101/ccpacket.h | 0 .../lib_rf}/cc1101/library.properties | 0 {lib_rf => lib/lib_rf}/rc-switch/.gitignore | 0 {lib_rf => lib/lib_rf}/rc-switch/README.md | 0 .../ReceiveDemo_Advanced.ino | 0 .../examples/ReceiveDemo_Advanced/output.ino | 0 .../ReceiveDemo_Simple/ReceiveDemo_Simple.ino | 0 .../rc-switch/examples/SendDemo/SendDemo.ino | 0 .../TypeA_WithDIPSwitches.ino | 0 .../TypeA_WithDIPSwitches_Lightweight.ino | 0 .../TypeB_WithRotaryOrSlidingSwitches.ino | 0 .../TypeC_Intertechno/TypeC_Intertechno.ino | 0 .../examples/TypeD_REV/TypeD_REV.ino | 0 .../examples/Webserver/Webserver.ino | 0 {lib_rf => lib/lib_rf}/rc-switch/keywords.txt | 0 {lib_rf => lib/lib_rf}/rc-switch/library.json | 0 .../lib_rf}/rc-switch/library.properties | 0 .../lib_rf}/rc-switch/platformio.ini | 0 .../lib_rf}/rc-switch/src/RCSwitch.cpp | 0 .../lib_rf}/rc-switch/src/RCSwitch.h | 0 {lib_ssl => lib/lib_ssl}/base64-1.1.1/LICENSE | 0 .../lib_ssl}/base64-1.1.1/Makefile | 0 .../lib_ssl}/base64-1.1.1/README.md | 0 .../lib_ssl}/base64-1.1.1/catch.cpp | 0 .../lib_ssl}/base64-1.1.1/catch.hpp | 0 .../lib_ssl}/base64-1.1.1/library.properties | 0 .../lib_ssl}/base64-1.1.1/src/base64.hpp | 0 .../bearssl_esp8266-customized.txt | 0 .../lib_ssl}/bearssl-esp8266/conf/esp8266.mk | 0 .../bearssl-esp8266/library.properties | 0 .../lib_ssl}/bearssl-esp8266/src/aead/ccm.c | 0 .../lib_ssl}/bearssl-esp8266/src/aead/eax.c | 0 .../lib_ssl}/bearssl-esp8266/src/aead/gcm.c | 0 .../bearssl-esp8266/src/codec/ccopy.c | 0 .../bearssl-esp8266/src/codec/dec16be.c | 0 .../bearssl-esp8266/src/codec/dec16le.c | 0 .../bearssl-esp8266/src/codec/dec32be.c | 0 .../bearssl-esp8266/src/codec/dec32le.c | 0 .../bearssl-esp8266/src/codec/dec64be.c | 0 .../bearssl-esp8266/src/codec/dec64le.c | 0 .../bearssl-esp8266/src/codec/enc16be.c | 0 .../bearssl-esp8266/src/codec/enc16le.c | 0 .../bearssl-esp8266/src/codec/enc32be.c | 0 .../bearssl-esp8266/src/codec/enc32le.c | 0 .../bearssl-esp8266/src/codec/enc64be.c | 0 .../bearssl-esp8266/src/codec/enc64le.c | 0 .../bearssl-esp8266/src/codec/pemdec.c | 0 .../bearssl-esp8266/src/codec/pemenc.c | 0 .../bearssl-esp8266/src/ec/ec_all_m15.c | 0 .../bearssl-esp8266/src/ec/ec_c25519_i15.c | 0 .../bearssl-esp8266/src/ec/ec_curve25519.c | 0 .../bearssl-esp8266/src/ec/ec_default.c | 0 .../bearssl-esp8266/src/ec/ec_keygen.c | 0 .../bearssl-esp8266/src/ec/ec_p256_m15.c | 0 .../bearssl-esp8266/src/ec/ec_prime_i15.c | 0 .../bearssl-esp8266/src/ec/ec_pubkey.c | 0 .../bearssl-esp8266/src/ec/ec_secp256r1.c | 0 .../bearssl-esp8266/src/ec/ec_secp384r1.c | 0 .../bearssl-esp8266/src/ec/ec_secp521r1.c | 0 .../bearssl-esp8266/src/ec/ecdsa_atr.c | 0 .../src/ec/ecdsa_default_sign_asn1.c | 0 .../src/ec/ecdsa_default_sign_raw.c | 0 .../src/ec/ecdsa_default_vrfy_asn1.c | 0 .../src/ec/ecdsa_default_vrfy_raw.c | 0 .../bearssl-esp8266/src/ec/ecdsa_i15_bits.c | 0 .../src/ec/ecdsa_i15_sign_asn1.c | 0 .../src/ec/ecdsa_i15_sign_raw.c | 0 .../src/ec/ecdsa_i15_vrfy_asn1.c | 0 .../src/ec/ecdsa_i15_vrfy_raw.c | 0 .../bearssl-esp8266/src/ec/ecdsa_rta.c | 0 .../bearssl-esp8266/src/hash/dig_oid.c | 0 .../bearssl-esp8266/src/hash/dig_size.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul32.c | 0 .../bearssl-esp8266/src/hash/ghash_ctmul64.c | 0 .../bearssl-esp8266/src/hash/ghash_pclmul.c | 0 .../lib_ssl}/bearssl-esp8266/src/hash/md5.c | 0 .../bearssl-esp8266/src/hash/md5sha1.c | 0 .../lib_ssl}/bearssl-esp8266/src/hash/mgf1.c | 0 .../bearssl-esp8266/src/hash/multihash.c | 0 .../lib_ssl}/bearssl-esp8266/src/hash/sha1.c | 0 .../bearssl-esp8266/src/hash/sha2big.c | 0 .../bearssl-esp8266/src/hash/sha2small.c | 0 .../bearssl-esp8266/src/int/i15_add.c | 0 .../bearssl-esp8266/src/int/i15_bitlen.c | 0 .../bearssl-esp8266/src/int/i15_decmod.c | 0 .../bearssl-esp8266/src/int/i15_decode.c | 0 .../bearssl-esp8266/src/int/i15_decred.c | 0 .../bearssl-esp8266/src/int/i15_encode.c | 0 .../bearssl-esp8266/src/int/i15_fmont.c | 0 .../bearssl-esp8266/src/int/i15_iszero.c | 0 .../bearssl-esp8266/src/int/i15_moddiv.c | 0 .../bearssl-esp8266/src/int/i15_modpow.c | 0 .../bearssl-esp8266/src/int/i15_modpow2.c | 0 .../bearssl-esp8266/src/int/i15_montmul.c | 0 .../bearssl-esp8266/src/int/i15_mulacc.c | 0 .../bearssl-esp8266/src/int/i15_muladd.c | 0 .../bearssl-esp8266/src/int/i15_ninv15.c | 0 .../bearssl-esp8266/src/int/i15_reduce.c | 0 .../bearssl-esp8266/src/int/i15_rshift.c | 0 .../bearssl-esp8266/src/int/i15_sub.c | 0 .../bearssl-esp8266/src/int/i15_tmont.c | 0 .../lib_ssl}/bearssl-esp8266/src/kdf/hkdf.c | 0 .../lib_ssl}/bearssl-esp8266/src/kdf/shake.c | 0 .../lib_ssl}/bearssl-esp8266/src/mac/hmac.c | 0 .../bearssl-esp8266/src/mac/hmac_ct.c | 0 .../bearssl-esp8266/src/pgmspace_bearssl.h | 0 .../bearssl-esp8266/src/rand/aesctr_drbg.c | 0 .../bearssl-esp8266/src/rand/hmac_drbg.c | 0 .../bearssl-esp8266/src/rand/sysrng.c | 0 .../src/rsa/rsa_default_keygen.c | 0 .../src/rsa/rsa_default_modulus.c | 0 .../src/rsa/rsa_default_oaep_decrypt.c | 0 .../src/rsa/rsa_default_oaep_encrypt.c | 0 .../src/rsa/rsa_default_pkcs1_sign.c | 0 .../src/rsa/rsa_default_pkcs1_vrfy.c | 0 .../src/rsa/rsa_default_priv.c | 0 .../src/rsa/rsa_default_privexp.c | 0 .../src/rsa/rsa_default_pss_sign.c | 0 .../src/rsa/rsa_default_pss_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_default_pub.c | 0 .../src/rsa/rsa_default_pubexp.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_keygen.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_modulus.c | 0 .../src/rsa/rsa_i15_oaep_decrypt.c | 0 .../src/rsa/rsa_i15_oaep_encrypt.c | 0 .../src/rsa/rsa_i15_pkcs1_sign.c | 0 .../src/rsa/rsa_i15_pkcs1_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_priv.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_privexp.c | 0 .../src/rsa/rsa_i15_pss_sign.c | 0 .../src/rsa/rsa_i15_pss_vrfy.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_pub.c | 0 .../bearssl-esp8266/src/rsa/rsa_i15_pubexp.c | 0 .../bearssl-esp8266/src/rsa/rsa_oaep_pad.c | 0 .../bearssl-esp8266/src/rsa/rsa_oaep_unpad.c | 0 .../src/rsa/rsa_pkcs1_sig_pad.c | 0 .../src/rsa/rsa_pkcs1_sig_unpad.c | 0 .../bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c | 0 .../src/rsa/rsa_pss_sig_unpad.c | 0 .../bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c | 0 .../lib_ssl}/bearssl-esp8266/src/settings.c | 0 .../lib_ssl}/bearssl-esp8266/src/ssl/prf.c | 0 .../bearssl-esp8266/src/ssl/prf_md5sha1.c | 0 .../bearssl-esp8266/src/ssl/prf_sha256.c | 0 .../bearssl-esp8266/src/ssl/prf_sha384.c | 0 .../src/ssl/ssl_ccert_single_ec.c | 0 .../src/ssl/ssl_ccert_single_rsa.c | 0 .../bearssl-esp8266/src/ssl/ssl_client.c | 0 .../src/ssl/ssl_client_default_rsapub.c | 0 .../bearssl-esp8266/src/ssl/ssl_client_full.c | 0 .../bearssl-esp8266/src/ssl/ssl_engine.c | 0 .../src/ssl/ssl_engine_default_aescbc.c | 0 .../src/ssl/ssl_engine_default_aesccm.c | 0 .../src/ssl/ssl_engine_default_aesgcm.c | 0 .../src/ssl/ssl_engine_default_chapol.c | 0 .../src/ssl/ssl_engine_default_descbc.c | 0 .../src/ssl/ssl_engine_default_ec.c | 0 .../src/ssl/ssl_engine_default_ecdsa.c | 0 .../src/ssl/ssl_engine_default_rsavrfy.c | 0 .../bearssl-esp8266/src/ssl/ssl_hashes.c | 0 .../bearssl-esp8266/src/ssl/ssl_hs_client.c | 0 .../bearssl-esp8266/src/ssl/ssl_hs_server.c | 0 .../lib_ssl}/bearssl-esp8266/src/ssl/ssl_io.c | 0 .../bearssl-esp8266/src/ssl/ssl_keyexport.c | 0 .../bearssl-esp8266/src/ssl/ssl_lru.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_cbc.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_ccm.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_chapol.c | 0 .../bearssl-esp8266/src/ssl/ssl_rec_gcm.c | 0 .../src/ssl/ssl_scert_single_ec.c | 0 .../src/ssl/ssl_scert_single_rsa.c | 0 .../src/symcipher/aes_big_cbcdec.c | 0 .../src/symcipher/aes_big_cbcenc.c | 0 .../src/symcipher/aes_big_ctr.c | 0 .../src/symcipher/aes_big_ctrcbc.c | 0 .../src/symcipher/aes_big_dec.c | 0 .../src/symcipher/aes_big_enc.c | 0 .../src/symcipher/aes_common.c | 0 .../bearssl-esp8266/src/symcipher/aes_ct.c | 0 .../bearssl-esp8266/src/symcipher/aes_ct64.c | 0 .../src/symcipher/aes_ct64_cbcdec.c | 0 .../src/symcipher/aes_ct64_cbcenc.c | 0 .../src/symcipher/aes_ct64_ctr.c | 0 .../src/symcipher/aes_ct64_ctrcbc.c | 0 .../src/symcipher/aes_ct64_dec.c | 0 .../src/symcipher/aes_ct64_enc.c | 0 .../src/symcipher/aes_ct_cbcdec.c | 0 .../src/symcipher/aes_ct_cbcenc.c | 0 .../src/symcipher/aes_ct_ctr.c | 0 .../src/symcipher/aes_ct_ctrcbc.c | 0 .../src/symcipher/aes_ct_dec.c | 0 .../src/symcipher/aes_ct_enc.c | 0 .../src/symcipher/aes_small_cbcdec.c | 0 .../src/symcipher/aes_small_cbcenc.c | 0 .../src/symcipher/aes_small_ctr.c | 0 .../src/symcipher/aes_small_ctrcbc.c | 0 .../src/symcipher/aes_small_dec.c | 0 .../src/symcipher/aes_small_enc.c | 0 .../src/symcipher/chacha20_ct.c | 0 .../src/symcipher/chacha20_sse2.c | 0 .../bearssl-esp8266/src/symcipher/des_ct.c | 0 .../src/symcipher/des_ct_cbcdec.c | 0 .../src/symcipher/des_ct_cbcenc.c | 0 .../src/symcipher/des_support.c | 0 .../bearssl-esp8266/src/symcipher/des_tab.c | 0 .../src/symcipher/des_tab_cbcdec.c | 0 .../src/symcipher/des_tab_cbcenc.c | 0 .../src/symcipher/poly1305_ctmul.c | 0 .../src/symcipher/poly1305_ctmul32.c | 0 .../src/symcipher/poly1305_ctmulq.c | 0 .../src/symcipher/poly1305_i15.c | 0 .../lib_ssl}/bearssl-esp8266/src/t_bearssl.h | 0 .../bearssl-esp8266/src/t_bearssl_aead.h | 0 .../bearssl-esp8266/src/t_bearssl_block.h | 0 .../bearssl-esp8266/src/t_bearssl_ec.h | 0 .../bearssl-esp8266/src/t_bearssl_hash.h | 0 .../bearssl-esp8266/src/t_bearssl_hmac.h | 0 .../bearssl-esp8266/src/t_bearssl_kdf.h | 0 .../bearssl-esp8266/src/t_bearssl_pem.h | 0 .../bearssl-esp8266/src/t_bearssl_prf.h | 0 .../bearssl-esp8266/src/t_bearssl_rand.h | 0 .../bearssl-esp8266/src/t_bearssl_rsa.h | 0 .../bearssl-esp8266/src/t_bearssl_ssl.h | 0 .../src/t_bearssl_tasmota_config.h | 0 .../bearssl-esp8266/src/t_bearssl_x509.h | 0 .../lib_ssl}/bearssl-esp8266/src/t_config.h | 0 .../lib_ssl}/bearssl-esp8266/src/t_inner.h | 0 .../bearssl-esp8266/src/x509/asn1enc.c | 0 .../src/x509/encode_ec_pk8der.c | 0 .../src/x509/encode_ec_rawder.c | 0 .../src/x509/encode_rsa_pk8der.c | 0 .../src/x509/encode_rsa_rawder.c | 0 .../bearssl-esp8266/src/x509/pkey_decoder.c | 0 .../bearssl-esp8266/src/x509/skey_decoder.c | 0 .../bearssl-esp8266/src/x509/x509_decoder.c | 0 .../bearssl-esp8266/src/x509/x509_knownkey.c | 0 .../bearssl-esp8266/src/x509/x509_minimal.c | 0 .../src/x509/x509_minimal_full.c | 0 .../libesp32}/ESP32-Ethernet/README.md | 0 .../EthernetLAN_IP101/EthernetLAN_IP101.ino | 0 .../ESP32-Ethernet/library.properties | 0 .../libesp32}/ESP32-Ethernet/src/ETH.cpp | 0 .../libesp32}/ESP32-Ethernet/src/ETH.h | 0 .../libesp32}/ESP32-Mail-Client/LICENSE | 0 .../libesp32}/ESP32-Mail-Client/README.md | 0 .../examples/Receive_email/Receive_email.ino | 0 .../examples/Send_email/Send_email.ino | 0 .../examples/Send_email/image.h | 0 .../examples/Set_flag/Set_flag.ino | 0 .../ESP32-Mail-Client/examples/Time/Time.ino | 0 .../libesp32}/ESP32-Mail-Client/keywords.txt | 0 .../ESP32-Mail-Client/library.properties | 0 .../media/images/esp32-mail.jpg | Bin .../media/images/esp32-mail.png | Bin .../src/ESP32MailHTTPClient.cpp | 0 .../src/ESP32MailHTTPClient.h | 0 .../ESP32-Mail-Client/src/ESP32TimeHelper.cpp | 0 .../ESP32-Mail-Client/src/ESP32TimeHelper.h | 0 .../src/ESP32_MailClient.cpp | 0 .../ESP32-Mail-Client/src/ESP32_MailClient.h | 0 .../ESP32-Mail-Client/src/RFC2047.cpp | 0 .../libesp32}/ESP32-Mail-Client/src/RFC2047.h | 0 .../src/WiFiClientSecureESP32.cpp | 0 .../src/WiFiClientSecureESP32.h | 0 .../ESP32-Mail-Client/src/ssl_client32.cpp | 0 .../ESP32-Mail-Client/src/ssl_client32.h | 0 .../ESP32-to-ESP8266-compat/README.adoc | 0 .../ESP32-to-ESP8266-compat/keywords.txt | 0 .../library.properties | 0 .../ESP32-to-ESP8266-compat/src/AddrList.h | 0 .../ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp | 0 .../src/ESP8266HTTPClient.h | 0 .../src/ESP8266WebServer.h | 0 .../ESP32-to-ESP8266-compat/src/ESP8266WiFi.h | 0 .../src/ESP8266httpUpdate.h | 0 .../ESP32-to-ESP8266-compat/src/ESP8266mDNS.h | 0 .../ESP32-to-ESP8266-compat/src/c_types.h | 0 .../src/eboot_command.h | 0 .../src/esp8266toEsp32.cpp | 0 .../src/esp8266toEsp32.h | 0 .../ESP32-to-ESP8266-compat/src/ets_sys.h | 0 .../ESP32-to-ESP8266-compat/src/gpio.h | 0 .../ESP32-to-ESP8266-compat/src/os_type.h | 0 .../ESP32-to-ESP8266-compat/src/osapi.h | 0 .../ESP32-to-ESP8266-compat/src/sntp.h | 0 .../ESP32-to-ESP8266-compat/src/spi_flash.h | 0 .../ESP32-to-ESP8266-compat/src/twi.h | 0 .../src/user_interface.h | 0 {libesp32 => lib/libesp32}/ESP32README.md | 0 .../libesp32}/NimBLE-Arduino/CHANGELOG.md | 0 .../libesp32}/NimBLE-Arduino/LICENSE | 0 .../libesp32}/NimBLE-Arduino/README.md | 0 .../docs/Improvements_and_updates.md | 0 .../NimBLE-Arduino/docs/Migration_guide.md | 0 .../NimBLE-Arduino/docs/New_user_guide.md | 0 .../BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino | 0 .../BLE_Beacon_Scanner/BLE_Beacon_Scanner.md | 0 .../BLE_EddystoneTLM_Beacon.ino | 0 .../BLE_EddystoneTLM_Beacon.md | 0 .../BLE_EddystoneURL_Beacon.ino | 0 .../BLE_EddystoneURL_Beacon.md | 0 .../examples/NimBLE_Client/NimBLE_Client.ino | 0 .../examples/NimBLE_Server/NimBLE_Server.ino | 0 .../BLE_client/BLE_client.ino | 0 .../BLE_iBeacon/BLE_iBeacon.ino | 0 .../BLE_notify/BLE_notify.ino | 0 .../BLE_scan/BLE_scan.ino | 0 .../BLE_server/BLE_server.ino | 0 .../BLE_server_multiconnect.ino | 0 .../BLE_uart/BLE_uart.ino | 0 .../BLE_write/BLE_write.ino | 0 .../NimBLE-Arduino/library.properties | 0 .../NimBLE-Arduino/src/CODING_STANDARDS.md | 0 .../libesp32}/NimBLE-Arduino/src/FreeRTOS.cpp | 0 .../libesp32}/NimBLE-Arduino/src/FreeRTOS.h | 0 .../NimBLE-Arduino/src/HIDKeyboardTypes.h | 0 .../libesp32}/NimBLE-Arduino/src/HIDTypes.h | 0 .../libesp32}/NimBLE-Arduino/src/NOTICE | 0 .../NimBLE-Arduino/src/NimBLE2904.cpp | 0 .../libesp32}/NimBLE-Arduino/src/NimBLE2904.h | 0 .../NimBLE-Arduino/src/NimBLEAddress.cpp | 0 .../NimBLE-Arduino/src/NimBLEAddress.h | 0 .../src/NimBLEAdvertisedDevice.cpp | 0 .../src/NimBLEAdvertisedDevice.h | 0 .../NimBLE-Arduino/src/NimBLEAdvertising.cpp | 0 .../NimBLE-Arduino/src/NimBLEAdvertising.h | 0 .../NimBLE-Arduino/src/NimBLEBeacon.cpp | 0 .../NimBLE-Arduino/src/NimBLEBeacon.h | 0 .../src/NimBLECharacteristic.cpp | 0 .../NimBLE-Arduino/src/NimBLECharacteristic.h | 0 .../NimBLE-Arduino/src/NimBLEClient.cpp | 0 .../NimBLE-Arduino/src/NimBLEClient.h | 0 .../NimBLE-Arduino/src/NimBLEDescriptor.cpp | 0 .../NimBLE-Arduino/src/NimBLEDescriptor.h | 0 .../NimBLE-Arduino/src/NimBLEDevice.cpp | 0 .../NimBLE-Arduino/src/NimBLEDevice.h | 0 .../NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp | 0 .../NimBLE-Arduino/src/NimBLEEddystoneTLM.h | 0 .../NimBLE-Arduino/src/NimBLEEddystoneURL.cpp | 0 .../NimBLE-Arduino/src/NimBLEEddystoneURL.h | 0 .../libesp32}/NimBLE-Arduino/src/NimBLELog.h | 0 .../src/NimBLERemoteCharacteristic.cpp | 0 .../src/NimBLERemoteCharacteristic.h | 0 .../src/NimBLERemoteDescriptor.cpp | 0 .../src/NimBLERemoteDescriptor.h | 0 .../src/NimBLERemoteService.cpp | 0 .../NimBLE-Arduino/src/NimBLERemoteService.h | 0 .../NimBLE-Arduino/src/NimBLEScan.cpp | 0 .../libesp32}/NimBLE-Arduino/src/NimBLEScan.h | 0 .../NimBLE-Arduino/src/NimBLESecurity.cpp | 0 .../NimBLE-Arduino/src/NimBLESecurity.h | 0 .../NimBLE-Arduino/src/NimBLEServer.cpp | 0 .../NimBLE-Arduino/src/NimBLEServer.h | 0 .../NimBLE-Arduino/src/NimBLEService.cpp | 0 .../NimBLE-Arduino/src/NimBLEService.h | 0 .../NimBLE-Arduino/src/NimBLEUUID.cpp | 0 .../libesp32}/NimBLE-Arduino/src/NimBLEUUID.h | 0 .../NimBLE-Arduino/src/NimBLEUtils.cpp | 0 .../NimBLE-Arduino/src/NimBLEUtils.h | 0 .../libesp32}/NimBLE-Arduino/src/README.md | 0 .../NimBLE-Arduino/src/RELEASE_NOTES.md | 0 .../NimBLE-Arduino/src/console/console.h | 0 .../src/esp-hci/src/esp_nimble_hci.c | 0 .../NimBLE-Arduino/src/esp_compiler.h | 0 .../NimBLE-Arduino/src/esp_nimble_cfg.h | 0 .../NimBLE-Arduino/src/esp_nimble_hci.h | 0 .../NimBLE-Arduino/src/esp_nimble_mem.h | 0 .../NimBLE-Arduino/src/ext/tinycrypt/AUTHORS | 0 .../NimBLE-Arduino/src/ext/tinycrypt/LICENSE | 0 .../NimBLE-Arduino/src/ext/tinycrypt/README | 0 .../NimBLE-Arduino/src/ext/tinycrypt/VERSION | 0 .../ext/tinycrypt/documentation/tinycrypt.rst | 0 .../src/ext/tinycrypt/src/aes_decrypt.c | 0 .../src/ext/tinycrypt/src/aes_encrypt.c | 0 .../src/ext/tinycrypt/src/cbc_mode.c | 0 .../src/ext/tinycrypt/src/ccm_mode.c | 0 .../src/ext/tinycrypt/src/cmac_mode.c | 0 .../src/ext/tinycrypt/src/ctr_mode.c | 0 .../src/ext/tinycrypt/src/ctr_prng.c | 0 .../src/ext/tinycrypt/src/ecc.c | 0 .../src/ext/tinycrypt/src/ecc_dh.c | 0 .../src/ext/tinycrypt/src/ecc_dsa.c | 0 .../ext/tinycrypt/src/ecc_platform_specific.c | 0 .../src/ext/tinycrypt/src/hmac.c | 0 .../src/ext/tinycrypt/src/hmac_prng.c | 0 .../src/ext/tinycrypt/src/sha256.c | 0 .../src/ext/tinycrypt/src/utils.c | 0 .../NimBLE-Arduino/src/hal/hal_timer.h | 0 .../NimBLE-Arduino/src/host/ble_att.h | 0 .../NimBLE-Arduino/src/host/ble_eddystone.h | 0 .../NimBLE-Arduino/src/host/ble_gap.h | 0 .../NimBLE-Arduino/src/host/ble_gatt.h | 0 .../NimBLE-Arduino/src/host/ble_hs.h | 0 .../NimBLE-Arduino/src/host/ble_hs_adv.h | 0 .../NimBLE-Arduino/src/host/ble_hs_hci.h | 0 .../NimBLE-Arduino/src/host/ble_hs_id.h | 0 .../NimBLE-Arduino/src/host/ble_hs_log.h | 0 .../NimBLE-Arduino/src/host/ble_hs_mbuf.h | 0 .../NimBLE-Arduino/src/host/ble_hs_pvcy.h | 0 .../NimBLE-Arduino/src/host/ble_hs_stop.h | 0 .../NimBLE-Arduino/src/host/ble_ibeacon.h | 0 .../NimBLE-Arduino/src/host/ble_l2cap.h | 0 .../NimBLE-Arduino/src/host/ble_monitor.h | 0 .../NimBLE-Arduino/src/host/ble_sm.h | 0 .../NimBLE-Arduino/src/host/ble_store.h | 0 .../NimBLE-Arduino/src/host/ble_uuid.h | 0 .../NimBLE-Arduino/src/host/util/util.h | 0 .../libesp32}/NimBLE-Arduino/src/log/log.h | 0 .../libesp32}/NimBLE-Arduino/src/mem/mem.h | 0 .../NimBLE-Arduino/src/mesh/access.h | 0 .../NimBLE-Arduino/src/mesh/cfg_cli.h | 0 .../NimBLE-Arduino/src/mesh/cfg_srv.h | 0 .../libesp32}/NimBLE-Arduino/src/mesh/glue.h | 0 .../NimBLE-Arduino/src/mesh/health_cli.h | 0 .../NimBLE-Arduino/src/mesh/health_srv.h | 0 .../libesp32}/NimBLE-Arduino/src/mesh/main.h | 0 .../libesp32}/NimBLE-Arduino/src/mesh/mesh.h | 0 .../NimBLE-Arduino/src/mesh/model_cli.h | 0 .../NimBLE-Arduino/src/mesh/model_srv.h | 0 .../NimBLE-Arduino/src/mesh/porting.h | 0 .../libesp32}/NimBLE-Arduino/src/mesh/proxy.h | 0 .../libesp32}/NimBLE-Arduino/src/mesh/slist.h | 0 .../NimBLE-Arduino/src/mesh/testing.h | 0 .../NimBLE-Arduino/src/modlog/modlog.h | 0 .../libesp32}/NimBLE-Arduino/src/nimble/ble.h | 0 .../NimBLE-Arduino/src/nimble/ble_hci_trans.h | 0 .../NimBLE-Arduino/src/nimble/hci_common.h | 0 .../src/nimble/host/mesh/src/access.c | 0 .../src/nimble/host/mesh/src/access.h | 0 .../src/nimble/host/mesh/src/adv.c | 0 .../src/nimble/host/mesh/src/adv.h | 0 .../src/nimble/host/mesh/src/atomic.h | 0 .../src/nimble/host/mesh/src/beacon.c | 0 .../src/nimble/host/mesh/src/beacon.h | 0 .../src/nimble/host/mesh/src/ble_att_priv.h | 0 .../src/nimble/host/mesh/src/ble_gatt_priv.h | 0 .../nimble/host/mesh/src/ble_hs_conn_priv.h | 0 .../nimble/host/mesh/src/ble_l2cap_coc_priv.h | 0 .../src/nimble/host/mesh/src/ble_l2cap_priv.h | 0 .../nimble/host/mesh/src/ble_l2cap_sig_priv.h | 0 .../src/nimble/host/mesh/src/cfg_cli.c | 0 .../src/nimble/host/mesh/src/cfg_srv.c | 0 .../src/nimble/host/mesh/src/crypto.c | 0 .../src/nimble/host/mesh/src/crypto.h | 0 .../src/nimble/host/mesh/src/foundation.h | 0 .../src/nimble/host/mesh/src/friend.c | 0 .../src/nimble/host/mesh/src/friend.h | 0 .../src/nimble/host/mesh/src/glue.c | 0 .../src/nimble/host/mesh/src/health_cli.c | 0 .../src/nimble/host/mesh/src/health_srv.c | 0 .../src/nimble/host/mesh/src/light_model.c | 0 .../src/nimble/host/mesh/src/light_model.h | 0 .../src/nimble/host/mesh/src/lpn.c | 0 .../src/nimble/host/mesh/src/lpn.h | 0 .../src/nimble/host/mesh/src/mesh.c | 0 .../src/nimble/host/mesh/src/mesh_priv.h | 0 .../src/nimble/host/mesh/src/model_cli.c | 0 .../src/nimble/host/mesh/src/model_srv.c | 0 .../src/nimble/host/mesh/src/net.c | 0 .../src/nimble/host/mesh/src/net.h | 0 .../src/nimble/host/mesh/src/prov.c | 0 .../src/nimble/host/mesh/src/prov.h | 0 .../src/nimble/host/mesh/src/proxy.c | 0 .../src/nimble/host/mesh/src/proxy.h | 0 .../src/nimble/host/mesh/src/settings.c | 0 .../src/nimble/host/mesh/src/settings.h | 0 .../src/nimble/host/mesh/src/shell.c | 0 .../src/nimble/host/mesh/src/shell.h | 0 .../host/mesh/src/src/ble_att_cmd_priv.h | 0 .../nimble/host/mesh/src/src/ble_att_priv.h | 0 .../nimble/host/mesh/src/src/ble_gap_priv.h | 0 .../nimble/host/mesh/src/src/ble_gatt_priv.h | 0 .../host/mesh/src/src/ble_hs_adv_priv.h | 0 .../host/mesh/src/src/ble_hs_atomic_priv.h | 0 .../host/mesh/src/src/ble_hs_conn_priv.h | 0 .../host/mesh/src/src/ble_hs_dbg_priv.h | 0 .../host/mesh/src/src/ble_hs_flow_priv.h | 0 .../host/mesh/src/src/ble_hs_hci_priv.h | 0 .../nimble/host/mesh/src/src/ble_hs_id_priv.h | 0 .../host/mesh/src/src/ble_hs_mbuf_priv.h | 0 .../mesh/src/src/ble_hs_periodic_sync_priv.h | 0 .../nimble/host/mesh/src/src/ble_hs_priv.h | 0 .../host/mesh/src/src/ble_hs_pvcy_priv.h | 0 .../host/mesh/src/src/ble_hs_resolv_priv.h | 0 .../host/mesh/src/src/ble_hs_startup_priv.h | 0 .../host/mesh/src/src/ble_l2cap_coc_priv.h | 0 .../nimble/host/mesh/src/src/ble_l2cap_priv.h | 0 .../host/mesh/src/src/ble_l2cap_sig_priv.h | 0 .../host/mesh/src/src/ble_monitor_priv.h | 0 .../nimble/host/mesh/src/src/ble_sm_priv.h | 0 .../nimble/host/mesh/src/src/ble_uuid_priv.h | 0 .../src/nimble/host/mesh/src/testing.c | 0 .../src/nimble/host/mesh/src/testing.h | 0 .../src/nimble/host/mesh/src/transport.c | 0 .../src/nimble/host/mesh/src/transport.h | 0 .../host/services/ans/src/ble_svc_ans.c | 0 .../host/services/bas/src/ble_svc_bas.c | 0 .../host/services/gap/src/ble_svc_gap.c | 0 .../host/services/gatt/src/ble_svc_gatt.c | 0 .../host/services/ias/src/ble_svc_ias.c | 0 .../host/services/ipss/src/ble_svc_ipss.c | 0 .../host/services/lls/src/ble_svc_lls.c | 0 .../host/services/tps/src/ble_hs_hci_priv.h | 0 .../host/services/tps/src/ble_svc_tps.c | 0 .../src/nimble/host/src/ble_att.c | 0 .../src/nimble/host/src/ble_att_clt.c | 0 .../src/nimble/host/src/ble_att_cmd.c | 0 .../src/nimble/host/src/ble_att_cmd_priv.h | 0 .../src/nimble/host/src/ble_att_priv.h | 0 .../src/nimble/host/src/ble_att_svr.c | 0 .../src/nimble/host/src/ble_eddystone.c | 0 .../src/nimble/host/src/ble_gap.c | 0 .../src/nimble/host/src/ble_gap_priv.h | 0 .../src/nimble/host/src/ble_gatt_priv.h | 0 .../src/nimble/host/src/ble_gattc.c | 0 .../src/nimble/host/src/ble_gatts.c | 0 .../src/nimble/host/src/ble_gatts_lcl.c | 0 .../src/nimble/host/src/ble_hs.c | 0 .../src/nimble/host/src/ble_hs_adv.c | 0 .../src/nimble/host/src/ble_hs_adv_priv.h | 0 .../src/nimble/host/src/ble_hs_atomic.c | 0 .../src/nimble/host/src/ble_hs_atomic_priv.h | 0 .../src/nimble/host/src/ble_hs_cfg.c | 0 .../src/nimble/host/src/ble_hs_conn.c | 0 .../src/nimble/host/src/ble_hs_conn_priv.h | 0 .../src/nimble/host/src/ble_hs_dbg.c | 0 .../src/nimble/host/src/ble_hs_dbg_priv.h | 0 .../src/nimble/host/src/ble_hs_flow.c | 0 .../src/nimble/host/src/ble_hs_flow_priv.h | 0 .../src/nimble/host/src/ble_hs_hci.c | 0 .../src/nimble/host/src/ble_hs_hci_cmd.c | 0 .../src/nimble/host/src/ble_hs_hci_evt.c | 0 .../src/nimble/host/src/ble_hs_hci_priv.h | 0 .../src/nimble/host/src/ble_hs_hci_util.c | 0 .../src/nimble/host/src/ble_hs_id.c | 0 .../src/nimble/host/src/ble_hs_id_priv.h | 0 .../src/nimble/host/src/ble_hs_log.c | 0 .../src/nimble/host/src/ble_hs_mbuf.c | 0 .../src/nimble/host/src/ble_hs_mbuf_priv.h | 0 .../src/nimble/host/src/ble_hs_misc.c | 0 .../src/nimble/host/src/ble_hs_mqueue.c | 0 .../nimble/host/src/ble_hs_periodic_sync.c | 0 .../host/src/ble_hs_periodic_sync_priv.h | 0 .../src/nimble/host/src/ble_hs_priv.h | 0 .../src/nimble/host/src/ble_hs_pvcy.c | 0 .../src/nimble/host/src/ble_hs_pvcy_priv.h | 0 .../src/nimble/host/src/ble_hs_resolv.c | 0 .../src/nimble/host/src/ble_hs_resolv_priv.h | 0 .../src/nimble/host/src/ble_hs_shutdown.c | 0 .../src/nimble/host/src/ble_hs_startup.c | 0 .../src/nimble/host/src/ble_hs_startup_priv.h | 0 .../src/nimble/host/src/ble_hs_stop.c | 0 .../src/nimble/host/src/ble_ibeacon.c | 0 .../src/nimble/host/src/ble_l2cap.c | 0 .../src/nimble/host/src/ble_l2cap_coc.c | 0 .../src/nimble/host/src/ble_l2cap_coc_priv.h | 0 .../src/nimble/host/src/ble_l2cap_priv.h | 0 .../src/nimble/host/src/ble_l2cap_sig.c | 0 .../src/nimble/host/src/ble_l2cap_sig_cmd.c | 0 .../src/nimble/host/src/ble_l2cap_sig_priv.h | 0 .../src/nimble/host/src/ble_monitor.c | 0 .../src/nimble/host/src/ble_monitor_priv.h | 0 .../src/nimble/host/src/ble_sm.c | 0 .../src/nimble/host/src/ble_sm_alg.c | 0 .../src/nimble/host/src/ble_sm_cmd.c | 0 .../src/nimble/host/src/ble_sm_lgcy.c | 0 .../src/nimble/host/src/ble_sm_priv.h | 0 .../src/nimble/host/src/ble_sm_sc.c | 0 .../src/nimble/host/src/ble_store.c | 0 .../src/nimble/host/src/ble_store_util.c | 0 .../src/nimble/host/src/ble_uuid.c | 0 .../src/nimble/host/src/ble_uuid_priv.h | 0 .../host/store/config/src/ble_store_config.c | 0 .../store/config/src/ble_store_config_priv.h | 0 .../host/store/config/src/ble_store_nvs.c | 0 .../nimble/host/store/ram/src/ble_store_ram.c | 0 .../src/nimble/host/util/src/addr.c | 0 .../NimBLE-Arduino/src/nimble/nimble_npl.h | 0 .../NimBLE-Arduino/src/nimble/nimble_npl_os.h | 0 .../NimBLE-Arduino/src/nimble/nimble_opt.h | 0 .../src/nimble/nimble_opt_auto.h | 0 .../NimBLE-Arduino/src/nimble/nimble_port.h | 0 .../src/nimble/nimble_port_freertos.h | 0 .../NimBLE-Arduino/src/nimble/npl_freertos.h | 0 .../libesp32}/NimBLE-Arduino/src/nimconfig.h | 0 .../libesp32}/NimBLE-Arduino/src/os/endian.h | 0 .../libesp32}/NimBLE-Arduino/src/os/os.h | 0 .../NimBLE-Arduino/src/os/os_cputime.h | 0 .../NimBLE-Arduino/src/os/os_error.h | 0 .../libesp32}/NimBLE-Arduino/src/os/os_mbuf.h | 0 .../NimBLE-Arduino/src/os/os_mempool.h | 0 .../NimBLE-Arduino/src/os/os_trace_api.h | 0 .../libesp32}/NimBLE-Arduino/src/os/queue.h | 0 .../src/port/src/esp_nimble_mem.c | 0 .../nimble/include/nimble/nimble_port.h | 0 .../src/porting/nimble/src/endian.c | 0 .../src/porting/nimble/src/hal_timer.c | 0 .../src/porting/nimble/src/mem.c | 0 .../src/porting/nimble/src/nimble_port.c | 0 .../src/porting/nimble/src/os_cputime.c | 0 .../src/porting/nimble/src/os_cputime_pwr2.c | 0 .../src/porting/nimble/src/os_mbuf.c | 0 .../src/porting/nimble/src/os_mempool.c | 0 .../src/porting/nimble/src/os_msys_init.c | 0 .../npl/freertos/src/nimble_port_freertos.c | 0 .../npl/freertos/src/npl_os_freertos.c | 0 .../src/services/ans/ble_svc_ans.h | 0 .../src/services/bas/ble_svc_bas.h | 0 .../src/services/gap/ble_svc_gap.h | 0 .../src/services/gatt/ble_svc_gatt.h | 0 .../src/services/ias/ble_svc_ias.h | 0 .../src/services/ipss/ble_svc_ipss.h | 0 .../src/services/lls/ble_svc_lls.h | 0 .../src/services/tps/ble_svc_tps.h | 0 .../NimBLE-Arduino/src/src/ble_hs_hci_priv.h | 0 .../NimBLE-Arduino/src/src/ble_sm_priv.h | 0 .../NimBLE-Arduino/src/stats/stats.h | 0 .../src/store/config/ble_store_config.h | 0 .../src/store/ram/ble_store_ram.h | 0 .../NimBLE-Arduino/src/syscfg/syscfg.h | 0 .../NimBLE-Arduino/src/sysinit/sysinit.h | 0 .../NimBLE-Arduino/src/tinycrypt/AUTHORS | 0 .../NimBLE-Arduino/src/tinycrypt/LICENSE | 0 .../NimBLE-Arduino/src/tinycrypt/README | 0 .../NimBLE-Arduino/src/tinycrypt/VERSION | 0 .../NimBLE-Arduino/src/tinycrypt/aes.h | 0 .../NimBLE-Arduino/src/tinycrypt/cbc_mode.h | 0 .../NimBLE-Arduino/src/tinycrypt/ccm_mode.h | 0 .../NimBLE-Arduino/src/tinycrypt/cmac_mode.h | 0 .../NimBLE-Arduino/src/tinycrypt/constants.h | 0 .../NimBLE-Arduino/src/tinycrypt/ctr_mode.h | 0 .../NimBLE-Arduino/src/tinycrypt/ctr_prng.h | 0 .../src/tinycrypt/documentation/tinycrypt.rst | 0 .../NimBLE-Arduino/src/tinycrypt/ecc.h | 0 .../NimBLE-Arduino/src/tinycrypt/ecc_dh.h | 0 .../NimBLE-Arduino/src/tinycrypt/ecc_dsa.h | 0 .../src/tinycrypt/ecc_platform_specific.h | 0 .../NimBLE-Arduino/src/tinycrypt/hmac.h | 0 .../NimBLE-Arduino/src/tinycrypt/hmac_prng.h | 0 .../NimBLE-Arduino/src/tinycrypt/sha256.h | 0 .../NimBLE-Arduino/src/tinycrypt/utils.h | 0 .../libesp32}/TTGO_TWatch_Library/LICENSE | 0 .../libesp32}/TTGO_TWatch_Library/README.MD | 0 .../TTGO_TWatch_Library/library.json | 0 .../TTGO_TWatch_Library/library.properties | 0 .../TTGO_TWatch_Library/src/axp20x.cpp | 0 .../TTGO_TWatch_Library/src/axp20x.h | 0 .../libesp32}/TTGO_TWatch_Library/src/bma.cpp | 0 .../libesp32}/TTGO_TWatch_Library/src/bma.h | 0 .../libesp32}/TTGO_TWatch_Library/src/bma4.c | 0 .../libesp32}/TTGO_TWatch_Library/src/bma4.h | 0 .../TTGO_TWatch_Library/src/bma423.c | 0 .../TTGO_TWatch_Library/src/bma423.h | 0 .../TTGO_TWatch_Library/src/bma4_defs.h | 0 .../TTGO_TWatch_Library/src/i2c_bus.cpp | 0 .../TTGO_TWatch_Library/src/i2c_bus.h | 0 platformio.ini | 2 +- platformio_override_sample.ini | 14 +- platformio_tasmota32.ini | 16 +- platformio_tasmota_env.ini | 10 +- platformio_tasmota_env.ini.new | 144 - platformio_tasmota_env32.ini | 14 +- tasmota/tasmota.ino.cpp | 115375 +++++++++++++++ 3438 files changed, 115403 insertions(+), 172 deletions(-) rename lib/{ => default}/AT24C256_512/Eeprom24C128_256.cpp (100%) rename lib/{ => default}/AT24C256_512/Eeprom24C128_256.h (100%) rename lib/{ => default}/AT24C256_512/Eeprom24C512.cpp (100%) rename lib/{ => default}/AT24C256_512/Eeprom24C512.h (100%) rename lib/{ => default}/AT24C256_512/library.properties (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/.gitignore (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/.travis.yml (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/CHANGES.txt (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/LICENSE.txt (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/README.md (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/keywords.txt (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/library.json (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/library.properties (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/.gitignore (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/Makefile (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/README.md (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py (100%) rename lib/{ => default}/PubSubClient-EspEasy-2.7.12/tests/testsuite.py (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/README.md (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/examples/swsertest/swsertest.ino (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/keywords.txt (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/library.json (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/library.properties (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp (100%) rename lib/{ => default}/TasmotaSerial-3.1.0/src/TasmotaSerial.h (100%) rename lib/{ => default}/UdpListener/library.properties (100%) rename lib/{ => default}/UdpListener/src/UdpListener.h (100%) rename lib/{ => default}/Unishox-1.0-shadinger/generator/generator.c (100%) rename lib/{ => default}/Unishox-1.0-shadinger/generator/remapping.xlsx (100%) rename lib/{ => default}/Unishox-1.0-shadinger/library.properties (100%) rename lib/{ => default}/Unishox-1.0-shadinger/python/unishox.py (100%) rename lib/{ => default}/Unishox-1.0-shadinger/src/unishox.cpp (100%) rename lib/{ => default}/Unishox-1.0-shadinger/src/unishox.h (100%) rename lib/{ => default}/headers/DPT.h (100%) rename lib/{ => default}/headers/esp-knx-ip.h (100%) rename lib/{ => default}/headers/readme.txt (100%) rename lib/{ => default}/jsmn-shadinger-1.0/README.md (100%) rename lib/{ => default}/jsmn-shadinger-1.0/library.properties (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/JsonGenerator.cpp (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/JsonGenerator.h (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/JsonParser.cpp (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/JsonParser.h (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/jsmn.cpp (100%) rename lib/{ => default}/jsmn-shadinger-1.0/src/jsmn.h (100%) rename lib/{ => default}/jsmn-shadinger-1.0/test/test-json.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/.github/workflows/pr-or-master-push.yml (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/LICENSE (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/README.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/MixerSample/MixerSample.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/MixerSample/viola.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/WebRadio/WebRadio.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/WebRadio/web.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/examples/WebRadio/web.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/keywords.txt (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/library.json (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/library.properties (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSource.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceBuffer.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceBuffer.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceFATFS.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceFS.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceFS.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceHTTPStream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceICYStream.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceICYStream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceID3.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceID3.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceLittleFS.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourcePROGMEM.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSD.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSD.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSPIFFS.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSTDIO.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileSourceSTDIO.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileStream.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioFileStream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGenerator.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorAAC.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorAAC.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorFLAC.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorFLAC.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMIDI.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMIDI.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMOD.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMOD.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMP3.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMP3.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMP3a.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorMP3a.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorOpus.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorOpus.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorRTTTL.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorRTTTL.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorTalkie.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorTalkie.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorWAV.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioGeneratorWAV.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioLogger.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioLogger.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutput.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputBuffer.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputBuffer.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputFilterDecimate.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputFilterDecimate.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputI2S.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputI2S.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputI2SNoDAC.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputMixer.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputMixer.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputNull.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSPDIF.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSPDIF.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSPIFFSWAV.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSTDIO.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSTDIO.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSerialWAV.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioOutputSerialWAV.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/AudioStatus.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/driver/SinglePinI2SDriver.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/AUTHORS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/COPYING.FDL (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/COPYING.GPL (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/COPYING.LGPL (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/COPYING.Xiph (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/assert.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/callback.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/export.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/format.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/metadata.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/ordinals.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/FLAC/stream_decoder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/README (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/README.ESP8266 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/bitmath.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/bitreader.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/config.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/cpu.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/crc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/fixed.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/float.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/format.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/lpc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/md5.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/memory.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/bitmath.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/bitreader.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/cpu.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/crc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/fixed.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/float.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/format.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/lpc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/macros.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/md5.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/memory.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/metadata.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/private/window.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/protected/all.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/protected/stream_decoder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/protected/stream_encoder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/alloc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/compat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/endswap.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/getopt.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/macros.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/private.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/safe_str.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/share/utf8.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/stream_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libflac/window.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/aaccommon.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/aacdec.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/aacdec.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/aactabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/assembly.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/bitstream.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/bitstream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/buffers.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/coder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/dct4.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/decelmnt.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/dequant.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/fft.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/filefmt.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/huffman.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/hufftabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/imdct.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/noiseless.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/pns.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/readme.txt (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbr.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbr.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrfft.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrfreq.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhfadj.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhfgen.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrhuff.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrimdct.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrmath.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrqmf.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrside.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/sbrtabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/statname.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/stproc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/tns.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-aac/trigtabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/LICENSE.txt (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/RCSL.txt (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/RPSL.txt (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/assembly.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/bitstream.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/buffers.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/coder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/dct32.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/dequant.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/dqchan.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/huffman.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/hufftabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/imdct.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3common.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3dec.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3dec.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/mp3tabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/player.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/polyphase.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/scalfact.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/statname.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/stproc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/subband.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libhelix-mp3/trigtabs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/CHANGES (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/COPYING (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/COPYRIGHT (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/CREDITS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/D.dat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/LICENSE (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/README (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/README.ESP8266 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/TODO (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/VERSION (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/bit.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/bit.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/config.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/decoder.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/fixed.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/fixed.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/frame.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/frame.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/global.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/huffman.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/huffman.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/imdct_s.dat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/layer3.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/layer3.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/mad.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/mad.h.sed (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/qc_table.dat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/rq_table.dat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/sf_table.dat.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/stream.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/stream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/synth.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/synth.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/timer.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/timer.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/version.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libmad/version.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/AUTHORS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/CHANGES (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/COPYING (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/README.esp8266.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/README.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/bitwise.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/config.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/crctable.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/framing.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/ogg.pc (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/ogg/config_types.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/ogg/ogg.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libogg/ogg/os_types.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/AUTHORS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/COPYING (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/ChangeLog (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/INSTALL (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/NEWS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/README (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/analysis.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/arch.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/bands.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/bands.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt_encoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt_lpc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/celt_lpc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/cpu_support.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/cwrs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/cwrs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/ecintrin.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entcode.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entcode.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entdec.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entdec.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entenc.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/entenc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/fixed_debug.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/fixed_generic.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/float_cast.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/kiss_fft.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/kiss_fft.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/laplace.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/laplace.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/mathops.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/mathops.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/mdct.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/mdct.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/mfrngcod.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/modes.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/modes.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/os_support.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/pitch.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/pitch.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/quant_bands.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/quant_bands.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/rate.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/rate.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/stack_alloc.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/static_modes_fixed.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/static_modes_float.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/vq.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/celt/vq.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/config.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/mapping_matrix.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/mapping_matrix.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/mlp.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus.pc (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_custom.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_defines.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_encoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_multistream.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_multistream.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_multistream_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_multistream_encoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_private.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_projection.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_projection_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_projection_encoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/opus_types.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/repacketizer.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/A2NLSF.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/API.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/CNG.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/Inlines.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/LPC_fit.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/MacroCount.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/MacroDebug.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF2A.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_VQ.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_decode.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_encode.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NLSF_unpack.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NSQ.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NSQ.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/PLC.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/PLC.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/SigProc_FIX.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/VAD.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/biquad_alt.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/bwexpander.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/bwexpander_32.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/check_control_input.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/code_signs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/control.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/control_SNR.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/control_codec.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/debug.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/debug.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/dec_API.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_core.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_frame.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_indices.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_parameters.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_pitch.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decode_pulses.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/decoder_set_fs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/define.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/enc_API.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/encode_indices.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/encode_pulses.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/errors.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/gain_quant.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/init_decoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/init_encoder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/interpolate.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/lin2log.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/log2lin.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/macros.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/main.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/pitch_est_defines.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/pitch_est_tables.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/process_NLSFs.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_down2.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_down2_3.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_rom.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_rom.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/resampler_structs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/shell_coder.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/sigm_Q15.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/sort.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/structs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/table_LSF_cos.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_LTP.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_gain.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_other.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/tuning_parameters.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/silk/typedef.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libopus/tansig_table.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libtinysoundfont/LICENSE (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libtinysoundfont/README.ESP8266 (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libtinysoundfont/README.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/libtinysoundfont/tsf.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/AUTHORS (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/COPYING (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/README.esp8266.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/README.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/config.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/info.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/internal.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/internal.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/opusfile.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/opusfile.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/opusfile.pc (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/opusfile/stream.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/src/spiram-fast.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/common.sh (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/Arduino.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/Makefile (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/Serial.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/aac.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/midi.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/mp3.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/opus.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/pgmspace.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/test_8u_16.wav (100%) rename {lib_audio => lib/lib_audio}/ESP8266Audio/tests/host/wav.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/README.md (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/examples/Speak/Speak.ino (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/library.json (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/library.properties (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/ESP8266SAM.cpp (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/ESP8266SAM.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/ReciterTabs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/RenderTabs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/SamData.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/SamTabs.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/reciter.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/reciter.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/render.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/render.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/sam.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/sam.h (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/samdebug.c (100%) rename {lib_audio => lib/lib_audio}/ESP8266SAM/src/samdebug.h (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/README.md (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/keywords.txt (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/library.json (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/library.properties (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/src/c2.cpp (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/src/c2.h (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/src/ihx.cpp (100%) rename {lib_basic => lib/lib_basic}/C2Programmer-1.0.0/src/ihx.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.github/Contributors.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.github/issue_template.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.gitignore (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.gitmodules (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.style.yapf (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/.travis.yml (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/CPPLINT.cfg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/Doxyfile (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/LICENSE.txt (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/README.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/README_fr.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/ReleaseNotes.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/SupportedProtocols.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/README.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/README_fr.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/_config.yml (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/docs/doxygen_index.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/keywords.txt (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/library.json (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/library.properties (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/platformio.ini (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/pylintrc (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/CPPLINT.cfg (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRac.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRac.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRrecv.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRrecv.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRsend.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRsend.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRtext.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRtext.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRtimer.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRtimer.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRutils.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/IRutils.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/i18n.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Airwell.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Amcor.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Argo.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Argo.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Carrier.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Coolix.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Corona.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Corona.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Daikin.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Delonghi.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Denon.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Dish.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Electra.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Electra.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Epson.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_GICable.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Goodweather.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Gree.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Gree.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Haier.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Haier.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Hitachi.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Inax.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_JVC.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_LG.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_LG.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lego.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_MWM.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Magiquest.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Metz.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Midea.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Midea.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_NEC.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_NEC.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Neoclima.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Panasonic.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Samsung.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sanyo.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sharp.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Sony.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Tcl.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Technibel.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Teco.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Teco.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Toshiba.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Transcold.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Trotec.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Vestel.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Voltas.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/README.md (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/de-CH.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/de-DE.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/defaults.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-AU.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-IE.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-UK.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/en-US.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/es-ES.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/fr-FR.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/it-IT.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/src/locale/zh-CN.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRac_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRrecv_test.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRsend_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRsend_test.h (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/IRutils_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/Makefile (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/Makefile (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/gc_decode.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/mkkeywords (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py (100%) rename {lib_basic => lib/lib_basic}/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.gitattributes (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.github/FUNDING.yml (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/.gitignore (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/COPYING (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/ReadMe.md (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/circular.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/cubic.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/different.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/exponential.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/gamma.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/pronounced.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/quadratic.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/quintic.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/keywords.txt (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/library.json (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/library.properties (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelBus.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HsbColor.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HslColor.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HslColor.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColor.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Layouts.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoDib.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEase.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoGamma.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSettings.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTiles.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/NeoTopology.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbColor.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/RgbwColor.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h (100%) rename {lib_basic => lib/lib_basic}/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/OneWire.h (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/README.md (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/keywords.txt (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/library.json (100%) rename {lib_basic => lib/lib_basic}/OneWire-Stickbreaker-20190506-1.1/library.properties (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/README.md (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/keywords.txt (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/library.json (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/library.properties (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp (100%) rename {lib_basic => lib/lib_basic}/TasmotaModbus-1.2.0/src/TasmotaModbus.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/README.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit_LED_Backpack-1.1.6/license.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/LICENSE.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SH1106-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/README.md (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/SSD1351.h (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/Tiger.c (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/Tiger.rgb (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/keywords.txt (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/Adafruit_SSD1351-gemu-1.0/spi_register.h (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/README.txt (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/keywords.txt (100%) rename {lib_display => lib/lib_display}/Arduino_ST7789-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/README.md (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/keywords.txt (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/JaretBurkett_ILI9488-gemu-1.0/spi_register.h (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/README.md (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/keywords.txt (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/library.json (100%) rename {lib_display => lib/lib_display}/LiquidCrystal_I2C-1.1.3/library.properties (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/RA8876.cpp (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/RA8876.h (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/README.md (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/keywords.txt (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/library.properties (100%) rename {lib_display => lib/lib_display}/Xlatb_RA8876-gemu-1.0/spi_register.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/Makefile (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/README.md (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/library.properties (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp (100%) rename {lib_display => lib/lib_display}/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h (100%) rename {lib_div => lib/lib_div}/A4988_Stepper/README.adoc (100%) rename {lib_div => lib/lib_div}/A4988_Stepper/keywords.txt (100%) rename {lib_div => lib/lib_div}/A4988_Stepper/library.properties (100%) rename {lib_div => lib/lib_div}/A4988_Stepper/src/A4988_Stepper.cpp (100%) rename {lib_div => lib/lib_div}/A4988_Stepper/src/A4988_Stepper.h (100%) rename {lib_div => lib/lib_div}/ArduinoNTPd/NTPPacket.cpp (100%) rename {lib_div => lib/lib_div}/ArduinoNTPd/NTPPacket.h (100%) rename {lib_div => lib/lib_div}/ArduinoNTPd/NTPServer.cpp (100%) rename {lib_div => lib/lib_div}/ArduinoNTPd/NTPServer.h (100%) rename {lib_div => lib/lib_div}/ArduinoNTPd/library.properties (100%) rename {lib_div => lib/lib_div}/LibTeleinfo/README.md (100%) rename {lib_div => lib/lib_div}/LibTeleinfo/library.json (100%) rename {lib_div => lib/lib_div}/LibTeleinfo/library.properties (100%) rename {lib_div => lib/lib_div}/LibTeleinfo/src/LibTeleinfo.cpp (100%) rename {lib_div => lib/lib_div}/LibTeleinfo/src/LibTeleinfo.h (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/README.md (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/examples/TimerExample/TimerExample.pde (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/keywords.txt (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/library.properties (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/src/NewPing.cpp (100%) rename {lib_div => lib/lib_div}/NewPing-1.9.1/src/NewPing.h (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/LICENSE (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/README.md (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/keywords.txt (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/library.properties (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/src/OpenTherm.cpp (100%) rename {lib_div => lib/lib_div}/OpenTherm-0.9.0/src/OpenTherm.h (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/LICENSE (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/README.md (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/examples/static-config/static-config.ino (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/keywords.txt (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/library.json (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/library.properties.off (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/DPT.h (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp (100%) rename {lib_div => lib/lib_div}/esp-knx-ip-0.5.2/src/esp-knx-ip.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/.travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_BusIO_Register.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_BusIO_Register.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_I2CDevice.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_I2CDevice.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_I2CRegister.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_SPIDevice.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/Adafruit_SPIDevice.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/LICENSE (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/examples/spi_registers/spi_registers.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_BusIO/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/.travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/LICENSE (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_CCS811-1.0.0.14/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/README.txt (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MAX31865-1.1.0-custom/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/.gitignore (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/assets/board.jpg (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/code-of-conduct.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_MCP9808_Tasmota/license.txt (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/license.txt (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_SGP30-1.2.0/travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_TSL2591_Library/Adafruit_TSL2591.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_TSL2591_Library/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/.gitignore (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/.travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/Adafruit_VEML7700.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/Adafruit_VEML7700.h (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Adafruit_VEML7700/license.txt (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/LICENSE (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/README.md (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/bme680.c (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/bme680.h (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/bme680_defs.h (100%) rename {lib_i2c => lib/lib_i2c}/BME680_driver-bme680_v3.5.9/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/.gitignore (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/LICENSE (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/README.md (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/src/FT5206.cpp (100%) rename {lib_i2c => lib/lib_i2c}/FT5206_Library/src/FT5206.h (100%) rename {lib_i2c => lib/lib_i2c}/FrogmoreScd30/FrogmoreScd30.cpp (100%) rename {lib_i2c => lib/lib_i2c}/FrogmoreScd30/FrogmoreScd30.h (100%) rename {lib_i2c => lib/lib_i2c}/FrogmoreScd30/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/LICENSE.md (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/README.md (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/example/example.ino (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/src/hpma115S0.cpp (100%) rename {lib_i2c => lib/lib_i2c}/HPMA115S0/src/hpma115S0.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-Core/.library.json (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-Core/I2Cdev.cpp (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-Core/I2Cdev.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-Core/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-Core/library.json (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/MPU6050.cpp (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/MPU6050.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/helper_3dmath.h (100%) rename {lib_i2c => lib/lib_i2c}/I2Cdevlib-MPU6050/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/.gitignore (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/.hgignore (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/.travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/COPYING (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/COPYING.LESSER (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/README (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/platformio.ini (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/examples/platformio.sh (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/lib/readme.txt (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/library.json (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/platformio.ini (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561.h (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/README.md (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/examples/i2c_background/i2c_background.ino (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/examples/i2c_command/i2c_command.ino (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/examples/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/src/LOLIN_HP303B.cpp (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/src/LOLIN_HP303B.h (100%) rename {lib_i2c => lib/lib_i2c}/LOLIN_HP303B/src/util/hp303b_consts.h (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/LICENSE.txt (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/LinkedList.h (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/README.md (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/examples/ClassList/ClassList.pde (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/library.json (100%) rename {lib_i2c => lib/lib_i2c}/LinkedList-1.2.3/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/License.txt (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/README.md (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/library.json (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp (100%) rename {lib_i2c => lib/lib_i2c}/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h (100%) rename {lib_i2c => lib/lib_i2c}/mlx90640-library/MLX90640_API.cpp (100%) rename {lib_i2c => lib/lib_i2c}/mlx90640-library/MLX90640_API.h (100%) rename {lib_i2c => lib/lib_i2c}/mlx90640-library/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/.travis.yml (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/LICENSE.txt (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/README.md (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.cpp (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/VL53L0X.h (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/examples/Single/Single.ino (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/vl53l0x-arduino-1.02/library.properties (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/LICENSE.txt (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/README.md (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.cpp (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/VL53L1X.h (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/keywords.txt (100%) rename {lib_i2c => lib/lib_i2c}/vl53l1x-arduino-1.01/library.properties (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/README.md (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/keywords.txt (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/library.properties (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/src/KeeloqLib.cpp (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/src/KeeloqLib.h (100%) rename {lib_rf => lib/lib_rf}/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/.gitignore (100%) rename {lib_rf => lib/lib_rf}/RF24/CONTRIBUTING.md (100%) rename {lib_rf => lib/lib_rf}/RF24/Doxyfile (100%) rename {lib_rf => lib/lib_rf}/RF24/LICENSE (100%) rename {lib_rf => lib/lib_rf}/RF24/Makefile (100%) rename {lib_rf => lib/lib_rf}/RF24/README.md (100%) rename {lib_rf => lib/lib_rf}/RF24/RF24.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/RF24.h (100%) rename {lib_rf => lib/lib_rf}/RF24/RF24_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/configure (100%) rename {lib_rf => lib/lib_rf}/RF24/doxygen-custom.css (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/GettingStarted/GettingStarted.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Transfer/Transfer.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/TransferTimeouts/TransferTimeouts.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/led_remote/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/led_remote/led_remote.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/nordic_fob/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/nordic_fob/nordic_fob.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/pingpair_maple/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/pingpair_maple/main.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/Usage/readme.md (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_ack/pingpair_ack.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_dyn/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_dyn/pingpair_dyn.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_irq/pingpair_irq.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_multi_dyn/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/scanner/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/scanner/scanner.ino (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/starping/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples/starping/starping.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/Makefile.examples (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/extra/Makefile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/extra/rpi-hub.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/extra/scanner.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/gettingstarted.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/gettingstarted_call_response.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/interrupts/Makefile (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/interrupts/transfer_interrupt.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/pingpair_dyn.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/pingpair_dyn.py (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/readme.md (100%) rename {lib_rf => lib/lib_rf}/RF24/examples_linux/transfer.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/keywords.txt (100%) rename {lib_rf => lib/lib_rf}/RF24/library.json (100%) rename {lib_rf => lib/lib_rf}/RF24/library.properties (100%) rename {lib_rf => lib/lib_rf}/RF24/nRF24L01.h (100%) rename {lib_rf => lib/lib_rf}/RF24/printf.h (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/crossunixccompiler.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24/crossunixccompiler.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24/pyRF24.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24/readme.md (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24/setup.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Mesh/example_master.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Mesh/setup.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/pyRF24Network/setup.py (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/readme.md (100%) rename {lib_rf => lib/lib_rf}/RF24/pyRF24/setup.py (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/README (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/native/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/native/pingpair_irq.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/native/printf.h (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/pingpair_blocking.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/printf.h (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/runtest.py (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/runtests.sh (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_blocking/test.ex (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/Jamfile (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/pingpair_test.pde (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/printf.h (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/runtest.py (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/runtests.sh (100%) rename {lib_rf => lib/lib_rf}/RF24/tests/pingpair_test/test.ex (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATTiny/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATTiny/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/README.md (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/compatibility.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/compatibility.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/gpio.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/gpio.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/gpio_helper.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/gpio_helper.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/spi.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/ATXMegaD3/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Due/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/LittleWire/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/LittleWire/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/compatibility.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/compatibility.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/gpio.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/gpio.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/spi.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/MRAA/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/bcm2835.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/bcm2835.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/interrupt.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/interrupt.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/spi.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/RPi/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/compatibility.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/compatibility.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/gpio.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/gpio.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/interrupt.c (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/interrupt.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/spi.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/SPIDEV/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Teensy/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Template/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Template/compatibility.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Template/gpio.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Template/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/Template/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/wiringPi/RF24_arch_config.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/wiringPi/includes.h (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/wiringPi/spi.cpp (100%) rename {lib_rf => lib/lib_rf}/RF24/utility/wiringPi/spi.h (100%) rename {lib_rf => lib/lib_rf}/RF24/wikidoc.xslt (100%) rename {lib_rf => lib/lib_rf}/cc1101/README.md (100%) rename {lib_rf => lib/lib_rf}/cc1101/cc1101.cpp (100%) rename {lib_rf => lib/lib_rf}/cc1101/cc1101.h (100%) rename {lib_rf => lib/lib_rf}/cc1101/cc1101.h.txt (100%) rename {lib_rf => lib/lib_rf}/cc1101/ccpacket.h (100%) rename {lib_rf => lib/lib_rf}/cc1101/library.properties (100%) rename {lib_rf => lib/lib_rf}/rc-switch/.gitignore (100%) rename {lib_rf => lib/lib_rf}/rc-switch/README.md (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/ReceiveDemo_Advanced/output.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/SendDemo/SendDemo.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/TypeD_REV/TypeD_REV.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/examples/Webserver/Webserver.ino (100%) rename {lib_rf => lib/lib_rf}/rc-switch/keywords.txt (100%) rename {lib_rf => lib/lib_rf}/rc-switch/library.json (100%) rename {lib_rf => lib/lib_rf}/rc-switch/library.properties (100%) rename {lib_rf => lib/lib_rf}/rc-switch/platformio.ini (100%) rename {lib_rf => lib/lib_rf}/rc-switch/src/RCSwitch.cpp (100%) rename {lib_rf => lib/lib_rf}/rc-switch/src/RCSwitch.h (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/LICENSE (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/Makefile (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/README.md (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/catch.cpp (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/catch.hpp (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/library.properties (100%) rename {lib_ssl => lib/lib_ssl}/base64-1.1.1/src/base64.hpp (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/bearssl_esp8266-customized.txt (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/conf/esp8266.mk (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/library.properties (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/aead/ccm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/aead/eax.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/aead/gcm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/ccopy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec16be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec16le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec32be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec32le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec64be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/dec64le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc16be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc16le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc32be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc32le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc64be.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/enc64le.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/pemdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/codec/pemenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_all_m15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_c25519_i15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_curve25519.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_default.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_keygen.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_p256_m15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_prime_i15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_pubkey.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_secp256r1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_secp384r1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ec_secp521r1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_atr.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_bits.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ec/ecdsa_rta.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/dig_oid.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/dig_size.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul32.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/ghash_ctmul64.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/ghash_pclmul.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/md5.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/md5sha1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/mgf1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/multihash.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/sha1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/sha2big.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/hash/sha2small.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_add.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_bitlen.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_decmod.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_decode.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_decred.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_encode.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_fmont.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_iszero.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_moddiv.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_modpow.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_modpow2.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_montmul.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_mulacc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_muladd.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_ninv15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_reduce.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_rshift.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_sub.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/int/i15_tmont.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/kdf/hkdf.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/kdf/shake.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/mac/hmac.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/mac/hmac_ct.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/pgmspace_bearssl.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rand/aesctr_drbg.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rand/hmac_drbg.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rand/sysrng.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_keygen.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_modulus.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_priv.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_privexp.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pub.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_default_pubexp.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_keygen.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_modulus.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_priv.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_privexp.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pub.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_oaep_pad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/settings.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/prf.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/prf_md5sha1.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/prf_sha256.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/prf_sha384.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_client.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_client_full.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_hashes.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_hs_client.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_hs_server.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_io.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_keyexport.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_lru.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_cbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_ccm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_chapol.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_rec_gcm.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_ctr.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_dec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_big_enc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_common.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_dec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct64_enc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_ctr.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_dec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_ct_enc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_ctr.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_dec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/aes_small_enc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/chacha20_ct.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/chacha20_sse2.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_ct.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_support.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_tab.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmul.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/symcipher/poly1305_i15.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_aead.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_block.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_ec.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_hash.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_hmac.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_kdf.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_pem.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_prf.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_rand.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_rsa.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_ssl.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_tasmota_config.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_bearssl_x509.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_config.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/t_inner.h (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/asn1enc.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/encode_ec_pk8der.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/encode_ec_rawder.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/encode_rsa_pk8der.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/encode_rsa_rawder.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/pkey_decoder.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/skey_decoder.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/x509_decoder.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/x509_knownkey.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/x509_minimal.c (100%) rename {lib_ssl => lib/lib_ssl}/bearssl-esp8266/src/x509/x509_minimal_full.c (100%) rename {libesp32 => lib/libesp32}/ESP32-Ethernet/README.md (100%) rename {libesp32 => lib/libesp32}/ESP32-Ethernet/examples/EthernetLAN_IP101/EthernetLAN_IP101.ino (100%) rename {libesp32 => lib/libesp32}/ESP32-Ethernet/library.properties (100%) rename {libesp32 => lib/libesp32}/ESP32-Ethernet/src/ETH.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Ethernet/src/ETH.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/LICENSE (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/README.md (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/examples/Send_email/Send_email.ino (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/examples/Send_email/image.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/examples/Time/Time.ino (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/keywords.txt (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/library.properties (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/media/images/esp32-mail.jpg (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/media/images/esp32-mail.png (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32MailHTTPClient.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32TimeHelper.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32TimeHelper.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32_MailClient.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ESP32_MailClient.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/RFC2047.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/RFC2047.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/WiFiClientSecureESP32.h (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ssl_client32.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-Mail-Client/src/ssl_client32.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/README.adoc (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/keywords.txt (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/library.properties (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/AddrList.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP8266HTTPClient.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP8266WebServer.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP8266httpUpdate.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ESP8266mDNS.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/c_types.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/eboot_command.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/ets_sys.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/gpio.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/os_type.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/osapi.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/sntp.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/spi_flash.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/twi.h (100%) rename {libesp32 => lib/libesp32}/ESP32-to-ESP8266-compat/src/user_interface.h (100%) rename {libesp32 => lib/libesp32}/ESP32README.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/CHANGELOG.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/LICENSE (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/README.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/docs/Improvements_and_updates.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/docs/Migration_guide.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/docs/New_user_guide.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/library.properties (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/CODING_STANDARDS.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/FreeRTOS.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/FreeRTOS.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/HIDKeyboardTypes.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/HIDTypes.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NOTICE (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLE2904.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLE2904.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAddress.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAddress.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAdvertising.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEAdvertising.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEBeacon.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEBeacon.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLECharacteristic.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLECharacteristic.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEClient.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEClient.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEDescriptor.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEDescriptor.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEDevice.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEDevice.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEEddystoneTLM.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEEddystoneURL.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLELog.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteDescriptor.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteService.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLERemoteService.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEScan.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEScan.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLESecurity.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLESecurity.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEServer.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEServer.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEService.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEService.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEUUID.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEUUID.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEUtils.cpp (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/NimBLEUtils.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/README.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/RELEASE_NOTES.md (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/console/console.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/esp_compiler.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/esp_nimble_cfg.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/esp_nimble_hci.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/esp_nimble_mem.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/LICENSE (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/README (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/VERSION (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/hal/hal_timer.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_att.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_eddystone.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_gap.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_gatt.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_adv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_hci.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_id.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_log.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_mbuf.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_pvcy.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_hs_stop.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_ibeacon.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_l2cap.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_monitor.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_sm.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_store.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/ble_uuid.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/host/util/util.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/log/log.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mem/mem.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/access.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/cfg_cli.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/cfg_srv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/glue.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/health_cli.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/health_srv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/main.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/mesh.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/model_cli.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/model_srv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/porting.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/proxy.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/slist.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/mesh/testing.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/modlog/modlog.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/ble.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/ble_hci_trans.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/hci_common.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/access.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/access.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/net.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/net.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gap.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_store.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/host/util/src/addr.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_npl.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_npl_os.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_opt.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_opt_auto.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_port.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/nimble_port_freertos.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimble/npl_freertos.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/nimconfig.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/endian.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os_cputime.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os_error.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os_mbuf.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os_mempool.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/os_trace_api.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/os/queue.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/port/src/esp_nimble_mem.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/endian.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/mem.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/ans/ble_svc_ans.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/bas/ble_svc_bas.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/gap/ble_svc_gap.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/ias/ble_svc_ias.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/lls/ble_svc_lls.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/services/tps/ble_svc_tps.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/src/ble_hs_hci_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/src/ble_sm_priv.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/stats/stats.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/store/config/ble_store_config.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/store/ram/ble_store_ram.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/syscfg/syscfg.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/sysinit/sysinit.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/AUTHORS (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/LICENSE (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/README (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/VERSION (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/aes.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/cbc_mode.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ccm_mode.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/cmac_mode.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/constants.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ctr_mode.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ctr_prng.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ecc.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ecc_dh.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/hmac.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/hmac_prng.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/sha256.h (100%) rename {libesp32 => lib/libesp32}/NimBLE-Arduino/src/tinycrypt/utils.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/LICENSE (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/README.MD (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/library.json (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/library.properties (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/axp20x.cpp (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/axp20x.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma.cpp (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma4.c (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma4.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma423.c (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma423.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/bma4_defs.h (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/i2c_bus.cpp (100%) rename {libesp32 => lib/libesp32}/TTGO_TWatch_Library/src/i2c_bus.h (100%) delete mode 100644 platformio_tasmota_env.ini.new create mode 100644 tasmota/tasmota.ino.cpp diff --git a/lib/AT24C256_512/Eeprom24C128_256.cpp b/lib/default/AT24C256_512/Eeprom24C128_256.cpp similarity index 100% rename from lib/AT24C256_512/Eeprom24C128_256.cpp rename to lib/default/AT24C256_512/Eeprom24C128_256.cpp diff --git a/lib/AT24C256_512/Eeprom24C128_256.h b/lib/default/AT24C256_512/Eeprom24C128_256.h similarity index 100% rename from lib/AT24C256_512/Eeprom24C128_256.h rename to lib/default/AT24C256_512/Eeprom24C128_256.h diff --git a/lib/AT24C256_512/Eeprom24C512.cpp b/lib/default/AT24C256_512/Eeprom24C512.cpp similarity index 100% rename from lib/AT24C256_512/Eeprom24C512.cpp rename to lib/default/AT24C256_512/Eeprom24C512.cpp diff --git a/lib/AT24C256_512/Eeprom24C512.h b/lib/default/AT24C256_512/Eeprom24C512.h similarity index 100% rename from lib/AT24C256_512/Eeprom24C512.h rename to lib/default/AT24C256_512/Eeprom24C512.h diff --git a/lib/AT24C256_512/library.properties b/lib/default/AT24C256_512/library.properties similarity index 100% rename from lib/AT24C256_512/library.properties rename to lib/default/AT24C256_512/library.properties diff --git a/lib/PubSubClient-EspEasy-2.7.12/.gitignore b/lib/default/PubSubClient-EspEasy-2.7.12/.gitignore similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/.gitignore rename to lib/default/PubSubClient-EspEasy-2.7.12/.gitignore diff --git a/lib/PubSubClient-EspEasy-2.7.12/.travis.yml b/lib/default/PubSubClient-EspEasy-2.7.12/.travis.yml similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/.travis.yml rename to lib/default/PubSubClient-EspEasy-2.7.12/.travis.yml diff --git a/lib/PubSubClient-EspEasy-2.7.12/CHANGES.txt b/lib/default/PubSubClient-EspEasy-2.7.12/CHANGES.txt similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/CHANGES.txt rename to lib/default/PubSubClient-EspEasy-2.7.12/CHANGES.txt diff --git a/lib/PubSubClient-EspEasy-2.7.12/LICENSE.txt b/lib/default/PubSubClient-EspEasy-2.7.12/LICENSE.txt similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/LICENSE.txt rename to lib/default/PubSubClient-EspEasy-2.7.12/LICENSE.txt diff --git a/lib/PubSubClient-EspEasy-2.7.12/README.md b/lib/default/PubSubClient-EspEasy-2.7.12/README.md similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/README.md rename to lib/default/PubSubClient-EspEasy-2.7.12/README.md diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino b/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino rename to lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/PubSubClient-EspEasy-2.7.12/keywords.txt b/lib/default/PubSubClient-EspEasy-2.7.12/keywords.txt similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/keywords.txt rename to lib/default/PubSubClient-EspEasy-2.7.12/keywords.txt diff --git a/lib/PubSubClient-EspEasy-2.7.12/library.json b/lib/default/PubSubClient-EspEasy-2.7.12/library.json similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/library.json rename to lib/default/PubSubClient-EspEasy-2.7.12/library.json diff --git a/lib/PubSubClient-EspEasy-2.7.12/library.properties b/lib/default/PubSubClient-EspEasy-2.7.12/library.properties similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/library.properties rename to lib/default/PubSubClient-EspEasy-2.7.12/library.properties diff --git a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h b/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h rename to lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/.gitignore b/lib/default/PubSubClient-EspEasy-2.7.12/tests/.gitignore similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/.gitignore rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/.gitignore diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/Makefile b/lib/default/PubSubClient-EspEasy-2.7.12/tests/Makefile similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/Makefile rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/Makefile diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/README.md b/lib/default/PubSubClient-EspEasy-2.7.12/tests/README.md similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/README.md rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/README.md diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp b/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py b/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py b/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py b/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py b/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py diff --git a/lib/PubSubClient-EspEasy-2.7.12/tests/testsuite.py b/lib/default/PubSubClient-EspEasy-2.7.12/tests/testsuite.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.7.12/tests/testsuite.py rename to lib/default/PubSubClient-EspEasy-2.7.12/tests/testsuite.py diff --git a/lib/TasmotaSerial-3.1.0/README.md b/lib/default/TasmotaSerial-3.1.0/README.md similarity index 100% rename from lib/TasmotaSerial-3.1.0/README.md rename to lib/default/TasmotaSerial-3.1.0/README.md diff --git a/lib/TasmotaSerial-3.1.0/examples/swsertest/swsertest.ino b/lib/default/TasmotaSerial-3.1.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-3.1.0/examples/swsertest/swsertest.ino rename to lib/default/TasmotaSerial-3.1.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-3.1.0/keywords.txt b/lib/default/TasmotaSerial-3.1.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-3.1.0/keywords.txt rename to lib/default/TasmotaSerial-3.1.0/keywords.txt diff --git a/lib/TasmotaSerial-3.1.0/library.json b/lib/default/TasmotaSerial-3.1.0/library.json similarity index 100% rename from lib/TasmotaSerial-3.1.0/library.json rename to lib/default/TasmotaSerial-3.1.0/library.json diff --git a/lib/TasmotaSerial-3.1.0/library.properties b/lib/default/TasmotaSerial-3.1.0/library.properties similarity index 100% rename from lib/TasmotaSerial-3.1.0/library.properties rename to lib/default/TasmotaSerial-3.1.0/library.properties diff --git a/lib/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp similarity index 100% rename from lib/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp rename to lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp diff --git a/lib/TasmotaSerial-3.1.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-3.1.0/src/TasmotaSerial.h rename to lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h diff --git a/lib/UdpListener/library.properties b/lib/default/UdpListener/library.properties similarity index 100% rename from lib/UdpListener/library.properties rename to lib/default/UdpListener/library.properties diff --git a/lib/UdpListener/src/UdpListener.h b/lib/default/UdpListener/src/UdpListener.h similarity index 100% rename from lib/UdpListener/src/UdpListener.h rename to lib/default/UdpListener/src/UdpListener.h diff --git a/lib/Unishox-1.0-shadinger/generator/generator.c b/lib/default/Unishox-1.0-shadinger/generator/generator.c similarity index 100% rename from lib/Unishox-1.0-shadinger/generator/generator.c rename to lib/default/Unishox-1.0-shadinger/generator/generator.c diff --git a/lib/Unishox-1.0-shadinger/generator/remapping.xlsx b/lib/default/Unishox-1.0-shadinger/generator/remapping.xlsx similarity index 100% rename from lib/Unishox-1.0-shadinger/generator/remapping.xlsx rename to lib/default/Unishox-1.0-shadinger/generator/remapping.xlsx diff --git a/lib/Unishox-1.0-shadinger/library.properties b/lib/default/Unishox-1.0-shadinger/library.properties similarity index 100% rename from lib/Unishox-1.0-shadinger/library.properties rename to lib/default/Unishox-1.0-shadinger/library.properties diff --git a/lib/Unishox-1.0-shadinger/python/unishox.py b/lib/default/Unishox-1.0-shadinger/python/unishox.py similarity index 100% rename from lib/Unishox-1.0-shadinger/python/unishox.py rename to lib/default/Unishox-1.0-shadinger/python/unishox.py diff --git a/lib/Unishox-1.0-shadinger/src/unishox.cpp b/lib/default/Unishox-1.0-shadinger/src/unishox.cpp similarity index 100% rename from lib/Unishox-1.0-shadinger/src/unishox.cpp rename to lib/default/Unishox-1.0-shadinger/src/unishox.cpp diff --git a/lib/Unishox-1.0-shadinger/src/unishox.h b/lib/default/Unishox-1.0-shadinger/src/unishox.h similarity index 100% rename from lib/Unishox-1.0-shadinger/src/unishox.h rename to lib/default/Unishox-1.0-shadinger/src/unishox.h diff --git a/lib/headers/DPT.h b/lib/default/headers/DPT.h similarity index 100% rename from lib/headers/DPT.h rename to lib/default/headers/DPT.h diff --git a/lib/headers/esp-knx-ip.h b/lib/default/headers/esp-knx-ip.h similarity index 100% rename from lib/headers/esp-knx-ip.h rename to lib/default/headers/esp-knx-ip.h diff --git a/lib/headers/readme.txt b/lib/default/headers/readme.txt similarity index 100% rename from lib/headers/readme.txt rename to lib/default/headers/readme.txt diff --git a/lib/jsmn-shadinger-1.0/README.md b/lib/default/jsmn-shadinger-1.0/README.md similarity index 100% rename from lib/jsmn-shadinger-1.0/README.md rename to lib/default/jsmn-shadinger-1.0/README.md diff --git a/lib/jsmn-shadinger-1.0/library.properties b/lib/default/jsmn-shadinger-1.0/library.properties similarity index 100% rename from lib/jsmn-shadinger-1.0/library.properties rename to lib/default/jsmn-shadinger-1.0/library.properties diff --git a/lib/jsmn-shadinger-1.0/src/JsonGenerator.cpp b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp similarity index 100% rename from lib/jsmn-shadinger-1.0/src/JsonGenerator.cpp rename to lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp diff --git a/lib/jsmn-shadinger-1.0/src/JsonGenerator.h b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h similarity index 100% rename from lib/jsmn-shadinger-1.0/src/JsonGenerator.h rename to lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h diff --git a/lib/jsmn-shadinger-1.0/src/JsonParser.cpp b/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp similarity index 100% rename from lib/jsmn-shadinger-1.0/src/JsonParser.cpp rename to lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp diff --git a/lib/jsmn-shadinger-1.0/src/JsonParser.h b/lib/default/jsmn-shadinger-1.0/src/JsonParser.h similarity index 100% rename from lib/jsmn-shadinger-1.0/src/JsonParser.h rename to lib/default/jsmn-shadinger-1.0/src/JsonParser.h diff --git a/lib/jsmn-shadinger-1.0/src/jsmn.cpp b/lib/default/jsmn-shadinger-1.0/src/jsmn.cpp similarity index 100% rename from lib/jsmn-shadinger-1.0/src/jsmn.cpp rename to lib/default/jsmn-shadinger-1.0/src/jsmn.cpp diff --git a/lib/jsmn-shadinger-1.0/src/jsmn.h b/lib/default/jsmn-shadinger-1.0/src/jsmn.h similarity index 100% rename from lib/jsmn-shadinger-1.0/src/jsmn.h rename to lib/default/jsmn-shadinger-1.0/src/jsmn.h diff --git a/lib/jsmn-shadinger-1.0/test/test-json.cpp b/lib/default/jsmn-shadinger-1.0/test/test-json.cpp similarity index 100% rename from lib/jsmn-shadinger-1.0/test/test-json.cpp rename to lib/default/jsmn-shadinger-1.0/test/test-json.cpp diff --git a/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml b/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml similarity index 100% rename from lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml rename to lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml diff --git a/lib_audio/ESP8266Audio/LICENSE b/lib/lib_audio/ESP8266Audio/LICENSE similarity index 100% rename from lib_audio/ESP8266Audio/LICENSE rename to lib/lib_audio/ESP8266Audio/LICENSE diff --git a/lib_audio/ESP8266Audio/README.md b/lib/lib_audio/ESP8266Audio/README.md similarity index 100% rename from lib_audio/ESP8266Audio/README.md rename to lib/lib_audio/ESP8266Audio/README.md diff --git a/lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino b/lib/lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino rename to lib/lib_audio/ESP8266Audio/examples/MixerSample/MixerSample.ino diff --git a/lib_audio/ESP8266Audio/examples/MixerSample/viola.h b/lib/lib_audio/ESP8266Audio/examples/MixerSample/viola.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/MixerSample/viola.h rename to lib/lib_audio/ESP8266Audio/examples/MixerSample/viola.h diff --git a/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino b/lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/PlayAACFromPROGMEM.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac b/lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac rename to lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/homer.aac diff --git a/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h b/lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h rename to lib/lib_audio/ESP8266Audio/examples/PlayAACFromPROGMEM/sampleaac.h diff --git a/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino b/lib/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/PlayFLACFromPROGMEMToDAC.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h b/lib/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h rename to lib/lib_audio/ESP8266Audio/examples/PlayFLACFromPROGMEMToDAC/sample.h diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/PlayMIDIFromLittleFS.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/1mgm.sf2 diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromLittleFS/data/furelise.mid diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/1mgm.sf2 diff --git a/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid rename to lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/data/furelise.mid diff --git a/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/PlayMODFromPROGMEMToDAC.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h b/lib/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h rename to lib/lib_audio/ESP8266Audio/examples/PlayMODFromPROGMEMToDAC/enigma.h diff --git a/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/PlayMP3FromSPIFFS.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 b/lib/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 rename to lib/lib_audio/ESP8266Audio/examples/PlayMP3FromSPIFFS/data/pno-cs.mp3 diff --git a/lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayMP3ToSPDIF/PlayMP3ToSPDIF.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/PlayOpusFromSPIFFS.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus b/lib/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus rename to lib/lib_audio/ESP8266Audio/examples/PlayOpusFromSPIFFS/data/gs-16b-2c-44100hz.opus diff --git a/lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino b/lib/lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayRTTTLToI2SDAC/PlayRTTTLToI2SDAC.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino rename to lib/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/PlayWAVFromPROGMEM.ino diff --git a/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h rename to lib/lib_audio/ESP8266Audio/examples/PlayWAVFromPROGMEM/viola.h diff --git a/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino rename to lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP/StreamMP3FromHTTP.ino diff --git a/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png similarity index 100% rename from lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png rename to lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/Schema_Spiram.png diff --git a/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino rename to lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino diff --git a/lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino b/lib/lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino rename to lib/lib_audio/ESP8266Audio/examples/TalkingClockI2S/TalkingClockI2S.ino diff --git a/lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino b/lib/lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino similarity index 100% rename from lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino rename to lib/lib_audio/ESP8266Audio/examples/WebRadio/WebRadio.ino diff --git a/lib_audio/ESP8266Audio/examples/WebRadio/web.cpp b/lib/lib_audio/ESP8266Audio/examples/WebRadio/web.cpp similarity index 100% rename from lib_audio/ESP8266Audio/examples/WebRadio/web.cpp rename to lib/lib_audio/ESP8266Audio/examples/WebRadio/web.cpp diff --git a/lib_audio/ESP8266Audio/examples/WebRadio/web.h b/lib/lib_audio/ESP8266Audio/examples/WebRadio/web.h similarity index 100% rename from lib_audio/ESP8266Audio/examples/WebRadio/web.h rename to lib/lib_audio/ESP8266Audio/examples/WebRadio/web.h diff --git a/lib_audio/ESP8266Audio/keywords.txt b/lib/lib_audio/ESP8266Audio/keywords.txt similarity index 100% rename from lib_audio/ESP8266Audio/keywords.txt rename to lib/lib_audio/ESP8266Audio/keywords.txt diff --git a/lib_audio/ESP8266Audio/library.json b/lib/lib_audio/ESP8266Audio/library.json similarity index 100% rename from lib_audio/ESP8266Audio/library.json rename to lib/lib_audio/ESP8266Audio/library.json diff --git a/lib_audio/ESP8266Audio/library.properties b/lib/lib_audio/ESP8266Audio/library.properties similarity index 100% rename from lib_audio/ESP8266Audio/library.properties rename to lib/lib_audio/ESP8266Audio/library.properties diff --git a/lib_audio/ESP8266Audio/src/AudioFileSource.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSource.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSource.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSource.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceBuffer.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceFATFS.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceFS.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFS.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceFS.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceFS.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceHTTPStream.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceID3.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceID3.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceID3.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceID3.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceID3.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourcePROGMEM.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSD.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSD.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSD.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSD.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSD.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIFFS.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileSourceSTDIO.h diff --git a/lib_audio/ESP8266Audio/src/AudioFileStream.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileStream.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileStream.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioFileStream.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioFileStream.h b/lib/lib_audio/ESP8266Audio/src/AudioFileStream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioFileStream.h rename to lib/lib_audio/ESP8266Audio/src/AudioFileStream.h diff --git a/lib_audio/ESP8266Audio/src/AudioGenerator.h b/lib/lib_audio/ESP8266Audio/src/AudioGenerator.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGenerator.h rename to lib/lib_audio/ESP8266Audio/src/AudioGenerator.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorAAC.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorFLAC.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorMP3a.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorOpus.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorRTTTL.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorTalkie.h diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h rename to lib/lib_audio/ESP8266Audio/src/AudioGeneratorWAV.h diff --git a/lib_audio/ESP8266Audio/src/AudioLogger.cpp b/lib/lib_audio/ESP8266Audio/src/AudioLogger.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioLogger.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioLogger.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioLogger.h b/lib/lib_audio/ESP8266Audio/src/AudioLogger.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioLogger.h rename to lib/lib_audio/ESP8266Audio/src/AudioLogger.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutput.h b/lib/lib_audio/ESP8266Audio/src/AudioOutput.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutput.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutput.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputBuffer.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputBuffer.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputBuffer.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputBuffer.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputBuffer.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputFilterDecimate.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputI2S.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputI2S.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputMixer.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputMixer.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputMixer.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputMixer.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputMixer.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputNull.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputNull.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputNull.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputNull.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSPIFFSWAV.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.h diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.cpp diff --git a/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h rename to lib/lib_audio/ESP8266Audio/src/AudioOutputSerialWAV.h diff --git a/lib_audio/ESP8266Audio/src/AudioStatus.h b/lib/lib_audio/ESP8266Audio/src/AudioStatus.h similarity index 100% rename from lib_audio/ESP8266Audio/src/AudioStatus.h rename to lib/lib_audio/ESP8266Audio/src/AudioStatus.h diff --git a/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp similarity index 100% rename from lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp rename to lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp diff --git a/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h similarity index 100% rename from lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h rename to lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.h diff --git a/lib_audio/ESP8266Audio/src/libflac/AUTHORS b/lib/lib_audio/ESP8266Audio/src/libflac/AUTHORS similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/AUTHORS rename to lib/lib_audio/ESP8266Audio/src/libflac/AUTHORS diff --git a/lib_audio/ESP8266Audio/src/libflac/COPYING.FDL b/lib/lib_audio/ESP8266Audio/src/libflac/COPYING.FDL similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/COPYING.FDL rename to lib/lib_audio/ESP8266Audio/src/libflac/COPYING.FDL diff --git a/lib_audio/ESP8266Audio/src/libflac/COPYING.GPL b/lib/lib_audio/ESP8266Audio/src/libflac/COPYING.GPL similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/COPYING.GPL rename to lib/lib_audio/ESP8266Audio/src/libflac/COPYING.GPL diff --git a/lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL b/lib/lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL rename to lib/lib_audio/ESP8266Audio/src/libflac/COPYING.LGPL diff --git a/lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph b/lib/lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph rename to lib/lib_audio/ESP8266Audio/src/libflac/COPYING.Xiph diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/assert.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/callback.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/export.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/export.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/export.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/export.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/format.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/format.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/format.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/format.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/metadata.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/ordinals.h diff --git a/lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h b/lib/lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h rename to lib/lib_audio/ESP8266Audio/src/libflac/FLAC/stream_decoder.h diff --git a/lib_audio/ESP8266Audio/src/libflac/README b/lib/lib_audio/ESP8266Audio/src/libflac/README similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/README rename to lib/lib_audio/ESP8266Audio/src/libflac/README diff --git a/lib_audio/ESP8266Audio/src/libflac/README.ESP8266 b/lib/lib_audio/ESP8266Audio/src/libflac/README.ESP8266 similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/README.ESP8266 rename to lib/lib_audio/ESP8266Audio/src/libflac/README.ESP8266 diff --git a/lib_audio/ESP8266Audio/src/libflac/bitmath.c b/lib/lib_audio/ESP8266Audio/src/libflac/bitmath.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/bitmath.c rename to lib/lib_audio/ESP8266Audio/src/libflac/bitmath.c diff --git a/lib_audio/ESP8266Audio/src/libflac/bitreader.c b/lib/lib_audio/ESP8266Audio/src/libflac/bitreader.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/bitreader.c rename to lib/lib_audio/ESP8266Audio/src/libflac/bitreader.c diff --git a/lib_audio/ESP8266Audio/src/libflac/config.h b/lib/lib_audio/ESP8266Audio/src/libflac/config.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/config.h rename to lib/lib_audio/ESP8266Audio/src/libflac/config.h diff --git a/lib_audio/ESP8266Audio/src/libflac/cpu.c b/lib/lib_audio/ESP8266Audio/src/libflac/cpu.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/cpu.c rename to lib/lib_audio/ESP8266Audio/src/libflac/cpu.c diff --git a/lib_audio/ESP8266Audio/src/libflac/crc.c b/lib/lib_audio/ESP8266Audio/src/libflac/crc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/crc.c rename to lib/lib_audio/ESP8266Audio/src/libflac/crc.c diff --git a/lib_audio/ESP8266Audio/src/libflac/fixed.c b/lib/lib_audio/ESP8266Audio/src/libflac/fixed.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/fixed.c rename to lib/lib_audio/ESP8266Audio/src/libflac/fixed.c diff --git a/lib_audio/ESP8266Audio/src/libflac/float.c b/lib/lib_audio/ESP8266Audio/src/libflac/float.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/float.c rename to lib/lib_audio/ESP8266Audio/src/libflac/float.c diff --git a/lib_audio/ESP8266Audio/src/libflac/format.c b/lib/lib_audio/ESP8266Audio/src/libflac/format.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/format.c rename to lib/lib_audio/ESP8266Audio/src/libflac/format.c diff --git a/lib_audio/ESP8266Audio/src/libflac/lpc.c b/lib/lib_audio/ESP8266Audio/src/libflac/lpc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/lpc.c rename to lib/lib_audio/ESP8266Audio/src/libflac/lpc.c diff --git a/lib_audio/ESP8266Audio/src/libflac/md5.c b/lib/lib_audio/ESP8266Audio/src/libflac/md5.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/md5.c rename to lib/lib_audio/ESP8266Audio/src/libflac/md5.c diff --git a/lib_audio/ESP8266Audio/src/libflac/memory.c b/lib/lib_audio/ESP8266Audio/src/libflac/memory.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/memory.c rename to lib/lib_audio/ESP8266Audio/src/libflac/memory.c diff --git a/lib_audio/ESP8266Audio/src/libflac/private/bitmath.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/bitmath.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/bitmath.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/bitmath.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/bitreader.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/bitreader.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/bitreader.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/bitreader.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/cpu.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/cpu.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/cpu.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/cpu.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/crc.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/crc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/crc.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/crc.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/fixed.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/fixed.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/fixed.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/fixed.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/float.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/float.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/float.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/float.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/format.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/format.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/format.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/format.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/lpc.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/lpc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/lpc.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/lpc.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/macros.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/macros.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/macros.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/macros.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/md5.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/md5.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/md5.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/md5.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/memory.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/memory.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/memory.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/memory.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/metadata.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/metadata.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/metadata.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/metadata.h diff --git a/lib_audio/ESP8266Audio/src/libflac/private/window.h b/lib/lib_audio/ESP8266Audio/src/libflac/private/window.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/private/window.h rename to lib/lib_audio/ESP8266Audio/src/libflac/private/window.h diff --git a/lib_audio/ESP8266Audio/src/libflac/protected/all.h b/lib/lib_audio/ESP8266Audio/src/libflac/protected/all.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/protected/all.h rename to lib/lib_audio/ESP8266Audio/src/libflac/protected/all.h diff --git a/lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h b/lib/lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h rename to lib/lib_audio/ESP8266Audio/src/libflac/protected/stream_decoder.h diff --git a/lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h b/lib/lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h rename to lib/lib_audio/ESP8266Audio/src/libflac/protected/stream_encoder.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/alloc.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/alloc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/alloc.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/alloc.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/compat.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/compat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/compat.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/compat.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/endswap.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/endswap.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/endswap.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/endswap.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/getopt.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/getopt.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/getopt.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/getopt.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/macros.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/macros.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/macros.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/macros.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/private.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/private.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/private.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/private.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/safe_str.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/safe_str.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/safe_str.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/safe_str.h diff --git a/lib_audio/ESP8266Audio/src/libflac/share/utf8.h b/lib/lib_audio/ESP8266Audio/src/libflac/share/utf8.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/share/utf8.h rename to lib/lib_audio/ESP8266Audio/src/libflac/share/utf8.h diff --git a/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c b/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/stream_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libflac/window.c b/lib/lib_audio/ESP8266Audio/src/libflac/window.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libflac/window.c rename to lib/lib_audio/ESP8266Audio/src/libflac/window.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/aaccommon.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/aacdec.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/aactabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/bitstream.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/buffers.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/coder.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/coder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/coder.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/coder.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/dct4.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/decelmnt.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/dequant.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/fft.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/fft.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/fft.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/fft.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/filefmt.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/huffman.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/hufftabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/imdct.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/noiseless.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/pns.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/pns.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/pns.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/pns.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/readme.txt diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbr.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfft.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrfreq.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfadj.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhfgen.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrhuff.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrimdct.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrmath.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrqmf.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrside.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/sbrtabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/statname.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/statname.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/statname.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/statname.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/stproc.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/tns.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/tns.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/tns.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/tns.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-aac/trigtabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/LICENSE.txt diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RCSL.txt diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/bitstream.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/buffers.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/coder.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dct32.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dequant.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/dqchan.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/huffman.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/hufftabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/imdct.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3common.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3dec.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mp3tabs.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/mpadecobjfixpt.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/player.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/player.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/player.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/player.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/polyphase.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/statname.h diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/stproc.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/subband.c diff --git a/lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c rename to lib/lib_audio/ESP8266Audio/src/libhelix-mp3/trigtabs.c diff --git a/lib_audio/ESP8266Audio/src/libmad/CHANGES b/lib/lib_audio/ESP8266Audio/src/libmad/CHANGES similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/CHANGES rename to lib/lib_audio/ESP8266Audio/src/libmad/CHANGES diff --git a/lib_audio/ESP8266Audio/src/libmad/COPYING b/lib/lib_audio/ESP8266Audio/src/libmad/COPYING similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/COPYING rename to lib/lib_audio/ESP8266Audio/src/libmad/COPYING diff --git a/lib_audio/ESP8266Audio/src/libmad/COPYRIGHT b/lib/lib_audio/ESP8266Audio/src/libmad/COPYRIGHT similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/COPYRIGHT rename to lib/lib_audio/ESP8266Audio/src/libmad/COPYRIGHT diff --git a/lib_audio/ESP8266Audio/src/libmad/CREDITS b/lib/lib_audio/ESP8266Audio/src/libmad/CREDITS similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/CREDITS rename to lib/lib_audio/ESP8266Audio/src/libmad/CREDITS diff --git a/lib_audio/ESP8266Audio/src/libmad/D.dat.h b/lib/lib_audio/ESP8266Audio/src/libmad/D.dat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/D.dat.h rename to lib/lib_audio/ESP8266Audio/src/libmad/D.dat.h diff --git a/lib_audio/ESP8266Audio/src/libmad/LICENSE b/lib/lib_audio/ESP8266Audio/src/libmad/LICENSE similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/LICENSE rename to lib/lib_audio/ESP8266Audio/src/libmad/LICENSE diff --git a/lib_audio/ESP8266Audio/src/libmad/README b/lib/lib_audio/ESP8266Audio/src/libmad/README similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/README rename to lib/lib_audio/ESP8266Audio/src/libmad/README diff --git a/lib_audio/ESP8266Audio/src/libmad/README.ESP8266 b/lib/lib_audio/ESP8266Audio/src/libmad/README.ESP8266 similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/README.ESP8266 rename to lib/lib_audio/ESP8266Audio/src/libmad/README.ESP8266 diff --git a/lib_audio/ESP8266Audio/src/libmad/TODO b/lib/lib_audio/ESP8266Audio/src/libmad/TODO similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/TODO rename to lib/lib_audio/ESP8266Audio/src/libmad/TODO diff --git a/lib_audio/ESP8266Audio/src/libmad/VERSION b/lib/lib_audio/ESP8266Audio/src/libmad/VERSION similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/VERSION rename to lib/lib_audio/ESP8266Audio/src/libmad/VERSION diff --git a/lib_audio/ESP8266Audio/src/libmad/bit.c b/lib/lib_audio/ESP8266Audio/src/libmad/bit.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/bit.c rename to lib/lib_audio/ESP8266Audio/src/libmad/bit.c diff --git a/lib_audio/ESP8266Audio/src/libmad/bit.h b/lib/lib_audio/ESP8266Audio/src/libmad/bit.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/bit.h rename to lib/lib_audio/ESP8266Audio/src/libmad/bit.h diff --git a/lib_audio/ESP8266Audio/src/libmad/config.h b/lib/lib_audio/ESP8266Audio/src/libmad/config.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/config.h rename to lib/lib_audio/ESP8266Audio/src/libmad/config.h diff --git a/lib_audio/ESP8266Audio/src/libmad/decoder.c b/lib/lib_audio/ESP8266Audio/src/libmad/decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/decoder.c rename to lib/lib_audio/ESP8266Audio/src/libmad/decoder.c diff --git a/lib_audio/ESP8266Audio/src/libmad/decoder.h b/lib/lib_audio/ESP8266Audio/src/libmad/decoder.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/decoder.h rename to lib/lib_audio/ESP8266Audio/src/libmad/decoder.h diff --git a/lib_audio/ESP8266Audio/src/libmad/fixed.c b/lib/lib_audio/ESP8266Audio/src/libmad/fixed.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/fixed.c rename to lib/lib_audio/ESP8266Audio/src/libmad/fixed.c diff --git a/lib_audio/ESP8266Audio/src/libmad/fixed.h b/lib/lib_audio/ESP8266Audio/src/libmad/fixed.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/fixed.h rename to lib/lib_audio/ESP8266Audio/src/libmad/fixed.h diff --git a/lib_audio/ESP8266Audio/src/libmad/frame.c b/lib/lib_audio/ESP8266Audio/src/libmad/frame.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/frame.c rename to lib/lib_audio/ESP8266Audio/src/libmad/frame.c diff --git a/lib_audio/ESP8266Audio/src/libmad/frame.h b/lib/lib_audio/ESP8266Audio/src/libmad/frame.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/frame.h rename to lib/lib_audio/ESP8266Audio/src/libmad/frame.h diff --git a/lib_audio/ESP8266Audio/src/libmad/global.h b/lib/lib_audio/ESP8266Audio/src/libmad/global.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/global.h rename to lib/lib_audio/ESP8266Audio/src/libmad/global.h diff --git a/lib_audio/ESP8266Audio/src/libmad/huffman.c b/lib/lib_audio/ESP8266Audio/src/libmad/huffman.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/huffman.c rename to lib/lib_audio/ESP8266Audio/src/libmad/huffman.c diff --git a/lib_audio/ESP8266Audio/src/libmad/huffman.h b/lib/lib_audio/ESP8266Audio/src/libmad/huffman.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/huffman.h rename to lib/lib_audio/ESP8266Audio/src/libmad/huffman.h diff --git a/lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h b/lib/lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h rename to lib/lib_audio/ESP8266Audio/src/libmad/imdct_s.dat.h diff --git a/lib_audio/ESP8266Audio/src/libmad/layer3.c b/lib/lib_audio/ESP8266Audio/src/libmad/layer3.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/layer3.c rename to lib/lib_audio/ESP8266Audio/src/libmad/layer3.c diff --git a/lib_audio/ESP8266Audio/src/libmad/layer3.h b/lib/lib_audio/ESP8266Audio/src/libmad/layer3.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/layer3.h rename to lib/lib_audio/ESP8266Audio/src/libmad/layer3.h diff --git a/lib_audio/ESP8266Audio/src/libmad/mad.h b/lib/lib_audio/ESP8266Audio/src/libmad/mad.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/mad.h rename to lib/lib_audio/ESP8266Audio/src/libmad/mad.h diff --git a/lib_audio/ESP8266Audio/src/libmad/mad.h.sed b/lib/lib_audio/ESP8266Audio/src/libmad/mad.h.sed similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/mad.h.sed rename to lib/lib_audio/ESP8266Audio/src/libmad/mad.h.sed diff --git a/lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h b/lib/lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h rename to lib/lib_audio/ESP8266Audio/src/libmad/qc_table.dat.h diff --git a/lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h b/lib/lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h rename to lib/lib_audio/ESP8266Audio/src/libmad/rq_table.dat.h diff --git a/lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h b/lib/lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h rename to lib/lib_audio/ESP8266Audio/src/libmad/sf_table.dat.h diff --git a/lib_audio/ESP8266Audio/src/libmad/stream.c b/lib/lib_audio/ESP8266Audio/src/libmad/stream.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/stream.c rename to lib/lib_audio/ESP8266Audio/src/libmad/stream.c diff --git a/lib_audio/ESP8266Audio/src/libmad/stream.h b/lib/lib_audio/ESP8266Audio/src/libmad/stream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/stream.h rename to lib/lib_audio/ESP8266Audio/src/libmad/stream.h diff --git a/lib_audio/ESP8266Audio/src/libmad/synth.c b/lib/lib_audio/ESP8266Audio/src/libmad/synth.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/synth.c rename to lib/lib_audio/ESP8266Audio/src/libmad/synth.c diff --git a/lib_audio/ESP8266Audio/src/libmad/synth.h b/lib/lib_audio/ESP8266Audio/src/libmad/synth.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/synth.h rename to lib/lib_audio/ESP8266Audio/src/libmad/synth.h diff --git a/lib_audio/ESP8266Audio/src/libmad/timer.c b/lib/lib_audio/ESP8266Audio/src/libmad/timer.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/timer.c rename to lib/lib_audio/ESP8266Audio/src/libmad/timer.c diff --git a/lib_audio/ESP8266Audio/src/libmad/timer.h b/lib/lib_audio/ESP8266Audio/src/libmad/timer.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/timer.h rename to lib/lib_audio/ESP8266Audio/src/libmad/timer.h diff --git a/lib_audio/ESP8266Audio/src/libmad/version.c b/lib/lib_audio/ESP8266Audio/src/libmad/version.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/version.c rename to lib/lib_audio/ESP8266Audio/src/libmad/version.c diff --git a/lib_audio/ESP8266Audio/src/libmad/version.h b/lib/lib_audio/ESP8266Audio/src/libmad/version.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libmad/version.h rename to lib/lib_audio/ESP8266Audio/src/libmad/version.h diff --git a/lib_audio/ESP8266Audio/src/libogg/AUTHORS b/lib/lib_audio/ESP8266Audio/src/libogg/AUTHORS similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/AUTHORS rename to lib/lib_audio/ESP8266Audio/src/libogg/AUTHORS diff --git a/lib_audio/ESP8266Audio/src/libogg/CHANGES b/lib/lib_audio/ESP8266Audio/src/libogg/CHANGES similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/CHANGES rename to lib/lib_audio/ESP8266Audio/src/libogg/CHANGES diff --git a/lib_audio/ESP8266Audio/src/libogg/COPYING b/lib/lib_audio/ESP8266Audio/src/libogg/COPYING similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/COPYING rename to lib/lib_audio/ESP8266Audio/src/libogg/COPYING diff --git a/lib_audio/ESP8266Audio/src/libogg/README.esp8266.md b/lib/lib_audio/ESP8266Audio/src/libogg/README.esp8266.md similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/README.esp8266.md rename to lib/lib_audio/ESP8266Audio/src/libogg/README.esp8266.md diff --git a/lib_audio/ESP8266Audio/src/libogg/README.md b/lib/lib_audio/ESP8266Audio/src/libogg/README.md similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/README.md rename to lib/lib_audio/ESP8266Audio/src/libogg/README.md diff --git a/lib_audio/ESP8266Audio/src/libogg/bitwise.c b/lib/lib_audio/ESP8266Audio/src/libogg/bitwise.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/bitwise.c rename to lib/lib_audio/ESP8266Audio/src/libogg/bitwise.c diff --git a/lib_audio/ESP8266Audio/src/libogg/config.h b/lib/lib_audio/ESP8266Audio/src/libogg/config.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/config.h rename to lib/lib_audio/ESP8266Audio/src/libogg/config.h diff --git a/lib_audio/ESP8266Audio/src/libogg/crctable.h b/lib/lib_audio/ESP8266Audio/src/libogg/crctable.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/crctable.h rename to lib/lib_audio/ESP8266Audio/src/libogg/crctable.h diff --git a/lib_audio/ESP8266Audio/src/libogg/framing.c b/lib/lib_audio/ESP8266Audio/src/libogg/framing.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/framing.c rename to lib/lib_audio/ESP8266Audio/src/libogg/framing.c diff --git a/lib_audio/ESP8266Audio/src/libogg/ogg.pc b/lib/lib_audio/ESP8266Audio/src/libogg/ogg.pc similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/ogg.pc rename to lib/lib_audio/ESP8266Audio/src/libogg/ogg.pc diff --git a/lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h b/lib/lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h rename to lib/lib_audio/ESP8266Audio/src/libogg/ogg/config_types.h diff --git a/lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h b/lib/lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h rename to lib/lib_audio/ESP8266Audio/src/libogg/ogg/ogg.h diff --git a/lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h b/lib/lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h rename to lib/lib_audio/ESP8266Audio/src/libogg/ogg/os_types.h diff --git a/lib_audio/ESP8266Audio/src/libopus/AUTHORS b/lib/lib_audio/ESP8266Audio/src/libopus/AUTHORS similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/AUTHORS rename to lib/lib_audio/ESP8266Audio/src/libopus/AUTHORS diff --git a/lib_audio/ESP8266Audio/src/libopus/COPYING b/lib/lib_audio/ESP8266Audio/src/libopus/COPYING similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/COPYING rename to lib/lib_audio/ESP8266Audio/src/libopus/COPYING diff --git a/lib_audio/ESP8266Audio/src/libopus/ChangeLog b/lib/lib_audio/ESP8266Audio/src/libopus/ChangeLog similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/ChangeLog rename to lib/lib_audio/ESP8266Audio/src/libopus/ChangeLog diff --git a/lib_audio/ESP8266Audio/src/libopus/INSTALL b/lib/lib_audio/ESP8266Audio/src/libopus/INSTALL similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/INSTALL rename to lib/lib_audio/ESP8266Audio/src/libopus/INSTALL diff --git a/lib_audio/ESP8266Audio/src/libopus/NEWS b/lib/lib_audio/ESP8266Audio/src/libopus/NEWS similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/NEWS rename to lib/lib_audio/ESP8266Audio/src/libopus/NEWS diff --git a/lib_audio/ESP8266Audio/src/libopus/README b/lib/lib_audio/ESP8266Audio/src/libopus/README similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/README rename to lib/lib_audio/ESP8266Audio/src/libopus/README diff --git a/lib_audio/ESP8266Audio/src/libopus/analysis.h b/lib/lib_audio/ESP8266Audio/src/libopus/analysis.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/analysis.h rename to lib/lib_audio/ESP8266Audio/src/libopus/analysis.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/_kiss_fft_guts.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/arch.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/arch.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/arch.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/arch.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/bands.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/bands.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/bands.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/bands.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/bands.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/bands.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/bands.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/bands.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_encoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/celt_lpc.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/cpu_support.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/cwrs.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/ecintrin.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entcode.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entcode.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entcode.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entcode.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entcode.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entcode.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entcode.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entcode.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entdec.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entdec.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entdec.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entdec.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entdec.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entdec.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entdec.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entdec.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entenc.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entenc.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entenc.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entenc.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/entenc.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/entenc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/entenc.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/entenc.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/fixed_debug.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/fixed_generic.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/float_cast.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/kiss_fft.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/laplace.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/laplace.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/laplace.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/laplace.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/laplace.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/laplace.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/laplace.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/laplace.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/mathops.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/mathops.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/mathops.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/mathops.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/mathops.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/mathops.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/mathops.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/mathops.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/mdct.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/mdct.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/mdct.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/mdct.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/mdct.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/mdct.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/mdct.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/mdct.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/mfrngcod.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/modes.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/modes.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/modes.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/modes.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/modes.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/modes.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/modes.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/modes.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/os_support.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/os_support.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/os_support.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/os_support.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/pitch.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/pitch.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/pitch.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/pitch.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/pitch.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/pitch.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/pitch.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/pitch.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/quant_bands.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/rate.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/rate.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/rate.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/rate.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/rate.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/rate.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/rate.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/rate.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/stack_alloc.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_fixed.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/static_modes_float.h diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/vq.c b/lib/lib_audio/ESP8266Audio/src/libopus/celt/vq.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/vq.c rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/vq.c diff --git a/lib_audio/ESP8266Audio/src/libopus/celt/vq.h b/lib/lib_audio/ESP8266Audio/src/libopus/celt/vq.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/celt/vq.h rename to lib/lib_audio/ESP8266Audio/src/libopus/celt/vq.h diff --git a/lib_audio/ESP8266Audio/src/libopus/config.h b/lib/lib_audio/ESP8266Audio/src/libopus/config.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/config.h rename to lib/lib_audio/ESP8266Audio/src/libopus/config.h diff --git a/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c b/lib/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c rename to lib/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.c diff --git a/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h b/lib/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h rename to lib/lib_audio/ESP8266Audio/src/libopus/mapping_matrix.h diff --git a/lib_audio/ESP8266Audio/src/libopus/mlp.h b/lib/lib_audio/ESP8266Audio/src/libopus/mlp.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/mlp.h rename to lib/lib_audio/ESP8266Audio/src/libopus/mlp.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus.pc b/lib/lib_audio/ESP8266Audio/src/libopus/opus.pc similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus.pc rename to lib/lib_audio/ESP8266Audio/src/libopus/opus.pc diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_custom.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_custom.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_custom.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_custom.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_decoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_defines.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_defines.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_defines.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_defines.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_encoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_encoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_encoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_encoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_multistream.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_multistream.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_multistream.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_multistream.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_multistream_encoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_private.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_private.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_private.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_private.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_projection.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_projection.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_projection.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_projection.h diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_projection_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_projection_encoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/opus_types.h b/lib/lib_audio/ESP8266Audio/src/libopus/opus_types.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/opus_types.h rename to lib/lib_audio/ESP8266Audio/src/libopus/opus_types.h diff --git a/lib_audio/ESP8266Audio/src/libopus/repacketizer.c b/lib/lib_audio/ESP8266Audio/src/libopus/repacketizer.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/repacketizer.c rename to lib/lib_audio/ESP8266Audio/src/libopus/repacketizer.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/A2NLSF.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/API.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/API.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/API.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/API.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/CNG.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/CNG.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/CNG.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/CNG.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/HP_variable_cutoff.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/Inlines.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_analysis_filter.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_fit.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/LPC_inv_pred_gain.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/LP_variable_cutoff.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/MacroCount.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/MacroDebug.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF2A.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_VQ_weights_laroia.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_decode.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_del_dec_quant.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_encode.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_stabilize.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NLSF_unpack.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/NSQ_del_dec.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/PLC.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/PLC.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/PLC.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/PLC.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/PLC.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/PLC.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/PLC.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/PLC.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/SigProc_FIX.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/VAD.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/VAD.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/VAD.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/VAD.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/VQ_WMat_EC.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/ana_filt_bank_1.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/biquad_alt.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/bwexpander_32.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/check_control_input.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/code_signs.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/control.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/control.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/control.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/control.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/control_SNR.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/control_audio_bandwidth.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/control_codec.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/debug.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/debug.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/debug.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/debug.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/debug.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/debug.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/debug.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/debug.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/dec_API.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_core.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_frame.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_indices.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_parameters.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_pitch.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decode_pulses.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/decoder_set_fs.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/define.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/define.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/define.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/define.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/enc_API.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/encode_indices.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/encode_pulses.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/errors.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/errors.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/errors.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/errors.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_analysis_filter_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/LTP_scale_ctrl_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/apply_sine_window_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/autocorr_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/burg_modified_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/corrMatrix_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/encode_frame_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LPC_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_LTP_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pitch_lags_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/find_pred_coefs_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/k2a_Q16_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/main_FIX.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/noise_shape_analysis_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/pitch_analysis_core_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/process_gains_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/regularize_correlations_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy16_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/residual_energy_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur64_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/schur_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/structs_FIX.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/vector_ops_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.lo diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o b/lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/fixed/warped_autocorrelation_FIX.o diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/gain_quant.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/init_decoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/init_encoder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/inner_prod_aligned.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/interpolate.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/lin2log.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/log2lin.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/macros.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/macros.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/macros.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/macros.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/main.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/main.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/main.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/main.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_defines.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/pitch_est_tables.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/process_NLSFs.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/quant_LTP_gains.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_down2_3.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_AR2.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_IIR_FIR.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_down_FIR.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_private_up2_HQ.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_rom.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/resampler_structs.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/shell_coder.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/sigm_Q15.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/sort.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/sort.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/sort.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/sort.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_LR_to_MS.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_MS_to_LR.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_decode_pred.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_encode_pred.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_find_predictor.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/stereo_quant_pred.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/structs.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/structs.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/structs.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/structs.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/sum_sqr_shift.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/table_LSF_cos.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_LTP.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_NB_MB.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_NLSF_CB_WB.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_gain.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_other.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_pitch_lag.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tables_pulses_per_block.c diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/tuning_parameters.h diff --git a/lib_audio/ESP8266Audio/src/libopus/silk/typedef.h b/lib/lib_audio/ESP8266Audio/src/libopus/silk/typedef.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/silk/typedef.h rename to lib/lib_audio/ESP8266Audio/src/libopus/silk/typedef.h diff --git a/lib_audio/ESP8266Audio/src/libopus/tansig_table.h b/lib/lib_audio/ESP8266Audio/src/libopus/tansig_table.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libopus/tansig_table.h rename to lib/lib_audio/ESP8266Audio/src/libopus/tansig_table.h diff --git a/lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE similarity index 100% rename from lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE rename to lib/lib_audio/ESP8266Audio/src/libtinysoundfont/LICENSE diff --git a/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 similarity index 100% rename from lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 rename to lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 diff --git a/lib_audio/ESP8266Audio/src/libtinysoundfont/README.md b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.md similarity index 100% rename from lib_audio/ESP8266Audio/src/libtinysoundfont/README.md rename to lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.md diff --git a/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h similarity index 100% rename from lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h rename to lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h diff --git a/lib_audio/ESP8266Audio/src/opusfile/AUTHORS b/lib/lib_audio/ESP8266Audio/src/opusfile/AUTHORS similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/AUTHORS rename to lib/lib_audio/ESP8266Audio/src/opusfile/AUTHORS diff --git a/lib_audio/ESP8266Audio/src/opusfile/COPYING b/lib/lib_audio/ESP8266Audio/src/opusfile/COPYING similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/COPYING rename to lib/lib_audio/ESP8266Audio/src/opusfile/COPYING diff --git a/lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md b/lib/lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md rename to lib/lib_audio/ESP8266Audio/src/opusfile/README.esp8266.md diff --git a/lib_audio/ESP8266Audio/src/opusfile/README.md b/lib/lib_audio/ESP8266Audio/src/opusfile/README.md similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/README.md rename to lib/lib_audio/ESP8266Audio/src/opusfile/README.md diff --git a/lib_audio/ESP8266Audio/src/opusfile/config.h b/lib/lib_audio/ESP8266Audio/src/opusfile/config.h similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/config.h rename to lib/lib_audio/ESP8266Audio/src/opusfile/config.h diff --git a/lib_audio/ESP8266Audio/src/opusfile/info.c b/lib/lib_audio/ESP8266Audio/src/opusfile/info.c similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/info.c rename to lib/lib_audio/ESP8266Audio/src/opusfile/info.c diff --git a/lib_audio/ESP8266Audio/src/opusfile/internal.c b/lib/lib_audio/ESP8266Audio/src/opusfile/internal.c similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/internal.c rename to lib/lib_audio/ESP8266Audio/src/opusfile/internal.c diff --git a/lib_audio/ESP8266Audio/src/opusfile/internal.h b/lib/lib_audio/ESP8266Audio/src/opusfile/internal.h similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/internal.h rename to lib/lib_audio/ESP8266Audio/src/opusfile/internal.h diff --git a/lib_audio/ESP8266Audio/src/opusfile/opusfile.c b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.c similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/opusfile.c rename to lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.c diff --git a/lib_audio/ESP8266Audio/src/opusfile/opusfile.h b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/opusfile.h rename to lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h diff --git a/lib_audio/ESP8266Audio/src/opusfile/opusfile.pc b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.pc similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/opusfile.pc rename to lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.pc diff --git a/lib_audio/ESP8266Audio/src/opusfile/stream.c b/lib/lib_audio/ESP8266Audio/src/opusfile/stream.c similarity index 100% rename from lib_audio/ESP8266Audio/src/opusfile/stream.c rename to lib/lib_audio/ESP8266Audio/src/opusfile/stream.c diff --git a/lib_audio/ESP8266Audio/src/spiram-fast.h b/lib/lib_audio/ESP8266Audio/src/spiram-fast.h similarity index 100% rename from lib_audio/ESP8266Audio/src/spiram-fast.h rename to lib/lib_audio/ESP8266Audio/src/spiram-fast.h diff --git a/lib_audio/ESP8266Audio/tests/common.sh b/lib/lib_audio/ESP8266Audio/tests/common.sh similarity index 100% rename from lib_audio/ESP8266Audio/tests/common.sh rename to lib/lib_audio/ESP8266Audio/tests/common.sh diff --git a/lib_audio/ESP8266Audio/tests/host/Arduino.h b/lib/lib_audio/ESP8266Audio/tests/host/Arduino.h similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/Arduino.h rename to lib/lib_audio/ESP8266Audio/tests/host/Arduino.h diff --git a/lib_audio/ESP8266Audio/tests/host/Makefile b/lib/lib_audio/ESP8266Audio/tests/host/Makefile similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/Makefile rename to lib/lib_audio/ESP8266Audio/tests/host/Makefile diff --git a/lib_audio/ESP8266Audio/tests/host/Serial.cpp b/lib/lib_audio/ESP8266Audio/tests/host/Serial.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/Serial.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/Serial.cpp diff --git a/lib_audio/ESP8266Audio/tests/host/aac.cpp b/lib/lib_audio/ESP8266Audio/tests/host/aac.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/aac.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/aac.cpp diff --git a/lib_audio/ESP8266Audio/tests/host/midi.cpp b/lib/lib_audio/ESP8266Audio/tests/host/midi.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/midi.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/midi.cpp diff --git a/lib_audio/ESP8266Audio/tests/host/mp3.cpp b/lib/lib_audio/ESP8266Audio/tests/host/mp3.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/mp3.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/mp3.cpp diff --git a/lib_audio/ESP8266Audio/tests/host/opus.cpp b/lib/lib_audio/ESP8266Audio/tests/host/opus.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/opus.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/opus.cpp diff --git a/lib_audio/ESP8266Audio/tests/host/pgmspace.h b/lib/lib_audio/ESP8266Audio/tests/host/pgmspace.h similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/pgmspace.h rename to lib/lib_audio/ESP8266Audio/tests/host/pgmspace.h diff --git a/lib_audio/ESP8266Audio/tests/host/test_8u_16.wav b/lib/lib_audio/ESP8266Audio/tests/host/test_8u_16.wav similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/test_8u_16.wav rename to lib/lib_audio/ESP8266Audio/tests/host/test_8u_16.wav diff --git a/lib_audio/ESP8266Audio/tests/host/wav.cpp b/lib/lib_audio/ESP8266Audio/tests/host/wav.cpp similarity index 100% rename from lib_audio/ESP8266Audio/tests/host/wav.cpp rename to lib/lib_audio/ESP8266Audio/tests/host/wav.cpp diff --git a/lib_audio/ESP8266SAM/README.md b/lib/lib_audio/ESP8266SAM/README.md similarity index 100% rename from lib_audio/ESP8266SAM/README.md rename to lib/lib_audio/ESP8266SAM/README.md diff --git a/lib_audio/ESP8266SAM/examples/Speak/Speak.ino b/lib/lib_audio/ESP8266SAM/examples/Speak/Speak.ino similarity index 100% rename from lib_audio/ESP8266SAM/examples/Speak/Speak.ino rename to lib/lib_audio/ESP8266SAM/examples/Speak/Speak.ino diff --git a/lib_audio/ESP8266SAM/library.json b/lib/lib_audio/ESP8266SAM/library.json similarity index 100% rename from lib_audio/ESP8266SAM/library.json rename to lib/lib_audio/ESP8266SAM/library.json diff --git a/lib_audio/ESP8266SAM/library.properties b/lib/lib_audio/ESP8266SAM/library.properties similarity index 100% rename from lib_audio/ESP8266SAM/library.properties rename to lib/lib_audio/ESP8266SAM/library.properties diff --git a/lib_audio/ESP8266SAM/src/ESP8266SAM.cpp b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.cpp similarity index 100% rename from lib_audio/ESP8266SAM/src/ESP8266SAM.cpp rename to lib/lib_audio/ESP8266SAM/src/ESP8266SAM.cpp diff --git a/lib_audio/ESP8266SAM/src/ESP8266SAM.h b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h similarity index 100% rename from lib_audio/ESP8266SAM/src/ESP8266SAM.h rename to lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h diff --git a/lib_audio/ESP8266SAM/src/ReciterTabs.h b/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h similarity index 100% rename from lib_audio/ESP8266SAM/src/ReciterTabs.h rename to lib/lib_audio/ESP8266SAM/src/ReciterTabs.h diff --git a/lib_audio/ESP8266SAM/src/RenderTabs.h b/lib/lib_audio/ESP8266SAM/src/RenderTabs.h similarity index 100% rename from lib_audio/ESP8266SAM/src/RenderTabs.h rename to lib/lib_audio/ESP8266SAM/src/RenderTabs.h diff --git a/lib_audio/ESP8266SAM/src/SamData.h b/lib/lib_audio/ESP8266SAM/src/SamData.h similarity index 100% rename from lib_audio/ESP8266SAM/src/SamData.h rename to lib/lib_audio/ESP8266SAM/src/SamData.h diff --git a/lib_audio/ESP8266SAM/src/SamTabs.h b/lib/lib_audio/ESP8266SAM/src/SamTabs.h similarity index 100% rename from lib_audio/ESP8266SAM/src/SamTabs.h rename to lib/lib_audio/ESP8266SAM/src/SamTabs.h diff --git a/lib_audio/ESP8266SAM/src/reciter.c b/lib/lib_audio/ESP8266SAM/src/reciter.c similarity index 100% rename from lib_audio/ESP8266SAM/src/reciter.c rename to lib/lib_audio/ESP8266SAM/src/reciter.c diff --git a/lib_audio/ESP8266SAM/src/reciter.h b/lib/lib_audio/ESP8266SAM/src/reciter.h similarity index 100% rename from lib_audio/ESP8266SAM/src/reciter.h rename to lib/lib_audio/ESP8266SAM/src/reciter.h diff --git a/lib_audio/ESP8266SAM/src/render.c b/lib/lib_audio/ESP8266SAM/src/render.c similarity index 100% rename from lib_audio/ESP8266SAM/src/render.c rename to lib/lib_audio/ESP8266SAM/src/render.c diff --git a/lib_audio/ESP8266SAM/src/render.h b/lib/lib_audio/ESP8266SAM/src/render.h similarity index 100% rename from lib_audio/ESP8266SAM/src/render.h rename to lib/lib_audio/ESP8266SAM/src/render.h diff --git a/lib_audio/ESP8266SAM/src/sam.c b/lib/lib_audio/ESP8266SAM/src/sam.c similarity index 100% rename from lib_audio/ESP8266SAM/src/sam.c rename to lib/lib_audio/ESP8266SAM/src/sam.c diff --git a/lib_audio/ESP8266SAM/src/sam.h b/lib/lib_audio/ESP8266SAM/src/sam.h similarity index 100% rename from lib_audio/ESP8266SAM/src/sam.h rename to lib/lib_audio/ESP8266SAM/src/sam.h diff --git a/lib_audio/ESP8266SAM/src/samdebug.c b/lib/lib_audio/ESP8266SAM/src/samdebug.c similarity index 100% rename from lib_audio/ESP8266SAM/src/samdebug.c rename to lib/lib_audio/ESP8266SAM/src/samdebug.c diff --git a/lib_audio/ESP8266SAM/src/samdebug.h b/lib/lib_audio/ESP8266SAM/src/samdebug.h similarity index 100% rename from lib_audio/ESP8266SAM/src/samdebug.h rename to lib/lib_audio/ESP8266SAM/src/samdebug.h diff --git a/lib_basic/C2Programmer-1.0.0/README.md b/lib/lib_basic/C2Programmer-1.0.0/README.md similarity index 100% rename from lib_basic/C2Programmer-1.0.0/README.md rename to lib/lib_basic/C2Programmer-1.0.0/README.md diff --git a/lib_basic/C2Programmer-1.0.0/keywords.txt b/lib/lib_basic/C2Programmer-1.0.0/keywords.txt similarity index 100% rename from lib_basic/C2Programmer-1.0.0/keywords.txt rename to lib/lib_basic/C2Programmer-1.0.0/keywords.txt diff --git a/lib_basic/C2Programmer-1.0.0/library.json b/lib/lib_basic/C2Programmer-1.0.0/library.json similarity index 100% rename from lib_basic/C2Programmer-1.0.0/library.json rename to lib/lib_basic/C2Programmer-1.0.0/library.json diff --git a/lib_basic/C2Programmer-1.0.0/library.properties b/lib/lib_basic/C2Programmer-1.0.0/library.properties similarity index 100% rename from lib_basic/C2Programmer-1.0.0/library.properties rename to lib/lib_basic/C2Programmer-1.0.0/library.properties diff --git a/lib_basic/C2Programmer-1.0.0/src/c2.cpp b/lib/lib_basic/C2Programmer-1.0.0/src/c2.cpp similarity index 100% rename from lib_basic/C2Programmer-1.0.0/src/c2.cpp rename to lib/lib_basic/C2Programmer-1.0.0/src/c2.cpp diff --git a/lib_basic/C2Programmer-1.0.0/src/c2.h b/lib/lib_basic/C2Programmer-1.0.0/src/c2.h similarity index 100% rename from lib_basic/C2Programmer-1.0.0/src/c2.h rename to lib/lib_basic/C2Programmer-1.0.0/src/c2.h diff --git a/lib_basic/C2Programmer-1.0.0/src/ihx.cpp b/lib/lib_basic/C2Programmer-1.0.0/src/ihx.cpp similarity index 100% rename from lib_basic/C2Programmer-1.0.0/src/ihx.cpp rename to lib/lib_basic/C2Programmer-1.0.0/src/ihx.cpp diff --git a/lib_basic/C2Programmer-1.0.0/src/ihx.h b/lib/lib_basic/C2Programmer-1.0.0/src/ihx.h similarity index 100% rename from lib_basic/C2Programmer-1.0.0/src/ihx.h rename to lib/lib_basic/C2Programmer-1.0.0/src/ihx.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md b/lib/lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/.github/CONTRIBUTING.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md b/lib/lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/.github/Contributors.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md b/lib/lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/.github/issue_template.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/.gitignore b/lib/lib_basic/IRremoteESP8266-2.7.11/.gitignore similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.gitignore rename to lib/lib_basic/IRremoteESP8266-2.7.11/.gitignore diff --git a/lib_basic/IRremoteESP8266-2.7.11/.gitmodules b/lib/lib_basic/IRremoteESP8266-2.7.11/.gitmodules similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.gitmodules rename to lib/lib_basic/IRremoteESP8266-2.7.11/.gitmodules diff --git a/lib_basic/IRremoteESP8266-2.7.11/.style.yapf b/lib/lib_basic/IRremoteESP8266-2.7.11/.style.yapf similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.style.yapf rename to lib/lib_basic/IRremoteESP8266-2.7.11/.style.yapf diff --git a/lib_basic/IRremoteESP8266-2.7.11/.travis.yml b/lib/lib_basic/IRremoteESP8266-2.7.11/.travis.yml similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/.travis.yml rename to lib/lib_basic/IRremoteESP8266-2.7.11/.travis.yml diff --git a/lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg b/lib/lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg rename to lib/lib_basic/IRremoteESP8266-2.7.11/CPPLINT.cfg diff --git a/lib_basic/IRremoteESP8266-2.7.11/Doxyfile b/lib/lib_basic/IRremoteESP8266-2.7.11/Doxyfile similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/Doxyfile rename to lib/lib_basic/IRremoteESP8266-2.7.11/Doxyfile diff --git a/lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt b/lib/lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt rename to lib/lib_basic/IRremoteESP8266-2.7.11/LICENSE.txt diff --git a/lib_basic/IRremoteESP8266-2.7.11/README.md b/lib/lib_basic/IRremoteESP8266-2.7.11/README.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/README.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/README.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/README_fr.md b/lib/lib_basic/IRremoteESP8266-2.7.11/README_fr.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/README_fr.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/README_fr.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md b/lib/lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/ReleaseNotes.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md b/lib/lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/SupportedProtocols.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/README.md b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/README.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/README.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/README.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/README_fr.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/_config.yml diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRac_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRrecv_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRremoteESP8266_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRsend_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtext_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRtimer_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/IRutils_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/README_8md.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/annotated.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bc_s.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/bdwn.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAirwellAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRAmcorAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRArgoAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCarrierAc64__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoolixAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRCoronaAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin128__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin152__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin160__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin176__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin216__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin2__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikin64__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDaikinESP__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRDelonghiAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRElectraAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRFujitsuAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGoodweatherAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRGreeAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierACYRW02__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHaierAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc1__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc344__inherit__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc3__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc424__inherit__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRHitachiAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRKelvinatorAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRLgAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMideaAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi112__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishi136__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy152Ac__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRMitsubishiHeavy88Ac__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRNeoclimaAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRPanasonicAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSamsungAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSanyoAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRSharpAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTcl112Ac__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTechnibelAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTecoAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRToshibaAC__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTranscoldAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRTrotecESP__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVestelAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRVoltas__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRWhirlpoolAc__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRac__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRrecv__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRsend.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classIRtimer.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classTimerMs.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classdecode__results.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/classes.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/closed.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-CH_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/de-DE_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/defaults_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/deprecated.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_49e56c817e5e54854c35e136979f97ca.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dir_84fe998d1eb06414cc389ad334e77e63.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doc.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.css diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/doxygen__index_8md.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/dynsections.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-AU_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-IE_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-UK_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/en-US_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/es-ES_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/files.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderclosed.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/folderopen.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/fr-FR_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_g.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_i.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_k.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_l.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_m.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_n.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_o.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_p.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_r.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_s.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_u.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_v.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_w.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_func_~.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_g.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_i.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_k.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_l.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_m.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_n.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_o.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_p.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_q.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_r.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_rela.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_s.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_u.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_v.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_i.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_l.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_m.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_n.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_o.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_p.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_q.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_r.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_s.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_u.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_v.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_w.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_x.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_vars_z.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_w.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_x.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_z.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/functions_~.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_enum.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_eval.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_func.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_g.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_i.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_j.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_k.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_l.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_m.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_n.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_p.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_r.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_s.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_type.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_u.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_v.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_i.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_vars_k.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_w.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_x.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_y.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/globals_z.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/graph_legend.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/hierarchy.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/i18n_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/index.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_0.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_1.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_10.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_11.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_12.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_13.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_14.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_15.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_16.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_17.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_18.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_19.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_2.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_20.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_21.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_22.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_23.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_24.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_25.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_26.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_27.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_28.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_29.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_3.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_30.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_31.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_32.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_33.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_34.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_35.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_36.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_37.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_38.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_39.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_4.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_40.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_41.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_42.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_43.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_44.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_45.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_46.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_47.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_48.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_49.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_5.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_50.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_51.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_52.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_53.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_54.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_55.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_56.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_57.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_58.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_59.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_6.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_60.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_61.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_62.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_63.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_64.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_65.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_66.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_67.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_68.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_7.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_8.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherit_graph_9.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/inherits.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Airwell_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Aiwa_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Amcor_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Argo_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Carrier_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Coolix_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Corona_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Daikin_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Delonghi_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Denon_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Dish_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Doshisha_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Electra_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Epson_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Fujitsu_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GICable_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__GlobalCache_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Goodweather_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Gree_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Haier_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Hitachi_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Inax_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__JVC_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Kelvinator_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__LG_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lasertag_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lego_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Lutron_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MWM_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Magiquest_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Metz_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Midea_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__MitsubishiHeavy_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Mitsubishi_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Multibrackets_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__NEC_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Neoclima_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Nikai_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Panasonic_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pioneer_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Pronto_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RC5__RC6_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__RCMM_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Samsung_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sanyo_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sharp_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sherwood_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Sony_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Symphony_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Tcl_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Technibel_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Teco_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Toshiba_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Transcold_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Trotec_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Vestel_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Voltas_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whirlpool_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Whynter_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/ir__Zepeal_8cpp.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/it-IT_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/jquery.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/md_src_locale_README.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menu.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/menudata.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceIRAcUtils.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaceirutils.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_enum.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacemembers_func.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespaces.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/namespacestdAc.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_f.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_g.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/nav_h.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/open.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/pages.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_10.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_11.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_12.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_13.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_14.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_15.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_16.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_17.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_18.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_19.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1a.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_1b.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_a.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_b.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_c.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_d.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_e.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/all_f.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/classes_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/close.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enums_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_10.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_11.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_12.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_13.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_14.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_15.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_a.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_b.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_c.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_d.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_e.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/enumvalues_f.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/files_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_10.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_11.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_12.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_13.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_14.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_15.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_16.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_17.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_a.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_b.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_c.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_d.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_e.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/functions_f.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/mag_sel.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/namespaces_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/nomatches.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/pages_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/related_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.css diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_l.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_m.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/search_r.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/searchdata.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/typedefs_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_0.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_1.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_10.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_11.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_12.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_13.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_14.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_15.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_16.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_17.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_2.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_3.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_4.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_5.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_6.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_7.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_8.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_9.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_a.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_b.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_c.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_d.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_e.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/search/variables_f.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/splitbar.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structCoronaSection.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structirparams__t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structmatch__result__t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/structstdAc_1_1state__t.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_off.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/sync_on.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_a.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_b.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_h.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tab_s.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/tabs.css diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/todo.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAirwellProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionAmcorProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionArgoProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCarrierProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.map diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.md5 diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionCoronaProtocol__coll__graph.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionDelonghiProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionGreeProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionHaierYRW02Protocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionMideaProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionVoltasProtocol.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest-members.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/unionmagiquest.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen/html/zh-CN_8h_source.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md b/lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/docs/doxygen_index.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/BlynkIrRemote.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/BlynkIrRemote/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/CommonAcControl.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/CommonAcControl/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/ControlSamsungAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/ControlSamsungAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/DumbIRRepeater.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/DumbIRRepeater/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCSendDemo/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRGCTCPServer/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/IRMQTTServer.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRMQTTServer/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/IRServer.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRServer/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDemo/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDump/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/IRrecvDumpV2.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV2/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/BaseOTA.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/IRrecvDumpV3.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRrecvDumpV3/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendDemo/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/IRsendProntoDemo.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/IRsendProntoDemo/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/LGACSend.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/LGACSend/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/SmartIRRepeater.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/SmartIRRepeater/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnArgoAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/TurnOnGreeAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnGreeAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnMitsubishiHeavyAc/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnPanasonicAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnToshibaAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/TurnOnTrotecAC/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/README.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/Web-AC-control.ino diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/favicon.ico diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_off.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_1_on.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_off.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_2_on.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_off.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_3_on.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_off.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/level_4_on.svg diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.html diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/data/ui.js diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png b/lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png rename to lib/lib_basic/IRremoteESP8266-2.7.11/examples/Web-AC-control/printscreen.png diff --git a/lib_basic/IRremoteESP8266-2.7.11/keywords.txt b/lib/lib_basic/IRremoteESP8266-2.7.11/keywords.txt similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/keywords.txt rename to lib/lib_basic/IRremoteESP8266-2.7.11/keywords.txt diff --git a/lib_basic/IRremoteESP8266-2.7.11/library.json b/lib/lib_basic/IRremoteESP8266-2.7.11/library.json similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/library.json rename to lib/lib_basic/IRremoteESP8266-2.7.11/library.json diff --git a/lib_basic/IRremoteESP8266-2.7.11/library.properties b/lib/lib_basic/IRremoteESP8266-2.7.11/library.properties similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/library.properties rename to lib/lib_basic/IRremoteESP8266-2.7.11/library.properties diff --git a/lib_basic/IRremoteESP8266-2.7.11/platformio.ini b/lib/lib_basic/IRremoteESP8266-2.7.11/platformio.ini similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/platformio.ini rename to lib/lib_basic/IRremoteESP8266-2.7.11/platformio.ini diff --git a/lib_basic/IRremoteESP8266-2.7.11/pylintrc b/lib/lib_basic/IRremoteESP8266-2.7.11/pylintrc similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/pylintrc rename to lib/lib_basic/IRremoteESP8266-2.7.11/pylintrc diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg b/lib/lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/CPPLINT.cfg diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRac.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRac.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRac.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRac.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRac.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRrecv.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRremoteESP8266.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRsend.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtext.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRtimer.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/IRutils.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/i18n.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/i18n.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/i18n.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/i18n.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Airwell.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Aiwa.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Amcor.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Argo.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Carrier.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Coolix.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Corona.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Daikin.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Delonghi.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Denon.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Dish.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Doshisha.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Electra.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Epson.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Fujitsu.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_GICable.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_GlobalCache.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Goodweather.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Gree.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Haier.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Hitachi.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Inax.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_JVC.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Kelvinator.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_LG.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lasertag.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lego.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Lutron.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MWM.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Magiquest.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Metz.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Midea.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Mitsubishi.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_MitsubishiHeavy.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Multibrackets.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_NEC.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Neoclima.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Nikai.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Panasonic.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pioneer.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Pronto.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_RC5_RC6.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_RCMM.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Samsung.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sanyo.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sharp.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sherwood.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Sony.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Symphony.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Tcl.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Technibel.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Teco.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Toshiba.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Transcold.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Trotec.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Vestel.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Voltas.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whirlpool.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Whynter.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/ir_Zepeal.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/README.md diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-CH.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/de-DE.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/defaults.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-AU.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-IE.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-UK.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/en-US.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/es-ES.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/fr-FR.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/it-IT.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h b/lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/src/locale/zh-CN.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRac_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRrecv_test.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRsend_test.h diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/IRutils_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/Makefile b/lib/lib_basic/IRremoteESP8266-2.7.11/test/Makefile similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/Makefile rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/Makefile diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Airwell_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Aiwa_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Amcor_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Argo_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Carrier_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Coolix_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Corona_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Daikin_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Delonghi_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Denon_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Dish_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Doshisha_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Electra_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Epson_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Fujitsu_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_GICable_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_GlobalCache_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Goodweather_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Gree_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Haier_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Hitachi_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Inax_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_JVC_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Kelvinator_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_LG_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lasertag_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lego_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Lutron_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_MWM_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Magiquest_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Metz_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Midea_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_MitsubishiHeavy_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Mitsubishi_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Multibrackets_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_NEC_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Neoclima_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Nikai_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Panasonic_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pioneer_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Pronto_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_RC5_RC6_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_RCMM_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Samsung_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sanyo_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sharp_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sherwood_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Sony_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Symphony_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Tcl_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Technibel_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Teco_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Toshiba_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Transcold_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Trotec_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Vestel_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Voltas_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whirlpool_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Whynter_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/test/ir_Zepeal_test.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/Makefile b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/Makefile similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/Makefile rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/Makefile diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/RawToGlobalCache.sh diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data.py diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/auto_analyse_raw_data_test.py diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/gc_decode.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/generate_irtext_h.sh diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/mkkeywords diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/mode2_decode.cpp diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code.py diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/raw_to_pronto_code_test.py diff --git a/lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py b/lib/lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py similarity index 100% rename from lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py rename to lib/lib_basic/IRremoteESP8266-2.7.11/tools/scrape_supported_devices.py diff --git a/lib_basic/NeoPixelBus-2.6.0/.gitattributes b/lib/lib_basic/NeoPixelBus-2.6.0/.gitattributes similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.gitattributes rename to lib/lib_basic/NeoPixelBus-2.6.0/.gitattributes diff --git a/lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml b/lib/lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml rename to lib/lib_basic/NeoPixelBus-2.6.0/.github/FUNDING.yml diff --git a/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md b/lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md rename to lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/all-others.md diff --git a/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md b/lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md rename to lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md b/lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md rename to lib/lib_basic/NeoPixelBus-2.6.0/.github/ISSUE_TEMPLATE/feature_request.md diff --git a/lib_basic/NeoPixelBus-2.6.0/.gitignore b/lib/lib_basic/NeoPixelBus-2.6.0/.gitignore similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/.gitignore rename to lib/lib_basic/NeoPixelBus-2.6.0/.gitignore diff --git a/lib_basic/NeoPixelBus-2.6.0/COPYING b/lib/lib_basic/NeoPixelBus-2.6.0/COPYING similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/COPYING rename to lib/lib_basic/NeoPixelBus-2.6.0/COPYING diff --git a/lib_basic/NeoPixelBus-2.6.0/ReadMe.md b/lib/lib_basic/NeoPixelBus-2.6.0/ReadMe.md similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/ReadMe.md rename to lib/lib_basic/NeoPixelBus-2.6.0/ReadMe.md diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/DotStarTest/DotStarTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelBrightness/NeoPixelBrightness.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelGamma/NeoPixelGamma.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/NeoPixelTest/NeoPixelTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelCylon/NeoPixelCylon.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/Strings.bmp diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBitmap/StringsW.bmp diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino b/lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino rename to lib/lib_basic/NeoPixelBus-2.6.0/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/circular.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/cubic.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/different.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/exponential.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/gamma.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/pronounced.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/quadratic.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/quintic.png diff --git a/lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png b/lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png rename to lib/lib_basic/NeoPixelBus-2.6.0/extras/curves/sinusoidal.png diff --git a/lib_basic/NeoPixelBus-2.6.0/keywords.txt b/lib/lib_basic/NeoPixelBus-2.6.0/keywords.txt similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/keywords.txt rename to lib/lib_basic/NeoPixelBus-2.6.0/keywords.txt diff --git a/lib_basic/NeoPixelBus-2.6.0/library.json b/lib/lib_basic/NeoPixelBus-2.6.0/library.json similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/library.json rename to lib/lib_basic/NeoPixelBus-2.6.0/library.json diff --git a/lib_basic/NeoPixelBus-2.6.0/library.properties b/lib/lib_basic/NeoPixelBus-2.6.0/library.properties similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/library.properties rename to lib/lib_basic/NeoPixelBus-2.6.0/library.properties diff --git a/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelAnimator.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBrightnessBus.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelBus.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/NeoPixelSegmentBus.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarColorFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/DotStarGenericMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.c diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Esp32_i2s.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HsbColor.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HslColor.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColor.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNameStrings.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorNames.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/HtmlColorShortNames.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Layouts.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806ColorFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Lpd8806GenericMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoArmMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoAvrMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBitmapFile.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBuffer.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferContext.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoBufferMethods.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoColorFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoDib.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEase.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32I2sMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp32RmtMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266DmaMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEsp8266UartMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoEspBitBangMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoGamma.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoHueBlend.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoMosaic.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoNrf52xMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAnimator.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoPixelAvr.c diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoRingTopology.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSegmentFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSettings.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoSpriteSheet.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTiles.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTm1814ColorFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/NeoTopology.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813ColorFeatures.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/P9813GenericMethod.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbColor.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/RgbwColor.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.cpp diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/SegmentDigit.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImple.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireBitBangImpleAvr.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/TwoWireSpiImple.h diff --git a/lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h b/lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h similarity index 100% rename from lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h rename to lib/lib_basic/NeoPixelBus-2.6.0/src/internal/Ws2801GenericMethod.h diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.cpp diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/OneWire.h diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/README.md diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/keywords.txt diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.json diff --git a/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties b/lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties similarity index 100% rename from lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties rename to lib/lib_basic/OneWire-Stickbreaker-20190506-1.1/library.properties diff --git a/lib_basic/TasmotaModbus-1.2.0/README.md b/lib/lib_basic/TasmotaModbus-1.2.0/README.md similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/README.md rename to lib/lib_basic/TasmotaModbus-1.2.0/README.md diff --git a/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino b/lib/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino rename to lib/lib_basic/TasmotaModbus-1.2.0/examples/modbustest/modbustest.ino diff --git a/lib_basic/TasmotaModbus-1.2.0/keywords.txt b/lib/lib_basic/TasmotaModbus-1.2.0/keywords.txt similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/keywords.txt rename to lib/lib_basic/TasmotaModbus-1.2.0/keywords.txt diff --git a/lib_basic/TasmotaModbus-1.2.0/library.json b/lib/lib_basic/TasmotaModbus-1.2.0/library.json similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/library.json rename to lib/lib_basic/TasmotaModbus-1.2.0/library.json diff --git a/lib_basic/TasmotaModbus-1.2.0/library.properties b/lib/lib_basic/TasmotaModbus-1.2.0/library.properties similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/library.properties rename to lib/lib_basic/TasmotaModbus-1.2.0/library.properties diff --git a/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp rename to lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp diff --git a/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h similarity index 100% rename from lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h rename to lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.gitignore diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/.travis.yml diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.cpp diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_GFX.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.cpp diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Adafruit_SPITFT_Macros.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMono9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBold9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoBoldOblique9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeMonoOblique9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSans9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBold9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansBoldOblique9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSansOblique9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerif9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBold9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifBoldItalic9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic12pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic18pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic24pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/FreeSerifItalic9pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Org_01.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Picopixel.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/Tiny3x3a2pt7b.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/Fonts/TomThumb.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/README.md diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/examples/mock_ili9341/mock_ili9341.ino diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/Makefile diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert.c diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/fontconvert_win.md diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/fontconvert/makefonts.sh diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/gfxfont.h diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/glcdfont.c diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/library.properties diff --git a/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt b/lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt similarity index 100% rename from lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt rename to lib/lib_display/Adafruit-GFX-Library-1.5.6-gemu-1.0/license.txt diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/ISSUE_TEMPLATE.md diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.gitignore diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/.travis.yml diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.cpp diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/Adafruit_ILI9341.h diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/README.md diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/.esp8266.test.skip diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/breakouttouchpaint/breakouttouchpaint.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/.mega2560.test.skip diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/fulltest_featherwing/fulltest_featherwing.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest/graphicstest.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/.mega2560.test.skip diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/graphicstest_featherwing/graphicstest_featherwing.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton/onoffbutton.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/.esp8266.test.skip diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/onoffbutton_breakout/onoffbutton_breakout.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/dragon.h diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/pictureEmbed/pictureEmbed.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/spitftbitmap/spitftbitmap.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint/touchpaint.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/.mega2560.test.skip diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/examples/touchpaint_featherwing/touchpaint_featherwing.ino diff --git a/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties b/lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties similarity index 100% rename from lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties rename to lib/lib_display/Adafruit_ILI9341-1.2.0-Tasmota-1.0/library.properties diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.cpp diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/Adafruit_LEDBackpack.h diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/README.md b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/README.md similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/README.md rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/README.md diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/README.txt b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/README.txt similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/README.txt rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/README.txt diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/HT16K33/HT16K33.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bargraph24/bargraph24.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/bicolor8x8/bicolor8x8.pde diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_ds1307/clock_sevenseg_ds1307.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/clock_sevenseg_gps/clock_sevenseg_gps.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix16x8/matrix16x8.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/matrix8x8/matrix8x8.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/minimatrix16x8/minimatrix16x8.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum/quadalphanum.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/quadalphanum_mini/quadalphanum_mini.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/roboface/roboface.pde diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/sevenseg/sevenseg.ino diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavface.pde diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/beware_i.wav diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/ihunger.wav diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/examples/wavface/wavs/run_cowd.wav diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/library.properties b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/library.properties similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/library.properties rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/library.properties diff --git a/lib_display/Adafruit_LED_Backpack-1.1.6/license.txt b/lib/lib_display/Adafruit_LED_Backpack-1.1.6/license.txt similarity index 100% rename from lib_display/Adafruit_LED_Backpack-1.1.6/license.txt rename to lib/lib_display/Adafruit_LED_Backpack-1.1.6/license.txt diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp b/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h b/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.h diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt b/lib/lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/LICENSE.txt diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/README.md b/lib/lib_display/Adafruit_SH1106-gemu-1.0/README.md similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/README.md rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/README.md diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino b/lib/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_i2c/sh1106_128x64_i2c.ino diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino b/lib/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/examples/sh1106_128x64_spi/sh1106_128x64_spi.ino diff --git a/lib_display/Adafruit_SH1106-gemu-1.0/library.properties b/lib/lib_display/Adafruit_SH1106-gemu-1.0/library.properties similarity index 100% rename from lib_display/Adafruit_SH1106-gemu-1.0/library.properties rename to lib/lib_display/Adafruit_SH1106-gemu-1.0/library.properties diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/ISSUE_TEMPLATE.md diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.gitignore diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/.travis.yml diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/README.md diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/OLED_featherwing/OLED_featherwing.ino diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x32_spi/ssd1306_128x32_spi.ino diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_i2c/ssd1306_128x64_i2c.ino diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/examples/ssd1306_128x64_spi/ssd1306_128x64_spi.ino diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/library.properties diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/license.txt diff --git a/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h similarity index 100% rename from lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h rename to lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/splash.h diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/README.md b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/README.md similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/README.md rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/README.md diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.c diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/Tiger.rgb diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/keywords.txt diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/library.properties b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/library.properties similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/library.properties rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/library.properties diff --git a/lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h similarity index 100% rename from lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h rename to lib/lib_display/Adafruit_SSD1351-gemu-1.0/spi_register.h diff --git a/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp rename to lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp diff --git a/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h rename to lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h diff --git a/lib_display/Arduino_ST7789-gemu-1.0/README.txt b/lib/lib_display/Arduino_ST7789-gemu-1.0/README.txt similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/README.txt rename to lib/lib_display/Arduino_ST7789-gemu-1.0/README.txt diff --git a/lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino b/lib/lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino rename to lib/lib_display/Arduino_ST7789-gemu-1.0/examples/graphicstest/graphicstest.ino diff --git a/lib_display/Arduino_ST7789-gemu-1.0/keywords.txt b/lib/lib_display/Arduino_ST7789-gemu-1.0/keywords.txt similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/keywords.txt rename to lib/lib_display/Arduino_ST7789-gemu-1.0/keywords.txt diff --git a/lib_display/Arduino_ST7789-gemu-1.0/library.properties b/lib/lib_display/Arduino_ST7789-gemu-1.0/library.properties similarity index 100% rename from lib_display/Arduino_ST7789-gemu-1.0/library.properties rename to lib/lib_display/Arduino_ST7789-gemu-1.0/library.properties diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.cpp diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/ILI9488.h diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/README.md diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/examples/graphicstest/graphicstest.ino diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/keywords.txt diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/library.properties diff --git a/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h b/lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h similarity index 100% rename from lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h rename to lib/lib_display/JaretBurkett_ILI9488-gemu-1.0/spi_register.h diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp b/lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.cpp diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h b/lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.h diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o b/lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/LiquidCrystal_I2C.o diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/README.md b/lib/lib_display/LiquidCrystal_I2C-1.1.3/README.md similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/README.md rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/README.md diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde b/lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/CustomChars/CustomChars.pde diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde b/lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/HelloWorld/HelloWorld.pde diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde b/lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/examples/SerialDisplay/SerialDisplay.pde diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt b/lib/lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/keywords.txt diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/library.json b/lib/lib_display/LiquidCrystal_I2C-1.1.3/library.json similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/library.json rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/library.json diff --git a/lib_display/LiquidCrystal_I2C-1.1.3/library.properties b/lib/lib_display/LiquidCrystal_I2C-1.1.3/library.properties similarity index 100% rename from lib_display/LiquidCrystal_I2C-1.1.3/library.properties rename to lib/lib_display/LiquidCrystal_I2C-1.1.3/library.properties diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/README.md b/lib/lib_display/Xlatb_RA8876-gemu-1.0/README.md similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/README.md rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/README.md diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt b/lib/lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/keywords.txt diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/library.properties b/lib/lib_display/Xlatb_RA8876-gemu-1.0/library.properties similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/library.properties rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/library.properties diff --git a/lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h b/lib/lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h similarity index 100% rename from lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h rename to lib/lib_display/Xlatb_RA8876-gemu-1.0/spi_register.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.gitignore diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/.travis.yml diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/epd2in9-demo/epd2in9-demo.ino diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Arduino/libraries/readme.txt diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/LICENSE diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/Makefile diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/README.md diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/component.mk diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper-29-ws.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_font.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/epaper_fonts.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font16.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font20.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/font8.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/components/epaper-29-ws/imagedata.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Doxyfile diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/Makefile diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/README.md diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/conf.py diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/gen-dxd.py diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/index.rst diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/link-roles.py diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/repo_util.py diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/docs/requirements.txt diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/library.properties diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/README.md diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/component.mk diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/esp-epaper-29-ws.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/main/imagedata.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/2.9inch_e-Paper_Datasheet.pdf diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-image.jpg diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/e-paper-and-esp-sample-text.jpg diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/espresif-logo.bmp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/pictures/image-conversion-setup.png diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd2in9.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epd4in2.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdif.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/epdpaint.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font12.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font16.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font20.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font24.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/font8.c diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/fonts.h diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.cpp diff --git a/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h b/lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h similarity index 100% rename from lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h rename to lib/lib_display/esp-epaper-29-ws-20171230-gemu-1.1/src/renderer.h diff --git a/lib_div/A4988_Stepper/README.adoc b/lib/lib_div/A4988_Stepper/README.adoc similarity index 100% rename from lib_div/A4988_Stepper/README.adoc rename to lib/lib_div/A4988_Stepper/README.adoc diff --git a/lib_div/A4988_Stepper/keywords.txt b/lib/lib_div/A4988_Stepper/keywords.txt similarity index 100% rename from lib_div/A4988_Stepper/keywords.txt rename to lib/lib_div/A4988_Stepper/keywords.txt diff --git a/lib_div/A4988_Stepper/library.properties b/lib/lib_div/A4988_Stepper/library.properties similarity index 100% rename from lib_div/A4988_Stepper/library.properties rename to lib/lib_div/A4988_Stepper/library.properties diff --git a/lib_div/A4988_Stepper/src/A4988_Stepper.cpp b/lib/lib_div/A4988_Stepper/src/A4988_Stepper.cpp similarity index 100% rename from lib_div/A4988_Stepper/src/A4988_Stepper.cpp rename to lib/lib_div/A4988_Stepper/src/A4988_Stepper.cpp diff --git a/lib_div/A4988_Stepper/src/A4988_Stepper.h b/lib/lib_div/A4988_Stepper/src/A4988_Stepper.h similarity index 100% rename from lib_div/A4988_Stepper/src/A4988_Stepper.h rename to lib/lib_div/A4988_Stepper/src/A4988_Stepper.h diff --git a/lib_div/ArduinoNTPd/NTPPacket.cpp b/lib/lib_div/ArduinoNTPd/NTPPacket.cpp similarity index 100% rename from lib_div/ArduinoNTPd/NTPPacket.cpp rename to lib/lib_div/ArduinoNTPd/NTPPacket.cpp diff --git a/lib_div/ArduinoNTPd/NTPPacket.h b/lib/lib_div/ArduinoNTPd/NTPPacket.h similarity index 100% rename from lib_div/ArduinoNTPd/NTPPacket.h rename to lib/lib_div/ArduinoNTPd/NTPPacket.h diff --git a/lib_div/ArduinoNTPd/NTPServer.cpp b/lib/lib_div/ArduinoNTPd/NTPServer.cpp similarity index 100% rename from lib_div/ArduinoNTPd/NTPServer.cpp rename to lib/lib_div/ArduinoNTPd/NTPServer.cpp diff --git a/lib_div/ArduinoNTPd/NTPServer.h b/lib/lib_div/ArduinoNTPd/NTPServer.h similarity index 100% rename from lib_div/ArduinoNTPd/NTPServer.h rename to lib/lib_div/ArduinoNTPd/NTPServer.h diff --git a/lib_div/ArduinoNTPd/library.properties b/lib/lib_div/ArduinoNTPd/library.properties similarity index 100% rename from lib_div/ArduinoNTPd/library.properties rename to lib/lib_div/ArduinoNTPd/library.properties diff --git a/lib_div/LibTeleinfo/README.md b/lib/lib_div/LibTeleinfo/README.md similarity index 100% rename from lib_div/LibTeleinfo/README.md rename to lib/lib_div/LibTeleinfo/README.md diff --git a/lib_div/LibTeleinfo/library.json b/lib/lib_div/LibTeleinfo/library.json similarity index 100% rename from lib_div/LibTeleinfo/library.json rename to lib/lib_div/LibTeleinfo/library.json diff --git a/lib_div/LibTeleinfo/library.properties b/lib/lib_div/LibTeleinfo/library.properties similarity index 100% rename from lib_div/LibTeleinfo/library.properties rename to lib/lib_div/LibTeleinfo/library.properties diff --git a/lib_div/LibTeleinfo/src/LibTeleinfo.cpp b/lib/lib_div/LibTeleinfo/src/LibTeleinfo.cpp similarity index 100% rename from lib_div/LibTeleinfo/src/LibTeleinfo.cpp rename to lib/lib_div/LibTeleinfo/src/LibTeleinfo.cpp diff --git a/lib_div/LibTeleinfo/src/LibTeleinfo.h b/lib/lib_div/LibTeleinfo/src/LibTeleinfo.h similarity index 100% rename from lib_div/LibTeleinfo/src/LibTeleinfo.h rename to lib/lib_div/LibTeleinfo/src/LibTeleinfo.h diff --git a/lib_div/NewPing-1.9.1/README.md b/lib/lib_div/NewPing-1.9.1/README.md similarity index 100% rename from lib_div/NewPing-1.9.1/README.md rename to lib/lib_div/NewPing-1.9.1/README.md diff --git a/lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde b/lib/lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde rename to lib/lib_div/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde diff --git a/lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde b/lib/lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde rename to lib/lib_div/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde diff --git a/lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde b/lib/lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde rename to lib/lib_div/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde diff --git a/lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde b/lib/lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde rename to lib/lib_div/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde diff --git a/lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde b/lib/lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde rename to lib/lib_div/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde diff --git a/lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde b/lib/lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde similarity index 100% rename from lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde rename to lib/lib_div/NewPing-1.9.1/examples/TimerExample/TimerExample.pde diff --git a/lib_div/NewPing-1.9.1/keywords.txt b/lib/lib_div/NewPing-1.9.1/keywords.txt similarity index 100% rename from lib_div/NewPing-1.9.1/keywords.txt rename to lib/lib_div/NewPing-1.9.1/keywords.txt diff --git a/lib_div/NewPing-1.9.1/library.properties b/lib/lib_div/NewPing-1.9.1/library.properties similarity index 100% rename from lib_div/NewPing-1.9.1/library.properties rename to lib/lib_div/NewPing-1.9.1/library.properties diff --git a/lib_div/NewPing-1.9.1/src/NewPing.cpp b/lib/lib_div/NewPing-1.9.1/src/NewPing.cpp similarity index 100% rename from lib_div/NewPing-1.9.1/src/NewPing.cpp rename to lib/lib_div/NewPing-1.9.1/src/NewPing.cpp diff --git a/lib_div/NewPing-1.9.1/src/NewPing.h b/lib/lib_div/NewPing-1.9.1/src/NewPing.h similarity index 100% rename from lib_div/NewPing-1.9.1/src/NewPing.h rename to lib/lib_div/NewPing-1.9.1/src/NewPing.h diff --git a/lib_div/OpenTherm-0.9.0/LICENSE b/lib/lib_div/OpenTherm-0.9.0/LICENSE similarity index 100% rename from lib_div/OpenTherm-0.9.0/LICENSE rename to lib/lib_div/OpenTherm-0.9.0/LICENSE diff --git a/lib_div/OpenTherm-0.9.0/README.md b/lib/lib_div/OpenTherm-0.9.0/README.md similarity index 100% rename from lib_div/OpenTherm-0.9.0/README.md rename to lib/lib_div/OpenTherm-0.9.0/README.md diff --git a/lib_div/OpenTherm-0.9.0/keywords.txt b/lib/lib_div/OpenTherm-0.9.0/keywords.txt similarity index 100% rename from lib_div/OpenTherm-0.9.0/keywords.txt rename to lib/lib_div/OpenTherm-0.9.0/keywords.txt diff --git a/lib_div/OpenTherm-0.9.0/library.properties b/lib/lib_div/OpenTherm-0.9.0/library.properties similarity index 100% rename from lib_div/OpenTherm-0.9.0/library.properties rename to lib/lib_div/OpenTherm-0.9.0/library.properties diff --git a/lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp b/lib/lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp similarity index 100% rename from lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp rename to lib/lib_div/OpenTherm-0.9.0/src/OpenTherm.cpp diff --git a/lib_div/OpenTherm-0.9.0/src/OpenTherm.h b/lib/lib_div/OpenTherm-0.9.0/src/OpenTherm.h similarity index 100% rename from lib_div/OpenTherm-0.9.0/src/OpenTherm.h rename to lib/lib_div/OpenTherm-0.9.0/src/OpenTherm.h diff --git a/lib_div/esp-knx-ip-0.5.2/LICENSE b/lib/lib_div/esp-knx-ip-0.5.2/LICENSE similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/LICENSE rename to lib/lib_div/esp-knx-ip-0.5.2/LICENSE diff --git a/lib_div/esp-knx-ip-0.5.2/README.md b/lib/lib_div/esp-knx-ip-0.5.2/README.md similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/README.md rename to lib/lib_div/esp-knx-ip-0.5.2/README.md diff --git a/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino b/lib/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino rename to lib/lib_div/esp-knx-ip-0.5.2/examples/environment-sensor/environment-sensor.ino diff --git a/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino b/lib/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino rename to lib/lib_div/esp-knx-ip-0.5.2/examples/sonoff/sonoff.ino diff --git a/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino b/lib/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino rename to lib/lib_div/esp-knx-ip-0.5.2/examples/static-config/static-config.ino diff --git a/lib_div/esp-knx-ip-0.5.2/keywords.txt b/lib/lib_div/esp-knx-ip-0.5.2/keywords.txt similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/keywords.txt rename to lib/lib_div/esp-knx-ip-0.5.2/keywords.txt diff --git a/lib_div/esp-knx-ip-0.5.2/library.json b/lib/lib_div/esp-knx-ip-0.5.2/library.json similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/library.json rename to lib/lib_div/esp-knx-ip-0.5.2/library.json diff --git a/lib_div/esp-knx-ip-0.5.2/library.properties.off b/lib/lib_div/esp-knx-ip-0.5.2/library.properties.off similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/library.properties.off rename to lib/lib_div/esp-knx-ip-0.5.2/library.properties.off diff --git a/lib_div/esp-knx-ip-0.5.2/src/DPT.h b/lib/lib_div/esp-knx-ip-0.5.2/src/DPT.h similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/DPT.h rename to lib/lib_div/esp-knx-ip-0.5.2/src/DPT.h diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-config.cpp diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-conversion.cpp diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-webserver.cpp diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.cpp diff --git a/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h similarity index 100% rename from lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h rename to lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip.h diff --git a/lib_i2c/Adafruit_BusIO/.travis.yml b/lib/lib_i2c/Adafruit_BusIO/.travis.yml similarity index 100% rename from lib_i2c/Adafruit_BusIO/.travis.yml rename to lib/lib_i2c/Adafruit_BusIO/.travis.yml diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp diff --git a/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h similarity index 100% rename from lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h rename to lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h diff --git a/lib_i2c/Adafruit_BusIO/LICENSE b/lib/lib_i2c/Adafruit_BusIO/LICENSE similarity index 100% rename from lib_i2c/Adafruit_BusIO/LICENSE rename to lib/lib_i2c/Adafruit_BusIO/LICENSE diff --git a/lib_i2c/Adafruit_BusIO/README.md b/lib/lib_i2c/Adafruit_BusIO/README.md similarity index 100% rename from lib_i2c/Adafruit_BusIO/README.md rename to lib/lib_i2c/Adafruit_BusIO/README.md diff --git a/lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino b/lib/lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino b/lib/lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino b/lib/lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino b/lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino b/lib/lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino b/lib/lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino diff --git a/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino b/lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino similarity index 100% rename from lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino rename to lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino diff --git a/lib_i2c/Adafruit_BusIO/library.properties b/lib/lib_i2c/Adafruit_BusIO/library.properties similarity index 100% rename from lib_i2c/Adafruit_BusIO/library.properties rename to lib/lib_i2c/Adafruit_BusIO/library.properties diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/.travis.yml diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.cpp diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/Adafruit_CCS811.h diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/LICENSE diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/README.md b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/README.md similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/README.md rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/README.md diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/examples/CCS811_test/CCS811_test.ino diff --git a/lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties b/lib/lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties similarity index 100% rename from lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties rename to lib/lib_i2c/Adafruit_CCS811-1.0.0.14/library.properties diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.cpp diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/Adafruit_MAX31865.h diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.md diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/README.txt diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/examples/max31865/max31865.ino diff --git a/lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties b/lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties similarity index 100% rename from lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties rename to lib/lib_i2c/Adafruit_MAX31865-1.1.0-custom/library.properties diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/ISSUE_TEMPLATE.md diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/.github/workflows/githubci.yml diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/.gitignore diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.cpp diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/Adafruit_MCP9808.h diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/README.md b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/README.md similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/README.md rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/README.md diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/assets/board.jpg diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/code-of-conduct.md diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/examples/mcp9808test/mcp9808test.ino diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/library.properties b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/library.properties similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/library.properties rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/library.properties diff --git a/lib_i2c/Adafruit_MCP9808_Tasmota/license.txt b/lib/lib_i2c/Adafruit_MCP9808_Tasmota/license.txt similarity index 100% rename from lib_i2c/Adafruit_MCP9808_Tasmota/license.txt rename to lib/lib_i2c/Adafruit_MCP9808_Tasmota/license.txt diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp b/lib/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.cpp diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h b/lib/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/Adafruit_SGP30.h diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/README.md b/lib/lib_i2c/Adafruit_SGP30-1.2.0/README.md similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/README.md rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/README.md diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino b/lib/lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/examples/sgp30test/sgp30test.ino diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/library.properties b/lib/lib_i2c/Adafruit_SGP30-1.2.0/library.properties similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/library.properties rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/library.properties diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/license.txt b/lib/lib_i2c/Adafruit_SGP30-1.2.0/license.txt similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/license.txt rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/license.txt diff --git a/lib_i2c/Adafruit_SGP30-1.2.0/travis.yml b/lib/lib_i2c/Adafruit_SGP30-1.2.0/travis.yml similarity index 100% rename from lib_i2c/Adafruit_SGP30-1.2.0/travis.yml rename to lib/lib_i2c/Adafruit_SGP30-1.2.0/travis.yml diff --git a/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp b/lib/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp similarity index 100% rename from lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp rename to lib/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp diff --git a/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h b/lib/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h similarity index 100% rename from lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h rename to lib/lib_i2c/Adafruit_TSL2591_Library/Adafruit_TSL2591.h diff --git a/lib_i2c/Adafruit_TSL2591_Library/library.properties b/lib/lib_i2c/Adafruit_TSL2591_Library/library.properties similarity index 100% rename from lib_i2c/Adafruit_TSL2591_Library/library.properties rename to lib/lib_i2c/Adafruit_TSL2591_Library/library.properties diff --git a/lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md b/lib/lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md similarity index 100% rename from lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md rename to lib/lib_i2c/Adafruit_VEML7700/.github/ISSUE_TEMPLATE.md diff --git a/lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md b/lib/lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md rename to lib/lib_i2c/Adafruit_VEML7700/.github/PULL_REQUEST_TEMPLATE.md diff --git a/lib_i2c/Adafruit_VEML7700/.gitignore b/lib/lib_i2c/Adafruit_VEML7700/.gitignore similarity index 100% rename from lib_i2c/Adafruit_VEML7700/.gitignore rename to lib/lib_i2c/Adafruit_VEML7700/.gitignore diff --git a/lib_i2c/Adafruit_VEML7700/.travis.yml b/lib/lib_i2c/Adafruit_VEML7700/.travis.yml similarity index 100% rename from lib_i2c/Adafruit_VEML7700/.travis.yml rename to lib/lib_i2c/Adafruit_VEML7700/.travis.yml diff --git a/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp b/lib/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp similarity index 100% rename from lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp rename to lib/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.cpp diff --git a/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h b/lib/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h similarity index 100% rename from lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h rename to lib/lib_i2c/Adafruit_VEML7700/Adafruit_VEML7700.h diff --git a/lib_i2c/Adafruit_VEML7700/README.md b/lib/lib_i2c/Adafruit_VEML7700/README.md similarity index 100% rename from lib_i2c/Adafruit_VEML7700/README.md rename to lib/lib_i2c/Adafruit_VEML7700/README.md diff --git a/lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino b/lib/lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino similarity index 100% rename from lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino rename to lib/lib_i2c/Adafruit_VEML7700/examples/veml7700_test/veml7700_test.ino diff --git a/lib_i2c/Adafruit_VEML7700/library.properties b/lib/lib_i2c/Adafruit_VEML7700/library.properties similarity index 100% rename from lib_i2c/Adafruit_VEML7700/library.properties rename to lib/lib_i2c/Adafruit_VEML7700/library.properties diff --git a/lib_i2c/Adafruit_VEML7700/license.txt b/lib/lib_i2c/Adafruit_VEML7700/license.txt similarity index 100% rename from lib_i2c/Adafruit_VEML7700/license.txt rename to lib/lib_i2c/Adafruit_VEML7700/license.txt diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/LICENSE diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/README.md b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/README.md similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/README.md rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/README.md diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.c diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/Self test/bme680_selftest.h diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.c diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680.h diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/bme680_defs.h diff --git a/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties b/lib/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties similarity index 100% rename from lib_i2c/BME680_driver-bme680_v3.5.9/library.properties rename to lib/lib_i2c/BME680_driver-bme680_v3.5.9/library.properties diff --git a/lib_i2c/FT5206_Library/.gitignore b/lib/lib_i2c/FT5206_Library/.gitignore similarity index 100% rename from lib_i2c/FT5206_Library/.gitignore rename to lib/lib_i2c/FT5206_Library/.gitignore diff --git a/lib_i2c/FT5206_Library/LICENSE b/lib/lib_i2c/FT5206_Library/LICENSE similarity index 100% rename from lib_i2c/FT5206_Library/LICENSE rename to lib/lib_i2c/FT5206_Library/LICENSE diff --git a/lib_i2c/FT5206_Library/README.md b/lib/lib_i2c/FT5206_Library/README.md similarity index 100% rename from lib_i2c/FT5206_Library/README.md rename to lib/lib_i2c/FT5206_Library/README.md diff --git a/lib_i2c/FT5206_Library/keywords.txt b/lib/lib_i2c/FT5206_Library/keywords.txt similarity index 100% rename from lib_i2c/FT5206_Library/keywords.txt rename to lib/lib_i2c/FT5206_Library/keywords.txt diff --git a/lib_i2c/FT5206_Library/library.properties b/lib/lib_i2c/FT5206_Library/library.properties similarity index 100% rename from lib_i2c/FT5206_Library/library.properties rename to lib/lib_i2c/FT5206_Library/library.properties diff --git a/lib_i2c/FT5206_Library/src/FT5206.cpp b/lib/lib_i2c/FT5206_Library/src/FT5206.cpp similarity index 100% rename from lib_i2c/FT5206_Library/src/FT5206.cpp rename to lib/lib_i2c/FT5206_Library/src/FT5206.cpp diff --git a/lib_i2c/FT5206_Library/src/FT5206.h b/lib/lib_i2c/FT5206_Library/src/FT5206.h similarity index 100% rename from lib_i2c/FT5206_Library/src/FT5206.h rename to lib/lib_i2c/FT5206_Library/src/FT5206.h diff --git a/lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp b/lib/lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp similarity index 100% rename from lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp rename to lib/lib_i2c/FrogmoreScd30/FrogmoreScd30.cpp diff --git a/lib_i2c/FrogmoreScd30/FrogmoreScd30.h b/lib/lib_i2c/FrogmoreScd30/FrogmoreScd30.h similarity index 100% rename from lib_i2c/FrogmoreScd30/FrogmoreScd30.h rename to lib/lib_i2c/FrogmoreScd30/FrogmoreScd30.h diff --git a/lib_i2c/FrogmoreScd30/library.properties b/lib/lib_i2c/FrogmoreScd30/library.properties similarity index 100% rename from lib_i2c/FrogmoreScd30/library.properties rename to lib/lib_i2c/FrogmoreScd30/library.properties diff --git a/lib_i2c/HPMA115S0/LICENSE.md b/lib/lib_i2c/HPMA115S0/LICENSE.md similarity index 100% rename from lib_i2c/HPMA115S0/LICENSE.md rename to lib/lib_i2c/HPMA115S0/LICENSE.md diff --git a/lib_i2c/HPMA115S0/README.md b/lib/lib_i2c/HPMA115S0/README.md similarity index 100% rename from lib_i2c/HPMA115S0/README.md rename to lib/lib_i2c/HPMA115S0/README.md diff --git a/lib_i2c/HPMA115S0/example/example.ino b/lib/lib_i2c/HPMA115S0/example/example.ino similarity index 100% rename from lib_i2c/HPMA115S0/example/example.ino rename to lib/lib_i2c/HPMA115S0/example/example.ino diff --git a/lib_i2c/HPMA115S0/library.properties b/lib/lib_i2c/HPMA115S0/library.properties similarity index 100% rename from lib_i2c/HPMA115S0/library.properties rename to lib/lib_i2c/HPMA115S0/library.properties diff --git a/lib_i2c/HPMA115S0/src/hpma115S0.cpp b/lib/lib_i2c/HPMA115S0/src/hpma115S0.cpp similarity index 100% rename from lib_i2c/HPMA115S0/src/hpma115S0.cpp rename to lib/lib_i2c/HPMA115S0/src/hpma115S0.cpp diff --git a/lib_i2c/HPMA115S0/src/hpma115S0.h b/lib/lib_i2c/HPMA115S0/src/hpma115S0.h similarity index 100% rename from lib_i2c/HPMA115S0/src/hpma115S0.h rename to lib/lib_i2c/HPMA115S0/src/hpma115S0.h diff --git a/lib_i2c/I2Cdevlib-Core/.library.json b/lib/lib_i2c/I2Cdevlib-Core/.library.json similarity index 100% rename from lib_i2c/I2Cdevlib-Core/.library.json rename to lib/lib_i2c/I2Cdevlib-Core/.library.json diff --git a/lib_i2c/I2Cdevlib-Core/I2Cdev.cpp b/lib/lib_i2c/I2Cdevlib-Core/I2Cdev.cpp similarity index 100% rename from lib_i2c/I2Cdevlib-Core/I2Cdev.cpp rename to lib/lib_i2c/I2Cdevlib-Core/I2Cdev.cpp diff --git a/lib_i2c/I2Cdevlib-Core/I2Cdev.h b/lib/lib_i2c/I2Cdevlib-Core/I2Cdev.h similarity index 100% rename from lib_i2c/I2Cdevlib-Core/I2Cdev.h rename to lib/lib_i2c/I2Cdevlib-Core/I2Cdev.h diff --git a/lib_i2c/I2Cdevlib-Core/keywords.txt b/lib/lib_i2c/I2Cdevlib-Core/keywords.txt similarity index 100% rename from lib_i2c/I2Cdevlib-Core/keywords.txt rename to lib/lib_i2c/I2Cdevlib-Core/keywords.txt diff --git a/lib_i2c/I2Cdevlib-Core/library.json b/lib/lib_i2c/I2Cdevlib-Core/library.json similarity index 100% rename from lib_i2c/I2Cdevlib-Core/library.json rename to lib/lib_i2c/I2Cdevlib-Core/library.json diff --git a/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino rename to lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino diff --git a/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde rename to lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde diff --git a/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino b/lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino rename to lib/lib_i2c/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino diff --git a/lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp b/lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp rename to lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050.cpp diff --git a/lib_i2c/I2Cdevlib-MPU6050/MPU6050.h b/lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050.h similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/MPU6050.h rename to lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050.h diff --git a/lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h rename to lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h diff --git a/lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h b/lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h rename to lib/lib_i2c/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h diff --git a/lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h b/lib/lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h rename to lib/lib_i2c/I2Cdevlib-MPU6050/helper_3dmath.h diff --git a/lib_i2c/I2Cdevlib-MPU6050/library.properties b/lib/lib_i2c/I2Cdevlib-MPU6050/library.properties similarity index 100% rename from lib_i2c/I2Cdevlib-MPU6050/library.properties rename to lib/lib_i2c/I2Cdevlib-MPU6050/library.properties diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/.gitignore b/lib/lib_i2c/Joba_Tsl2561-2.0.10/.gitignore similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/.gitignore rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/.gitignore diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/.hgignore b/lib/lib_i2c/Joba_Tsl2561-2.0.10/.hgignore similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/.hgignore rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/.hgignore diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml b/lib/lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/.travis.yml diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/COPYING b/lib/lib_i2c/Joba_Tsl2561-2.0.10/COPYING similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/COPYING rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/COPYING diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER b/lib/lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/COPYING.LESSER diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/README b/lib/lib_i2c/Joba_Tsl2561-2.0.10/README similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/README rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/README diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Autogain/Autogain.ino diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Simple/Simple.ino diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Testing/Testing.ino diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/Utility/Utility.ino diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.ini diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh b/lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/examples/platformio.sh diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt b/lib/lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/lib/readme.txt diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/library.json b/lib/lib_i2c/Joba_Tsl2561-2.0.10/library.json similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/library.json rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/library.json diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/library.properties b/lib/lib_i2c/Joba_Tsl2561-2.0.10/library.properties similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/library.properties rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/library.properties diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini b/lib/lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/platformio.ini diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp b/lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.cpp diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h b/lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561.h diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp b/lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.cpp diff --git a/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h b/lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h similarity index 100% rename from lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h rename to lib/lib_i2c/Joba_Tsl2561-2.0.10/src/Tsl2561Util.h diff --git a/lib_i2c/LOLIN_HP303B/README.md b/lib/lib_i2c/LOLIN_HP303B/README.md similarity index 100% rename from lib_i2c/LOLIN_HP303B/README.md rename to lib/lib_i2c/LOLIN_HP303B/README.md diff --git a/lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino b/lib/lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino similarity index 100% rename from lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino rename to lib/lib_i2c/LOLIN_HP303B/examples/i2c_background/i2c_background.ino diff --git a/lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino b/lib/lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino similarity index 100% rename from lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino rename to lib/lib_i2c/LOLIN_HP303B/examples/i2c_command/i2c_command.ino diff --git a/lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino b/lib/lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino similarity index 100% rename from lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino rename to lib/lib_i2c/LOLIN_HP303B/examples/i2c_interrupt/i2c_interrupt.ino diff --git a/lib_i2c/LOLIN_HP303B/examples/library.properties b/lib/lib_i2c/LOLIN_HP303B/examples/library.properties similarity index 100% rename from lib_i2c/LOLIN_HP303B/examples/library.properties rename to lib/lib_i2c/LOLIN_HP303B/examples/library.properties diff --git a/lib_i2c/LOLIN_HP303B/keywords.txt b/lib/lib_i2c/LOLIN_HP303B/keywords.txt similarity index 100% rename from lib_i2c/LOLIN_HP303B/keywords.txt rename to lib/lib_i2c/LOLIN_HP303B/keywords.txt diff --git a/lib_i2c/LOLIN_HP303B/library.properties b/lib/lib_i2c/LOLIN_HP303B/library.properties similarity index 100% rename from lib_i2c/LOLIN_HP303B/library.properties rename to lib/lib_i2c/LOLIN_HP303B/library.properties diff --git a/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp b/lib/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp similarity index 100% rename from lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp rename to lib/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.cpp diff --git a/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h b/lib/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h similarity index 100% rename from lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h rename to lib/lib_i2c/LOLIN_HP303B/src/LOLIN_HP303B.h diff --git a/lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h b/lib/lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h similarity index 100% rename from lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h rename to lib/lib_i2c/LOLIN_HP303B/src/util/hp303b_consts.h diff --git a/lib_i2c/LinkedList-1.2.3/LICENSE.txt b/lib/lib_i2c/LinkedList-1.2.3/LICENSE.txt similarity index 100% rename from lib_i2c/LinkedList-1.2.3/LICENSE.txt rename to lib/lib_i2c/LinkedList-1.2.3/LICENSE.txt diff --git a/lib_i2c/LinkedList-1.2.3/LinkedList.h b/lib/lib_i2c/LinkedList-1.2.3/LinkedList.h similarity index 100% rename from lib_i2c/LinkedList-1.2.3/LinkedList.h rename to lib/lib_i2c/LinkedList-1.2.3/LinkedList.h diff --git a/lib_i2c/LinkedList-1.2.3/README.md b/lib/lib_i2c/LinkedList-1.2.3/README.md similarity index 100% rename from lib_i2c/LinkedList-1.2.3/README.md rename to lib/lib_i2c/LinkedList-1.2.3/README.md diff --git a/lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde b/lib/lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde similarity index 100% rename from lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde rename to lib/lib_i2c/LinkedList-1.2.3/examples/ClassList/ClassList.pde diff --git a/lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde b/lib/lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde similarity index 100% rename from lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde rename to lib/lib_i2c/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde diff --git a/lib_i2c/LinkedList-1.2.3/keywords.txt b/lib/lib_i2c/LinkedList-1.2.3/keywords.txt similarity index 100% rename from lib_i2c/LinkedList-1.2.3/keywords.txt rename to lib/lib_i2c/LinkedList-1.2.3/keywords.txt diff --git a/lib_i2c/LinkedList-1.2.3/library.json b/lib/lib_i2c/LinkedList-1.2.3/library.json similarity index 100% rename from lib_i2c/LinkedList-1.2.3/library.json rename to lib/lib_i2c/LinkedList-1.2.3/library.json diff --git a/lib_i2c/LinkedList-1.2.3/library.properties b/lib/lib_i2c/LinkedList-1.2.3/library.properties similarity index 100% rename from lib_i2c/LinkedList-1.2.3/library.properties rename to lib/lib_i2c/LinkedList-1.2.3/library.properties diff --git a/lib_i2c/Mutichannel_Gas_Sensor/License.txt b/lib/lib_i2c/Mutichannel_Gas_Sensor/License.txt similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/License.txt rename to lib/lib_i2c/Mutichannel_Gas_Sensor/License.txt diff --git a/lib_i2c/Mutichannel_Gas_Sensor/README.md b/lib/lib_i2c/Mutichannel_Gas_Sensor/README.md similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/README.md rename to lib/lib_i2c/Mutichannel_Gas_Sensor/README.md diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/GetVersion/GetVersion.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/I2C_Address/I2C_Address.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/RawData/RawData.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Grove/ReadSensorValue_Grove.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/ReadSensorValue_Xadow/ReadSensorValue_Xadow.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/UpdateFrimware.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/bootloader_atmega168.h diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/UpdateFrimware/gpl.txt diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/calibration/calibration.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/factory_setting/factory_setting.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino b/lib/lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino rename to lib/lib_i2c/Mutichannel_Gas_Sensor/examples/new_firmware/new_firmware.ino diff --git a/lib_i2c/Mutichannel_Gas_Sensor/library.json b/lib/lib_i2c/Mutichannel_Gas_Sensor/library.json similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/library.json rename to lib/lib_i2c/Mutichannel_Gas_Sensor/library.json diff --git a/lib_i2c/Mutichannel_Gas_Sensor/library.properties b/lib/lib_i2c/Mutichannel_Gas_Sensor/library.properties similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/library.properties rename to lib/lib_i2c/Mutichannel_Gas_Sensor/library.properties diff --git a/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp b/lib/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp rename to lib/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.cpp diff --git a/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h b/lib/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h similarity index 100% rename from lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h rename to lib/lib_i2c/Mutichannel_Gas_Sensor/src/MutichannelGasSensor.h diff --git a/lib_i2c/mlx90640-library/MLX90640_API.cpp b/lib/lib_i2c/mlx90640-library/MLX90640_API.cpp similarity index 100% rename from lib_i2c/mlx90640-library/MLX90640_API.cpp rename to lib/lib_i2c/mlx90640-library/MLX90640_API.cpp diff --git a/lib_i2c/mlx90640-library/MLX90640_API.h b/lib/lib_i2c/mlx90640-library/MLX90640_API.h similarity index 100% rename from lib_i2c/mlx90640-library/MLX90640_API.h rename to lib/lib_i2c/mlx90640-library/MLX90640_API.h diff --git a/lib_i2c/mlx90640-library/library.properties b/lib/lib_i2c/mlx90640-library/library.properties similarity index 100% rename from lib_i2c/mlx90640-library/library.properties rename to lib/lib_i2c/mlx90640-library/library.properties diff --git a/lib_i2c/vl53l0x-arduino-1.02/.travis.yml b/lib/lib_i2c/vl53l0x-arduino-1.02/.travis.yml similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/.travis.yml rename to lib/lib_i2c/vl53l0x-arduino-1.02/.travis.yml diff --git a/lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt b/lib/lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt rename to lib/lib_i2c/vl53l0x-arduino-1.02/LICENSE.txt diff --git a/lib_i2c/vl53l0x-arduino-1.02/README.md b/lib/lib_i2c/vl53l0x-arduino-1.02/README.md similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/README.md rename to lib/lib_i2c/vl53l0x-arduino-1.02/README.md diff --git a/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp b/lib/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp rename to lib/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.cpp diff --git a/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h b/lib/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h rename to lib/lib_i2c/vl53l0x-arduino-1.02/VL53L0X.h diff --git a/lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino b/lib/lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino rename to lib/lib_i2c/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino diff --git a/lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino b/lib/lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino rename to lib/lib_i2c/vl53l0x-arduino-1.02/examples/Single/Single.ino diff --git a/lib_i2c/vl53l0x-arduino-1.02/keywords.txt b/lib/lib_i2c/vl53l0x-arduino-1.02/keywords.txt similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/keywords.txt rename to lib/lib_i2c/vl53l0x-arduino-1.02/keywords.txt diff --git a/lib_i2c/vl53l0x-arduino-1.02/library.properties b/lib/lib_i2c/vl53l0x-arduino-1.02/library.properties similarity index 100% rename from lib_i2c/vl53l0x-arduino-1.02/library.properties rename to lib/lib_i2c/vl53l0x-arduino-1.02/library.properties diff --git a/lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt b/lib/lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt rename to lib/lib_i2c/vl53l1x-arduino-1.01/LICENSE.txt diff --git a/lib_i2c/vl53l1x-arduino-1.01/README.md b/lib/lib_i2c/vl53l1x-arduino-1.01/README.md similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/README.md rename to lib/lib_i2c/vl53l1x-arduino-1.01/README.md diff --git a/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp b/lib/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp rename to lib/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.cpp diff --git a/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h b/lib/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h rename to lib/lib_i2c/vl53l1x-arduino-1.01/VL53L1X.h diff --git a/lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino b/lib/lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino rename to lib/lib_i2c/vl53l1x-arduino-1.01/examples/Continuous/Continuous.ino diff --git a/lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino b/lib/lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino rename to lib/lib_i2c/vl53l1x-arduino-1.01/examples/ContinuousWithDetails/ContinuousWithDetails.ino diff --git a/lib_i2c/vl53l1x-arduino-1.01/keywords.txt b/lib/lib_i2c/vl53l1x-arduino-1.01/keywords.txt similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/keywords.txt rename to lib/lib_i2c/vl53l1x-arduino-1.01/keywords.txt diff --git a/lib_i2c/vl53l1x-arduino-1.01/library.properties b/lib/lib_i2c/vl53l1x-arduino-1.01/library.properties similarity index 100% rename from lib_i2c/vl53l1x-arduino-1.01/library.properties rename to lib/lib_i2c/vl53l1x-arduino-1.01/library.properties diff --git a/lib_rf/KeeloqLib/README.md b/lib/lib_rf/KeeloqLib/README.md similarity index 100% rename from lib_rf/KeeloqLib/README.md rename to lib/lib_rf/KeeloqLib/README.md diff --git a/lib_rf/KeeloqLib/keywords.txt b/lib/lib_rf/KeeloqLib/keywords.txt similarity index 100% rename from lib_rf/KeeloqLib/keywords.txt rename to lib/lib_rf/KeeloqLib/keywords.txt diff --git a/lib_rf/KeeloqLib/library.properties b/lib/lib_rf/KeeloqLib/library.properties similarity index 100% rename from lib_rf/KeeloqLib/library.properties rename to lib/lib_rf/KeeloqLib/library.properties diff --git a/lib_rf/KeeloqLib/src/KeeloqLib.cpp b/lib/lib_rf/KeeloqLib/src/KeeloqLib.cpp similarity index 100% rename from lib_rf/KeeloqLib/src/KeeloqLib.cpp rename to lib/lib_rf/KeeloqLib/src/KeeloqLib.cpp diff --git a/lib_rf/KeeloqLib/src/KeeloqLib.h b/lib/lib_rf/KeeloqLib/src/KeeloqLib.h similarity index 100% rename from lib_rf/KeeloqLib/src/KeeloqLib.h rename to lib/lib_rf/KeeloqLib/src/KeeloqLib.h diff --git a/lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino b/lib/lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino similarity index 100% rename from lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino rename to lib/lib_rf/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino diff --git a/lib_rf/RF24/.gitignore b/lib/lib_rf/RF24/.gitignore similarity index 100% rename from lib_rf/RF24/.gitignore rename to lib/lib_rf/RF24/.gitignore diff --git a/lib_rf/RF24/CONTRIBUTING.md b/lib/lib_rf/RF24/CONTRIBUTING.md similarity index 100% rename from lib_rf/RF24/CONTRIBUTING.md rename to lib/lib_rf/RF24/CONTRIBUTING.md diff --git a/lib_rf/RF24/Doxyfile b/lib/lib_rf/RF24/Doxyfile similarity index 100% rename from lib_rf/RF24/Doxyfile rename to lib/lib_rf/RF24/Doxyfile diff --git a/lib_rf/RF24/LICENSE b/lib/lib_rf/RF24/LICENSE similarity index 100% rename from lib_rf/RF24/LICENSE rename to lib/lib_rf/RF24/LICENSE diff --git a/lib_rf/RF24/Makefile b/lib/lib_rf/RF24/Makefile similarity index 100% rename from lib_rf/RF24/Makefile rename to lib/lib_rf/RF24/Makefile diff --git a/lib_rf/RF24/README.md b/lib/lib_rf/RF24/README.md similarity index 100% rename from lib_rf/RF24/README.md rename to lib/lib_rf/RF24/README.md diff --git a/lib_rf/RF24/RF24.cpp b/lib/lib_rf/RF24/RF24.cpp similarity index 100% rename from lib_rf/RF24/RF24.cpp rename to lib/lib_rf/RF24/RF24.cpp diff --git a/lib_rf/RF24/RF24.h b/lib/lib_rf/RF24/RF24.h similarity index 100% rename from lib_rf/RF24/RF24.h rename to lib/lib_rf/RF24/RF24.h diff --git a/lib_rf/RF24/RF24_config.h b/lib/lib_rf/RF24/RF24_config.h similarity index 100% rename from lib_rf/RF24/RF24_config.h rename to lib/lib_rf/RF24/RF24_config.h diff --git a/lib_rf/RF24/configure b/lib/lib_rf/RF24/configure similarity index 100% rename from lib_rf/RF24/configure rename to lib/lib_rf/RF24/configure diff --git a/lib_rf/RF24/doxygen-custom.css b/lib/lib_rf/RF24/doxygen-custom.css similarity index 100% rename from lib_rf/RF24/doxygen-custom.css rename to lib/lib_rf/RF24/doxygen-custom.css diff --git a/lib_rf/RF24/examples/GettingStarted/GettingStarted.ino b/lib/lib_rf/RF24/examples/GettingStarted/GettingStarted.ino similarity index 100% rename from lib_rf/RF24/examples/GettingStarted/GettingStarted.ino rename to lib/lib_rf/RF24/examples/GettingStarted/GettingStarted.ino diff --git a/lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino b/lib/lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino similarity index 100% rename from lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino rename to lib/lib_rf/RF24/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino diff --git a/lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino b/lib/lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino similarity index 100% rename from lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino rename to lib/lib_rf/RF24/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino diff --git a/lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino b/lib/lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino similarity index 100% rename from lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino rename to lib/lib_rf/RF24/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino diff --git a/lib_rf/RF24/examples/Transfer/Transfer.ino b/lib/lib_rf/RF24/examples/Transfer/Transfer.ino similarity index 100% rename from lib_rf/RF24/examples/Transfer/Transfer.ino rename to lib/lib_rf/RF24/examples/Transfer/Transfer.ino diff --git a/lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino b/lib/lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino similarity index 100% rename from lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino rename to lib/lib_rf/RF24/examples/TransferTimeouts/TransferTimeouts.ino diff --git a/lib_rf/RF24/examples/Usage/led_remote/Jamfile b/lib/lib_rf/RF24/examples/Usage/led_remote/Jamfile similarity index 100% rename from lib_rf/RF24/examples/Usage/led_remote/Jamfile rename to lib/lib_rf/RF24/examples/Usage/led_remote/Jamfile diff --git a/lib_rf/RF24/examples/Usage/led_remote/led_remote.pde b/lib/lib_rf/RF24/examples/Usage/led_remote/led_remote.pde similarity index 100% rename from lib_rf/RF24/examples/Usage/led_remote/led_remote.pde rename to lib/lib_rf/RF24/examples/Usage/led_remote/led_remote.pde diff --git a/lib_rf/RF24/examples/Usage/nordic_fob/Jamfile b/lib/lib_rf/RF24/examples/Usage/nordic_fob/Jamfile similarity index 100% rename from lib_rf/RF24/examples/Usage/nordic_fob/Jamfile rename to lib/lib_rf/RF24/examples/Usage/nordic_fob/Jamfile diff --git a/lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde b/lib/lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde similarity index 100% rename from lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde rename to lib/lib_rf/RF24/examples/Usage/nordic_fob/nordic_fob.pde diff --git a/lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile b/lib/lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile similarity index 100% rename from lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile rename to lib/lib_rf/RF24/examples/Usage/pingpair_maple/Jamfile diff --git a/lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp b/lib/lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp similarity index 100% rename from lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp rename to lib/lib_rf/RF24/examples/Usage/pingpair_maple/main.cpp diff --git a/lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde b/lib/lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde similarity index 100% rename from lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde rename to lib/lib_rf/RF24/examples/Usage/pingpair_maple/pingpair_maple.pde diff --git a/lib_rf/RF24/examples/Usage/readme.md b/lib/lib_rf/RF24/examples/Usage/readme.md similarity index 100% rename from lib_rf/RF24/examples/Usage/readme.md rename to lib/lib_rf/RF24/examples/Usage/readme.md diff --git a/lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino b/lib/lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino rename to lib/lib_rf/RF24/examples/pingpair_ack/pingpair_ack.ino diff --git a/lib_rf/RF24/examples/pingpair_dyn/Jamfile b/lib/lib_rf/RF24/examples/pingpair_dyn/Jamfile similarity index 100% rename from lib_rf/RF24/examples/pingpair_dyn/Jamfile rename to lib/lib_rf/RF24/examples/pingpair_dyn/Jamfile diff --git a/lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino b/lib/lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino rename to lib/lib_rf/RF24/examples/pingpair_dyn/pingpair_dyn.ino diff --git a/lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino b/lib/lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino rename to lib/lib_rf/RF24/examples/pingpair_irq/pingpair_irq.ino diff --git a/lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino b/lib/lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino rename to lib/lib_rf/RF24/examples/pingpair_irq_simple/pingpair_irq_simple.ino diff --git a/lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile b/lib/lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile similarity index 100% rename from lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile rename to lib/lib_rf/RF24/examples/pingpair_multi_dyn/Jamfile diff --git a/lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino b/lib/lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino rename to lib/lib_rf/RF24/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino diff --git a/lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino b/lib/lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino similarity index 100% rename from lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino rename to lib/lib_rf/RF24/examples/pingpair_sleepy/pingpair_sleepy.ino diff --git a/lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino b/lib/lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino similarity index 100% rename from lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino rename to lib/lib_rf/RF24/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino diff --git a/lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino b/lib/lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino similarity index 100% rename from lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino rename to lib/lib_rf/RF24/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino diff --git a/lib_rf/RF24/examples/scanner/Jamfile b/lib/lib_rf/RF24/examples/scanner/Jamfile similarity index 100% rename from lib_rf/RF24/examples/scanner/Jamfile rename to lib/lib_rf/RF24/examples/scanner/Jamfile diff --git a/lib_rf/RF24/examples/scanner/scanner.ino b/lib/lib_rf/RF24/examples/scanner/scanner.ino similarity index 100% rename from lib_rf/RF24/examples/scanner/scanner.ino rename to lib/lib_rf/RF24/examples/scanner/scanner.ino diff --git a/lib_rf/RF24/examples/starping/Jamfile b/lib/lib_rf/RF24/examples/starping/Jamfile similarity index 100% rename from lib_rf/RF24/examples/starping/Jamfile rename to lib/lib_rf/RF24/examples/starping/Jamfile diff --git a/lib_rf/RF24/examples/starping/starping.pde b/lib/lib_rf/RF24/examples/starping/starping.pde similarity index 100% rename from lib_rf/RF24/examples/starping/starping.pde rename to lib/lib_rf/RF24/examples/starping/starping.pde diff --git a/lib_rf/RF24/examples_linux/Makefile.examples b/lib/lib_rf/RF24/examples_linux/Makefile.examples similarity index 100% rename from lib_rf/RF24/examples_linux/Makefile.examples rename to lib/lib_rf/RF24/examples_linux/Makefile.examples diff --git a/lib_rf/RF24/examples_linux/extra/Makefile b/lib/lib_rf/RF24/examples_linux/extra/Makefile similarity index 100% rename from lib_rf/RF24/examples_linux/extra/Makefile rename to lib/lib_rf/RF24/examples_linux/extra/Makefile diff --git a/lib_rf/RF24/examples_linux/extra/rpi-hub.cpp b/lib/lib_rf/RF24/examples_linux/extra/rpi-hub.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/extra/rpi-hub.cpp rename to lib/lib_rf/RF24/examples_linux/extra/rpi-hub.cpp diff --git a/lib_rf/RF24/examples_linux/extra/scanner.cpp b/lib/lib_rf/RF24/examples_linux/extra/scanner.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/extra/scanner.cpp rename to lib/lib_rf/RF24/examples_linux/extra/scanner.cpp diff --git a/lib_rf/RF24/examples_linux/gettingstarted.cpp b/lib/lib_rf/RF24/examples_linux/gettingstarted.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/gettingstarted.cpp rename to lib/lib_rf/RF24/examples_linux/gettingstarted.cpp diff --git a/lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp b/lib/lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp rename to lib/lib_rf/RF24/examples_linux/gettingstarted_call_response.cpp diff --git a/lib_rf/RF24/examples_linux/interrupts/Makefile b/lib/lib_rf/RF24/examples_linux/interrupts/Makefile similarity index 100% rename from lib_rf/RF24/examples_linux/interrupts/Makefile rename to lib/lib_rf/RF24/examples_linux/interrupts/Makefile diff --git a/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp b/lib/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp rename to lib/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int.cpp diff --git a/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp b/lib/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp rename to lib/lib_rf/RF24/examples_linux/interrupts/gettingstarted_call_response_int2.cpp diff --git a/lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp b/lib/lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp rename to lib/lib_rf/RF24/examples_linux/interrupts/pingpair_dyn_int.cpp diff --git a/lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp b/lib/lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp rename to lib/lib_rf/RF24/examples_linux/interrupts/transfer_interrupt.cpp diff --git a/lib_rf/RF24/examples_linux/pingpair_dyn.cpp b/lib/lib_rf/RF24/examples_linux/pingpair_dyn.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/pingpair_dyn.cpp rename to lib/lib_rf/RF24/examples_linux/pingpair_dyn.cpp diff --git a/lib_rf/RF24/examples_linux/pingpair_dyn.py b/lib/lib_rf/RF24/examples_linux/pingpair_dyn.py similarity index 100% rename from lib_rf/RF24/examples_linux/pingpair_dyn.py rename to lib/lib_rf/RF24/examples_linux/pingpair_dyn.py diff --git a/lib_rf/RF24/examples_linux/readme.md b/lib/lib_rf/RF24/examples_linux/readme.md similarity index 100% rename from lib_rf/RF24/examples_linux/readme.md rename to lib/lib_rf/RF24/examples_linux/readme.md diff --git a/lib_rf/RF24/examples_linux/transfer.cpp b/lib/lib_rf/RF24/examples_linux/transfer.cpp similarity index 100% rename from lib_rf/RF24/examples_linux/transfer.cpp rename to lib/lib_rf/RF24/examples_linux/transfer.cpp diff --git a/lib_rf/RF24/keywords.txt b/lib/lib_rf/RF24/keywords.txt similarity index 100% rename from lib_rf/RF24/keywords.txt rename to lib/lib_rf/RF24/keywords.txt diff --git a/lib_rf/RF24/library.json b/lib/lib_rf/RF24/library.json similarity index 100% rename from lib_rf/RF24/library.json rename to lib/lib_rf/RF24/library.json diff --git a/lib_rf/RF24/library.properties b/lib/lib_rf/RF24/library.properties similarity index 100% rename from lib_rf/RF24/library.properties rename to lib/lib_rf/RF24/library.properties diff --git a/lib_rf/RF24/nRF24L01.h b/lib/lib_rf/RF24/nRF24L01.h similarity index 100% rename from lib_rf/RF24/nRF24L01.h rename to lib/lib_rf/RF24/nRF24L01.h diff --git a/lib_rf/RF24/printf.h b/lib/lib_rf/RF24/printf.h similarity index 100% rename from lib_rf/RF24/printf.h rename to lib/lib_rf/RF24/printf.h diff --git a/lib_rf/RF24/pyRF24/crossunixccompiler.py b/lib/lib_rf/RF24/pyRF24/crossunixccompiler.py similarity index 100% rename from lib_rf/RF24/pyRF24/crossunixccompiler.py rename to lib/lib_rf/RF24/pyRF24/crossunixccompiler.py diff --git a/lib_rf/RF24/pyRF24/pyRF24.cpp b/lib/lib_rf/RF24/pyRF24/pyRF24.cpp similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24.cpp rename to lib/lib_rf/RF24/pyRF24/pyRF24.cpp diff --git a/lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py b/lib/lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py rename to lib/lib_rf/RF24/pyRF24/pyRF24/crossunixccompiler.py diff --git a/lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp b/lib/lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp rename to lib/lib_rf/RF24/pyRF24/pyRF24/pyRF24.cpp diff --git a/lib_rf/RF24/pyRF24/pyRF24/readme.md b/lib/lib_rf/RF24/pyRF24/pyRF24/readme.md similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24/readme.md rename to lib/lib_rf/RF24/pyRF24/pyRF24/readme.md diff --git a/lib_rf/RF24/pyRF24/pyRF24/setup.py b/lib/lib_rf/RF24/pyRF24/pyRF24/setup.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24/setup.py rename to lib/lib_rf/RF24/pyRF24/pyRF24/setup.py diff --git a/lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py b/lib/lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py rename to lib/lib_rf/RF24/pyRF24/pyRF24Mesh/example_master.py diff --git a/lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp b/lib/lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp rename to lib/lib_rf/RF24/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp diff --git a/lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py b/lib/lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py rename to lib/lib_rf/RF24/pyRF24/pyRF24Mesh/setup.py diff --git a/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py b/lib/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py rename to lib/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_rx.py diff --git a/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py b/lib/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py rename to lib/lib_rf/RF24/pyRF24/pyRF24Network/examples/helloworld_tx.py diff --git a/lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp b/lib/lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp rename to lib/lib_rf/RF24/pyRF24/pyRF24Network/pyRF24Network.cpp diff --git a/lib_rf/RF24/pyRF24/pyRF24Network/setup.py b/lib/lib_rf/RF24/pyRF24/pyRF24Network/setup.py similarity index 100% rename from lib_rf/RF24/pyRF24/pyRF24Network/setup.py rename to lib/lib_rf/RF24/pyRF24/pyRF24Network/setup.py diff --git a/lib_rf/RF24/pyRF24/readme.md b/lib/lib_rf/RF24/pyRF24/readme.md similarity index 100% rename from lib_rf/RF24/pyRF24/readme.md rename to lib/lib_rf/RF24/pyRF24/readme.md diff --git a/lib_rf/RF24/pyRF24/setup.py b/lib/lib_rf/RF24/pyRF24/setup.py similarity index 100% rename from lib_rf/RF24/pyRF24/setup.py rename to lib/lib_rf/RF24/pyRF24/setup.py diff --git a/lib_rf/RF24/tests/README b/lib/lib_rf/RF24/tests/README similarity index 100% rename from lib_rf/RF24/tests/README rename to lib/lib_rf/RF24/tests/README diff --git a/lib_rf/RF24/tests/native/Jamfile b/lib/lib_rf/RF24/tests/native/Jamfile similarity index 100% rename from lib_rf/RF24/tests/native/Jamfile rename to lib/lib_rf/RF24/tests/native/Jamfile diff --git a/lib_rf/RF24/tests/native/pingpair_irq.pde b/lib/lib_rf/RF24/tests/native/pingpair_irq.pde similarity index 100% rename from lib_rf/RF24/tests/native/pingpair_irq.pde rename to lib/lib_rf/RF24/tests/native/pingpair_irq.pde diff --git a/lib_rf/RF24/tests/native/printf.h b/lib/lib_rf/RF24/tests/native/printf.h similarity index 100% rename from lib_rf/RF24/tests/native/printf.h rename to lib/lib_rf/RF24/tests/native/printf.h diff --git a/lib_rf/RF24/tests/pingpair_blocking/Jamfile b/lib/lib_rf/RF24/tests/pingpair_blocking/Jamfile similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/Jamfile rename to lib/lib_rf/RF24/tests/pingpair_blocking/Jamfile diff --git a/lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde b/lib/lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde rename to lib/lib_rf/RF24/tests/pingpair_blocking/pingpair_blocking.pde diff --git a/lib_rf/RF24/tests/pingpair_blocking/printf.h b/lib/lib_rf/RF24/tests/pingpair_blocking/printf.h similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/printf.h rename to lib/lib_rf/RF24/tests/pingpair_blocking/printf.h diff --git a/lib_rf/RF24/tests/pingpair_blocking/runtest.py b/lib/lib_rf/RF24/tests/pingpair_blocking/runtest.py similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/runtest.py rename to lib/lib_rf/RF24/tests/pingpair_blocking/runtest.py diff --git a/lib_rf/RF24/tests/pingpair_blocking/runtests.sh b/lib/lib_rf/RF24/tests/pingpair_blocking/runtests.sh similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/runtests.sh rename to lib/lib_rf/RF24/tests/pingpair_blocking/runtests.sh diff --git a/lib_rf/RF24/tests/pingpair_blocking/test.ex b/lib/lib_rf/RF24/tests/pingpair_blocking/test.ex similarity index 100% rename from lib_rf/RF24/tests/pingpair_blocking/test.ex rename to lib/lib_rf/RF24/tests/pingpair_blocking/test.ex diff --git a/lib_rf/RF24/tests/pingpair_test/Jamfile b/lib/lib_rf/RF24/tests/pingpair_test/Jamfile similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/Jamfile rename to lib/lib_rf/RF24/tests/pingpair_test/Jamfile diff --git a/lib_rf/RF24/tests/pingpair_test/pingpair_test.pde b/lib/lib_rf/RF24/tests/pingpair_test/pingpair_test.pde similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/pingpair_test.pde rename to lib/lib_rf/RF24/tests/pingpair_test/pingpair_test.pde diff --git a/lib_rf/RF24/tests/pingpair_test/printf.h b/lib/lib_rf/RF24/tests/pingpair_test/printf.h similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/printf.h rename to lib/lib_rf/RF24/tests/pingpair_test/printf.h diff --git a/lib_rf/RF24/tests/pingpair_test/runtest.py b/lib/lib_rf/RF24/tests/pingpair_test/runtest.py similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/runtest.py rename to lib/lib_rf/RF24/tests/pingpair_test/runtest.py diff --git a/lib_rf/RF24/tests/pingpair_test/runtests.sh b/lib/lib_rf/RF24/tests/pingpair_test/runtests.sh similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/runtests.sh rename to lib/lib_rf/RF24/tests/pingpair_test/runtests.sh diff --git a/lib_rf/RF24/tests/pingpair_test/test.ex b/lib/lib_rf/RF24/tests/pingpair_test/test.ex similarity index 100% rename from lib_rf/RF24/tests/pingpair_test/test.ex rename to lib/lib_rf/RF24/tests/pingpair_test/test.ex diff --git a/lib_rf/RF24/utility/ATTiny/RF24_arch_config.h b/lib/lib_rf/RF24/utility/ATTiny/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/ATTiny/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/ATTiny/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/ATTiny/spi.h b/lib/lib_rf/RF24/utility/ATTiny/spi.h similarity index 100% rename from lib_rf/RF24/utility/ATTiny/spi.h rename to lib/lib_rf/RF24/utility/ATTiny/spi.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/README.md b/lib/lib_rf/RF24/utility/ATXMegaD3/README.md similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/README.md rename to lib/lib_rf/RF24/utility/ATXMegaD3/README.md diff --git a/lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h b/lib/lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/compatibility.c b/lib/lib_rf/RF24/utility/ATXMegaD3/compatibility.c similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/compatibility.c rename to lib/lib_rf/RF24/utility/ATXMegaD3/compatibility.c diff --git a/lib_rf/RF24/utility/ATXMegaD3/compatibility.h b/lib/lib_rf/RF24/utility/ATXMegaD3/compatibility.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/compatibility.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/compatibility.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/gpio.cpp b/lib/lib_rf/RF24/utility/ATXMegaD3/gpio.cpp similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/gpio.cpp rename to lib/lib_rf/RF24/utility/ATXMegaD3/gpio.cpp diff --git a/lib_rf/RF24/utility/ATXMegaD3/gpio.h b/lib/lib_rf/RF24/utility/ATXMegaD3/gpio.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/gpio.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/gpio.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c b/lib/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c rename to lib/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.c diff --git a/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h b/lib/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/gpio_helper.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/includes.h b/lib/lib_rf/RF24/utility/ATXMegaD3/includes.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/includes.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/includes.h diff --git a/lib_rf/RF24/utility/ATXMegaD3/spi.cpp b/lib/lib_rf/RF24/utility/ATXMegaD3/spi.cpp similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/spi.cpp rename to lib/lib_rf/RF24/utility/ATXMegaD3/spi.cpp diff --git a/lib_rf/RF24/utility/ATXMegaD3/spi.h b/lib/lib_rf/RF24/utility/ATXMegaD3/spi.h similarity index 100% rename from lib_rf/RF24/utility/ATXMegaD3/spi.h rename to lib/lib_rf/RF24/utility/ATXMegaD3/spi.h diff --git a/lib_rf/RF24/utility/Due/RF24_arch_config.h b/lib/lib_rf/RF24/utility/Due/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/Due/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/Due/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/LittleWire/RF24_arch_config.h b/lib/lib_rf/RF24/utility/LittleWire/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/LittleWire/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/LittleWire/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/LittleWire/includes.h b/lib/lib_rf/RF24/utility/LittleWire/includes.h similarity index 100% rename from lib_rf/RF24/utility/LittleWire/includes.h rename to lib/lib_rf/RF24/utility/LittleWire/includes.h diff --git a/lib_rf/RF24/utility/MRAA/RF24_arch_config.h b/lib/lib_rf/RF24/utility/MRAA/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/MRAA/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/MRAA/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/MRAA/compatibility.c b/lib/lib_rf/RF24/utility/MRAA/compatibility.c similarity index 100% rename from lib_rf/RF24/utility/MRAA/compatibility.c rename to lib/lib_rf/RF24/utility/MRAA/compatibility.c diff --git a/lib_rf/RF24/utility/MRAA/compatibility.h b/lib/lib_rf/RF24/utility/MRAA/compatibility.h similarity index 100% rename from lib_rf/RF24/utility/MRAA/compatibility.h rename to lib/lib_rf/RF24/utility/MRAA/compatibility.h diff --git a/lib_rf/RF24/utility/MRAA/gpio.cpp b/lib/lib_rf/RF24/utility/MRAA/gpio.cpp similarity index 100% rename from lib_rf/RF24/utility/MRAA/gpio.cpp rename to lib/lib_rf/RF24/utility/MRAA/gpio.cpp diff --git a/lib_rf/RF24/utility/MRAA/gpio.h b/lib/lib_rf/RF24/utility/MRAA/gpio.h similarity index 100% rename from lib_rf/RF24/utility/MRAA/gpio.h rename to lib/lib_rf/RF24/utility/MRAA/gpio.h diff --git a/lib_rf/RF24/utility/MRAA/includes.h b/lib/lib_rf/RF24/utility/MRAA/includes.h similarity index 100% rename from lib_rf/RF24/utility/MRAA/includes.h rename to lib/lib_rf/RF24/utility/MRAA/includes.h diff --git a/lib_rf/RF24/utility/MRAA/spi.cpp b/lib/lib_rf/RF24/utility/MRAA/spi.cpp similarity index 100% rename from lib_rf/RF24/utility/MRAA/spi.cpp rename to lib/lib_rf/RF24/utility/MRAA/spi.cpp diff --git a/lib_rf/RF24/utility/MRAA/spi.h b/lib/lib_rf/RF24/utility/MRAA/spi.h similarity index 100% rename from lib_rf/RF24/utility/MRAA/spi.h rename to lib/lib_rf/RF24/utility/MRAA/spi.h diff --git a/lib_rf/RF24/utility/RPi/RF24_arch_config.h b/lib/lib_rf/RF24/utility/RPi/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/RPi/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/RPi/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/RPi/bcm2835.c b/lib/lib_rf/RF24/utility/RPi/bcm2835.c similarity index 100% rename from lib_rf/RF24/utility/RPi/bcm2835.c rename to lib/lib_rf/RF24/utility/RPi/bcm2835.c diff --git a/lib_rf/RF24/utility/RPi/bcm2835.h b/lib/lib_rf/RF24/utility/RPi/bcm2835.h similarity index 100% rename from lib_rf/RF24/utility/RPi/bcm2835.h rename to lib/lib_rf/RF24/utility/RPi/bcm2835.h diff --git a/lib_rf/RF24/utility/RPi/includes.h b/lib/lib_rf/RF24/utility/RPi/includes.h similarity index 100% rename from lib_rf/RF24/utility/RPi/includes.h rename to lib/lib_rf/RF24/utility/RPi/includes.h diff --git a/lib_rf/RF24/utility/RPi/interrupt.c b/lib/lib_rf/RF24/utility/RPi/interrupt.c similarity index 100% rename from lib_rf/RF24/utility/RPi/interrupt.c rename to lib/lib_rf/RF24/utility/RPi/interrupt.c diff --git a/lib_rf/RF24/utility/RPi/interrupt.h b/lib/lib_rf/RF24/utility/RPi/interrupt.h similarity index 100% rename from lib_rf/RF24/utility/RPi/interrupt.h rename to lib/lib_rf/RF24/utility/RPi/interrupt.h diff --git a/lib_rf/RF24/utility/RPi/spi.cpp b/lib/lib_rf/RF24/utility/RPi/spi.cpp similarity index 100% rename from lib_rf/RF24/utility/RPi/spi.cpp rename to lib/lib_rf/RF24/utility/RPi/spi.cpp diff --git a/lib_rf/RF24/utility/RPi/spi.h b/lib/lib_rf/RF24/utility/RPi/spi.h similarity index 100% rename from lib_rf/RF24/utility/RPi/spi.h rename to lib/lib_rf/RF24/utility/RPi/spi.h diff --git a/lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h b/lib/lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/SPIDEV/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/SPIDEV/compatibility.c b/lib/lib_rf/RF24/utility/SPIDEV/compatibility.c similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/compatibility.c rename to lib/lib_rf/RF24/utility/SPIDEV/compatibility.c diff --git a/lib_rf/RF24/utility/SPIDEV/compatibility.h b/lib/lib_rf/RF24/utility/SPIDEV/compatibility.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/compatibility.h rename to lib/lib_rf/RF24/utility/SPIDEV/compatibility.h diff --git a/lib_rf/RF24/utility/SPIDEV/gpio.cpp b/lib/lib_rf/RF24/utility/SPIDEV/gpio.cpp similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/gpio.cpp rename to lib/lib_rf/RF24/utility/SPIDEV/gpio.cpp diff --git a/lib_rf/RF24/utility/SPIDEV/gpio.h b/lib/lib_rf/RF24/utility/SPIDEV/gpio.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/gpio.h rename to lib/lib_rf/RF24/utility/SPIDEV/gpio.h diff --git a/lib_rf/RF24/utility/SPIDEV/includes.h b/lib/lib_rf/RF24/utility/SPIDEV/includes.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/includes.h rename to lib/lib_rf/RF24/utility/SPIDEV/includes.h diff --git a/lib_rf/RF24/utility/SPIDEV/interrupt.c b/lib/lib_rf/RF24/utility/SPIDEV/interrupt.c similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/interrupt.c rename to lib/lib_rf/RF24/utility/SPIDEV/interrupt.c diff --git a/lib_rf/RF24/utility/SPIDEV/interrupt.h b/lib/lib_rf/RF24/utility/SPIDEV/interrupt.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/interrupt.h rename to lib/lib_rf/RF24/utility/SPIDEV/interrupt.h diff --git a/lib_rf/RF24/utility/SPIDEV/spi.cpp b/lib/lib_rf/RF24/utility/SPIDEV/spi.cpp similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/spi.cpp rename to lib/lib_rf/RF24/utility/SPIDEV/spi.cpp diff --git a/lib_rf/RF24/utility/SPIDEV/spi.h b/lib/lib_rf/RF24/utility/SPIDEV/spi.h similarity index 100% rename from lib_rf/RF24/utility/SPIDEV/spi.h rename to lib/lib_rf/RF24/utility/SPIDEV/spi.h diff --git a/lib_rf/RF24/utility/Teensy/RF24_arch_config.h b/lib/lib_rf/RF24/utility/Teensy/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/Teensy/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/Teensy/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/Template/RF24_arch_config.h b/lib/lib_rf/RF24/utility/Template/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/Template/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/Template/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/Template/compatibility.h b/lib/lib_rf/RF24/utility/Template/compatibility.h similarity index 100% rename from lib_rf/RF24/utility/Template/compatibility.h rename to lib/lib_rf/RF24/utility/Template/compatibility.h diff --git a/lib_rf/RF24/utility/Template/gpio.h b/lib/lib_rf/RF24/utility/Template/gpio.h similarity index 100% rename from lib_rf/RF24/utility/Template/gpio.h rename to lib/lib_rf/RF24/utility/Template/gpio.h diff --git a/lib_rf/RF24/utility/Template/includes.h b/lib/lib_rf/RF24/utility/Template/includes.h similarity index 100% rename from lib_rf/RF24/utility/Template/includes.h rename to lib/lib_rf/RF24/utility/Template/includes.h diff --git a/lib_rf/RF24/utility/Template/spi.h b/lib/lib_rf/RF24/utility/Template/spi.h similarity index 100% rename from lib_rf/RF24/utility/Template/spi.h rename to lib/lib_rf/RF24/utility/Template/spi.h diff --git a/lib_rf/RF24/utility/wiringPi/RF24_arch_config.h b/lib/lib_rf/RF24/utility/wiringPi/RF24_arch_config.h similarity index 100% rename from lib_rf/RF24/utility/wiringPi/RF24_arch_config.h rename to lib/lib_rf/RF24/utility/wiringPi/RF24_arch_config.h diff --git a/lib_rf/RF24/utility/wiringPi/includes.h b/lib/lib_rf/RF24/utility/wiringPi/includes.h similarity index 100% rename from lib_rf/RF24/utility/wiringPi/includes.h rename to lib/lib_rf/RF24/utility/wiringPi/includes.h diff --git a/lib_rf/RF24/utility/wiringPi/spi.cpp b/lib/lib_rf/RF24/utility/wiringPi/spi.cpp similarity index 100% rename from lib_rf/RF24/utility/wiringPi/spi.cpp rename to lib/lib_rf/RF24/utility/wiringPi/spi.cpp diff --git a/lib_rf/RF24/utility/wiringPi/spi.h b/lib/lib_rf/RF24/utility/wiringPi/spi.h similarity index 100% rename from lib_rf/RF24/utility/wiringPi/spi.h rename to lib/lib_rf/RF24/utility/wiringPi/spi.h diff --git a/lib_rf/RF24/wikidoc.xslt b/lib/lib_rf/RF24/wikidoc.xslt similarity index 100% rename from lib_rf/RF24/wikidoc.xslt rename to lib/lib_rf/RF24/wikidoc.xslt diff --git a/lib_rf/cc1101/README.md b/lib/lib_rf/cc1101/README.md similarity index 100% rename from lib_rf/cc1101/README.md rename to lib/lib_rf/cc1101/README.md diff --git a/lib_rf/cc1101/cc1101.cpp b/lib/lib_rf/cc1101/cc1101.cpp similarity index 100% rename from lib_rf/cc1101/cc1101.cpp rename to lib/lib_rf/cc1101/cc1101.cpp diff --git a/lib_rf/cc1101/cc1101.h b/lib/lib_rf/cc1101/cc1101.h similarity index 100% rename from lib_rf/cc1101/cc1101.h rename to lib/lib_rf/cc1101/cc1101.h diff --git a/lib_rf/cc1101/cc1101.h.txt b/lib/lib_rf/cc1101/cc1101.h.txt similarity index 100% rename from lib_rf/cc1101/cc1101.h.txt rename to lib/lib_rf/cc1101/cc1101.h.txt diff --git a/lib_rf/cc1101/ccpacket.h b/lib/lib_rf/cc1101/ccpacket.h similarity index 100% rename from lib_rf/cc1101/ccpacket.h rename to lib/lib_rf/cc1101/ccpacket.h diff --git a/lib_rf/cc1101/library.properties b/lib/lib_rf/cc1101/library.properties similarity index 100% rename from lib_rf/cc1101/library.properties rename to lib/lib_rf/cc1101/library.properties diff --git a/lib_rf/rc-switch/.gitignore b/lib/lib_rf/rc-switch/.gitignore similarity index 100% rename from lib_rf/rc-switch/.gitignore rename to lib/lib_rf/rc-switch/.gitignore diff --git a/lib_rf/rc-switch/README.md b/lib/lib_rf/rc-switch/README.md similarity index 100% rename from lib_rf/rc-switch/README.md rename to lib/lib_rf/rc-switch/README.md diff --git a/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino b/lib/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino similarity index 100% rename from lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino rename to lib/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino diff --git a/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino b/lib/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino similarity index 100% rename from lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino rename to lib/lib_rf/rc-switch/examples/ReceiveDemo_Advanced/output.ino diff --git a/lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino b/lib/lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino similarity index 100% rename from lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino rename to lib/lib_rf/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino diff --git a/lib_rf/rc-switch/examples/SendDemo/SendDemo.ino b/lib/lib_rf/rc-switch/examples/SendDemo/SendDemo.ino similarity index 100% rename from lib_rf/rc-switch/examples/SendDemo/SendDemo.ino rename to lib/lib_rf/rc-switch/examples/SendDemo/SendDemo.ino diff --git a/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino b/lib/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino similarity index 100% rename from lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino rename to lib/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino diff --git a/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/lib/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino similarity index 100% rename from lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino rename to lib/lib_rf/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino diff --git a/lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino b/lib/lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino similarity index 100% rename from lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino rename to lib/lib_rf/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino diff --git a/lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino b/lib/lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino similarity index 100% rename from lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino rename to lib/lib_rf/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino diff --git a/lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino b/lib/lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino similarity index 100% rename from lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino rename to lib/lib_rf/rc-switch/examples/TypeD_REV/TypeD_REV.ino diff --git a/lib_rf/rc-switch/examples/Webserver/Webserver.ino b/lib/lib_rf/rc-switch/examples/Webserver/Webserver.ino similarity index 100% rename from lib_rf/rc-switch/examples/Webserver/Webserver.ino rename to lib/lib_rf/rc-switch/examples/Webserver/Webserver.ino diff --git a/lib_rf/rc-switch/keywords.txt b/lib/lib_rf/rc-switch/keywords.txt similarity index 100% rename from lib_rf/rc-switch/keywords.txt rename to lib/lib_rf/rc-switch/keywords.txt diff --git a/lib_rf/rc-switch/library.json b/lib/lib_rf/rc-switch/library.json similarity index 100% rename from lib_rf/rc-switch/library.json rename to lib/lib_rf/rc-switch/library.json diff --git a/lib_rf/rc-switch/library.properties b/lib/lib_rf/rc-switch/library.properties similarity index 100% rename from lib_rf/rc-switch/library.properties rename to lib/lib_rf/rc-switch/library.properties diff --git a/lib_rf/rc-switch/platformio.ini b/lib/lib_rf/rc-switch/platformio.ini similarity index 100% rename from lib_rf/rc-switch/platformio.ini rename to lib/lib_rf/rc-switch/platformio.ini diff --git a/lib_rf/rc-switch/src/RCSwitch.cpp b/lib/lib_rf/rc-switch/src/RCSwitch.cpp similarity index 100% rename from lib_rf/rc-switch/src/RCSwitch.cpp rename to lib/lib_rf/rc-switch/src/RCSwitch.cpp diff --git a/lib_rf/rc-switch/src/RCSwitch.h b/lib/lib_rf/rc-switch/src/RCSwitch.h similarity index 100% rename from lib_rf/rc-switch/src/RCSwitch.h rename to lib/lib_rf/rc-switch/src/RCSwitch.h diff --git a/lib_ssl/base64-1.1.1/LICENSE b/lib/lib_ssl/base64-1.1.1/LICENSE similarity index 100% rename from lib_ssl/base64-1.1.1/LICENSE rename to lib/lib_ssl/base64-1.1.1/LICENSE diff --git a/lib_ssl/base64-1.1.1/Makefile b/lib/lib_ssl/base64-1.1.1/Makefile similarity index 100% rename from lib_ssl/base64-1.1.1/Makefile rename to lib/lib_ssl/base64-1.1.1/Makefile diff --git a/lib_ssl/base64-1.1.1/README.md b/lib/lib_ssl/base64-1.1.1/README.md similarity index 100% rename from lib_ssl/base64-1.1.1/README.md rename to lib/lib_ssl/base64-1.1.1/README.md diff --git a/lib_ssl/base64-1.1.1/catch.cpp b/lib/lib_ssl/base64-1.1.1/catch.cpp similarity index 100% rename from lib_ssl/base64-1.1.1/catch.cpp rename to lib/lib_ssl/base64-1.1.1/catch.cpp diff --git a/lib_ssl/base64-1.1.1/catch.hpp b/lib/lib_ssl/base64-1.1.1/catch.hpp similarity index 100% rename from lib_ssl/base64-1.1.1/catch.hpp rename to lib/lib_ssl/base64-1.1.1/catch.hpp diff --git a/lib_ssl/base64-1.1.1/library.properties b/lib/lib_ssl/base64-1.1.1/library.properties similarity index 100% rename from lib_ssl/base64-1.1.1/library.properties rename to lib/lib_ssl/base64-1.1.1/library.properties diff --git a/lib_ssl/base64-1.1.1/src/base64.hpp b/lib/lib_ssl/base64-1.1.1/src/base64.hpp similarity index 100% rename from lib_ssl/base64-1.1.1/src/base64.hpp rename to lib/lib_ssl/base64-1.1.1/src/base64.hpp diff --git a/lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt b/lib/lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt similarity index 100% rename from lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt rename to lib/lib_ssl/bearssl-esp8266/bearssl_esp8266-customized.txt diff --git a/lib_ssl/bearssl-esp8266/conf/esp8266.mk b/lib/lib_ssl/bearssl-esp8266/conf/esp8266.mk similarity index 100% rename from lib_ssl/bearssl-esp8266/conf/esp8266.mk rename to lib/lib_ssl/bearssl-esp8266/conf/esp8266.mk diff --git a/lib_ssl/bearssl-esp8266/library.properties b/lib/lib_ssl/bearssl-esp8266/library.properties similarity index 100% rename from lib_ssl/bearssl-esp8266/library.properties rename to lib/lib_ssl/bearssl-esp8266/library.properties diff --git a/lib_ssl/bearssl-esp8266/src/aead/ccm.c b/lib/lib_ssl/bearssl-esp8266/src/aead/ccm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/aead/ccm.c rename to lib/lib_ssl/bearssl-esp8266/src/aead/ccm.c diff --git a/lib_ssl/bearssl-esp8266/src/aead/eax.c b/lib/lib_ssl/bearssl-esp8266/src/aead/eax.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/aead/eax.c rename to lib/lib_ssl/bearssl-esp8266/src/aead/eax.c diff --git a/lib_ssl/bearssl-esp8266/src/aead/gcm.c b/lib/lib_ssl/bearssl-esp8266/src/aead/gcm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/aead/gcm.c rename to lib/lib_ssl/bearssl-esp8266/src/aead/gcm.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/ccopy.c b/lib/lib_ssl/bearssl-esp8266/src/codec/ccopy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/ccopy.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/ccopy.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec16be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec16be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec16be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec16be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec16le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec16le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec16le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec16le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec32be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec32be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec32be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec32be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec32le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec32le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec32le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec32le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec64be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec64be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec64be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec64be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/dec64le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/dec64le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/dec64le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/dec64le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc16be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc16be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc16be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc16be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc16le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc16le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc16le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc16le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc32be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc32be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc32be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc32be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc32le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc32le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc32le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc32le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc64be.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc64be.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc64be.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc64be.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/enc64le.c b/lib/lib_ssl/bearssl-esp8266/src/codec/enc64le.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/enc64le.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/enc64le.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/pemdec.c b/lib/lib_ssl/bearssl-esp8266/src/codec/pemdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/pemdec.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/pemdec.c diff --git a/lib_ssl/bearssl-esp8266/src/codec/pemenc.c b/lib/lib_ssl/bearssl-esp8266/src/codec/pemenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/codec/pemenc.c rename to lib/lib_ssl/bearssl-esp8266/src/codec/pemenc.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_all_m15.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_c25519_i15.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_curve25519.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_default.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_default.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_default.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_default.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_keygen.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_p256_m15.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_prime_i15.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_pubkey.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp256r1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp384r1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ec_secp521r1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_atr.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_asn1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_sign_raw.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_asn1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_default_vrfy_raw.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_bits.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_asn1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_sign_raw.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_asn1.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_i15_vrfy_raw.c diff --git a/lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c b/lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c rename to lib/lib_ssl/bearssl-esp8266/src/ec/ecdsa_rta.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/dig_oid.c b/lib/lib_ssl/bearssl-esp8266/src/hash/dig_oid.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/dig_oid.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/dig_oid.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/dig_size.c b/lib/lib_ssl/bearssl-esp8266/src/hash/dig_size.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/dig_size.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/dig_size.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c b/lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c b/lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul32.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c b/lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/ghash_ctmul64.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c b/lib/lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/ghash_pclmul.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/md5.c b/lib/lib_ssl/bearssl-esp8266/src/hash/md5.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/md5.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/md5.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/md5sha1.c b/lib/lib_ssl/bearssl-esp8266/src/hash/md5sha1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/md5sha1.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/md5sha1.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/mgf1.c b/lib/lib_ssl/bearssl-esp8266/src/hash/mgf1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/mgf1.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/mgf1.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/multihash.c b/lib/lib_ssl/bearssl-esp8266/src/hash/multihash.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/multihash.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/multihash.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/sha1.c b/lib/lib_ssl/bearssl-esp8266/src/hash/sha1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/sha1.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/sha1.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/sha2big.c b/lib/lib_ssl/bearssl-esp8266/src/hash/sha2big.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/sha2big.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/sha2big.c diff --git a/lib_ssl/bearssl-esp8266/src/hash/sha2small.c b/lib/lib_ssl/bearssl-esp8266/src/hash/sha2small.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/hash/sha2small.c rename to lib/lib_ssl/bearssl-esp8266/src/hash/sha2small.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_add.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_add.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_add.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_add.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_bitlen.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_decmod.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_decmod.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_decmod.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_decmod.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_decode.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_decode.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_decode.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_decode.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_decred.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_decred.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_decred.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_decred.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_encode.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_encode.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_encode.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_encode.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_fmont.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_fmont.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_fmont.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_fmont.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_iszero.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_iszero.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_iszero.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_iszero.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_moddiv.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_modpow.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_modpow.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_modpow.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_modpow.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_modpow2.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_montmul.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_montmul.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_montmul.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_montmul.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_mulacc.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_muladd.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_muladd.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_muladd.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_muladd.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_ninv15.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_reduce.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_reduce.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_reduce.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_reduce.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_rshift.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_rshift.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_rshift.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_rshift.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_sub.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_sub.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_sub.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_sub.c diff --git a/lib_ssl/bearssl-esp8266/src/int/i15_tmont.c b/lib/lib_ssl/bearssl-esp8266/src/int/i15_tmont.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/int/i15_tmont.c rename to lib/lib_ssl/bearssl-esp8266/src/int/i15_tmont.c diff --git a/lib_ssl/bearssl-esp8266/src/kdf/hkdf.c b/lib/lib_ssl/bearssl-esp8266/src/kdf/hkdf.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/kdf/hkdf.c rename to lib/lib_ssl/bearssl-esp8266/src/kdf/hkdf.c diff --git a/lib_ssl/bearssl-esp8266/src/kdf/shake.c b/lib/lib_ssl/bearssl-esp8266/src/kdf/shake.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/kdf/shake.c rename to lib/lib_ssl/bearssl-esp8266/src/kdf/shake.c diff --git a/lib_ssl/bearssl-esp8266/src/mac/hmac.c b/lib/lib_ssl/bearssl-esp8266/src/mac/hmac.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/mac/hmac.c rename to lib/lib_ssl/bearssl-esp8266/src/mac/hmac.c diff --git a/lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c b/lib/lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c rename to lib/lib_ssl/bearssl-esp8266/src/mac/hmac_ct.c diff --git a/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h b/lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h rename to lib/lib_ssl/bearssl-esp8266/src/pgmspace_bearssl.h diff --git a/lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c b/lib/lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c rename to lib/lib_ssl/bearssl-esp8266/src/rand/aesctr_drbg.c diff --git a/lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c b/lib/lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c rename to lib/lib_ssl/bearssl-esp8266/src/rand/hmac_drbg.c diff --git a/lib_ssl/bearssl-esp8266/src/rand/sysrng.c b/lib/lib_ssl/bearssl-esp8266/src/rand/sysrng.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rand/sysrng.c rename to lib/lib_ssl/bearssl-esp8266/src/rand/sysrng.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_keygen.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_modulus.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_decrypt.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_oaep_encrypt.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_sign.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pkcs1_vrfy.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_priv.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_privexp.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_sign.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pss_vrfy.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pub.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_default_pubexp.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_keygen.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_modulus.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_decrypt.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_oaep_encrypt.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_sign.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pkcs1_vrfy.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_priv.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_privexp.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_sign.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pss_vrfy.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pub.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_i15_pubexp.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_pad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_oaep_unpad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_pad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pkcs1_sig_unpad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_pad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_pss_sig_unpad.c diff --git a/lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c b/lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c rename to lib/lib_ssl/bearssl-esp8266/src/rsa/rsa_ssl_decrypt.c diff --git a/lib_ssl/bearssl-esp8266/src/settings.c b/lib/lib_ssl/bearssl-esp8266/src/settings.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/settings.c rename to lib/lib_ssl/bearssl-esp8266/src/settings.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/prf.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/prf.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/prf.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/prf.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/prf_md5sha1.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/prf_sha256.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/prf_sha384.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_ec.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_ccert_single_rsa.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_default_rsapub.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_client_full.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aescbc.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesccm.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_aesgcm.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_chapol.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_descbc.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ec.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_ecdsa.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_engine_default_rsavrfy.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hashes.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_client.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_hs_server.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_io.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_keyexport.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_lru.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_cbc.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_ccm.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_chapol.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_rec_gcm.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_ec.c diff --git a/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c b/lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c rename to lib/lib_ssl/bearssl-esp8266/src/ssl/ssl_scert_single_rsa.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctr.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_ctrcbc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_dec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_big_enc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_common.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctr.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_ctrcbc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_dec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct64_enc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctr.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_ctrcbc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_dec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_ct_enc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctr.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_ctrcbc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_dec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/aes_small_enc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_ct.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/chacha20_sse2.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_ct_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_support.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_support.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_support.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_support.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcdec.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/des_tab_cbcenc.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmul32.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_ctmulq.c diff --git a/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c b/lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c rename to lib/lib_ssl/bearssl-esp8266/src/symcipher/poly1305_i15.c diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_aead.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_block.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_block.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_block.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_block.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_ec.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_hash.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_hmac.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_kdf.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_pem.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_prf.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_rand.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_rsa.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_ssl.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_tasmota_config.h diff --git a/lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h b/lib/lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h rename to lib/lib_ssl/bearssl-esp8266/src/t_bearssl_x509.h diff --git a/lib_ssl/bearssl-esp8266/src/t_config.h b/lib/lib_ssl/bearssl-esp8266/src/t_config.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_config.h rename to lib/lib_ssl/bearssl-esp8266/src/t_config.h diff --git a/lib_ssl/bearssl-esp8266/src/t_inner.h b/lib/lib_ssl/bearssl-esp8266/src/t_inner.h similarity index 100% rename from lib_ssl/bearssl-esp8266/src/t_inner.h rename to lib/lib_ssl/bearssl-esp8266/src/t_inner.h diff --git a/lib_ssl/bearssl-esp8266/src/x509/asn1enc.c b/lib/lib_ssl/bearssl-esp8266/src/x509/asn1enc.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/asn1enc.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/asn1enc.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c b/lib/lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/encode_ec_pk8der.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c b/lib/lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/encode_ec_rawder.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c b/lib/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_pk8der.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c b/lib/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/encode_rsa_rawder.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c b/lib/lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/pkey_decoder.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c b/lib/lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/skey_decoder.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c b/lib/lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/x509_decoder.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c b/lib/lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/x509_knownkey.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c b/lib/lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/x509_minimal.c diff --git a/lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c b/lib/lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c similarity index 100% rename from lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c rename to lib/lib_ssl/bearssl-esp8266/src/x509/x509_minimal_full.c diff --git a/libesp32/ESP32-Ethernet/README.md b/lib/libesp32/ESP32-Ethernet/README.md similarity index 100% rename from libesp32/ESP32-Ethernet/README.md rename to lib/libesp32/ESP32-Ethernet/README.md diff --git a/libesp32/ESP32-Ethernet/examples/EthernetLAN_IP101/EthernetLAN_IP101.ino b/lib/libesp32/ESP32-Ethernet/examples/EthernetLAN_IP101/EthernetLAN_IP101.ino similarity index 100% rename from libesp32/ESP32-Ethernet/examples/EthernetLAN_IP101/EthernetLAN_IP101.ino rename to lib/libesp32/ESP32-Ethernet/examples/EthernetLAN_IP101/EthernetLAN_IP101.ino diff --git a/libesp32/ESP32-Ethernet/library.properties b/lib/libesp32/ESP32-Ethernet/library.properties similarity index 100% rename from libesp32/ESP32-Ethernet/library.properties rename to lib/libesp32/ESP32-Ethernet/library.properties diff --git a/libesp32/ESP32-Ethernet/src/ETH.cpp b/lib/libesp32/ESP32-Ethernet/src/ETH.cpp similarity index 100% rename from libesp32/ESP32-Ethernet/src/ETH.cpp rename to lib/libesp32/ESP32-Ethernet/src/ETH.cpp diff --git a/libesp32/ESP32-Ethernet/src/ETH.h b/lib/libesp32/ESP32-Ethernet/src/ETH.h similarity index 100% rename from libesp32/ESP32-Ethernet/src/ETH.h rename to lib/libesp32/ESP32-Ethernet/src/ETH.h diff --git a/libesp32/ESP32-Mail-Client/LICENSE b/lib/libesp32/ESP32-Mail-Client/LICENSE similarity index 100% rename from libesp32/ESP32-Mail-Client/LICENSE rename to lib/libesp32/ESP32-Mail-Client/LICENSE diff --git a/libesp32/ESP32-Mail-Client/README.md b/lib/libesp32/ESP32-Mail-Client/README.md similarity index 100% rename from libesp32/ESP32-Mail-Client/README.md rename to lib/libesp32/ESP32-Mail-Client/README.md diff --git a/libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino b/lib/libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino similarity index 100% rename from libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino rename to lib/libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino diff --git a/libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino b/lib/libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino similarity index 100% rename from libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino rename to lib/libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino diff --git a/libesp32/ESP32-Mail-Client/examples/Send_email/image.h b/lib/libesp32/ESP32-Mail-Client/examples/Send_email/image.h similarity index 100% rename from libesp32/ESP32-Mail-Client/examples/Send_email/image.h rename to lib/libesp32/ESP32-Mail-Client/examples/Send_email/image.h diff --git a/libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino b/lib/libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino similarity index 100% rename from libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino rename to lib/libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino diff --git a/libesp32/ESP32-Mail-Client/examples/Time/Time.ino b/lib/libesp32/ESP32-Mail-Client/examples/Time/Time.ino similarity index 100% rename from libesp32/ESP32-Mail-Client/examples/Time/Time.ino rename to lib/libesp32/ESP32-Mail-Client/examples/Time/Time.ino diff --git a/libesp32/ESP32-Mail-Client/keywords.txt b/lib/libesp32/ESP32-Mail-Client/keywords.txt similarity index 100% rename from libesp32/ESP32-Mail-Client/keywords.txt rename to lib/libesp32/ESP32-Mail-Client/keywords.txt diff --git a/libesp32/ESP32-Mail-Client/library.properties b/lib/libesp32/ESP32-Mail-Client/library.properties similarity index 100% rename from libesp32/ESP32-Mail-Client/library.properties rename to lib/libesp32/ESP32-Mail-Client/library.properties diff --git a/libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg b/lib/libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg similarity index 100% rename from libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg rename to lib/libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg diff --git a/libesp32/ESP32-Mail-Client/media/images/esp32-mail.png b/lib/libesp32/ESP32-Mail-Client/media/images/esp32-mail.png similarity index 100% rename from libesp32/ESP32-Mail-Client/media/images/esp32-mail.png rename to lib/libesp32/ESP32-Mail-Client/media/images/esp32-mail.png diff --git a/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp b/lib/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp rename to lib/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp diff --git a/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h b/lib/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h rename to lib/libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h diff --git a/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp b/lib/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp rename to lib/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp diff --git a/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h b/lib/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h rename to lib/libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h diff --git a/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp b/lib/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp rename to lib/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp diff --git a/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h b/lib/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h rename to lib/libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h diff --git a/libesp32/ESP32-Mail-Client/src/RFC2047.cpp b/lib/libesp32/ESP32-Mail-Client/src/RFC2047.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/RFC2047.cpp rename to lib/libesp32/ESP32-Mail-Client/src/RFC2047.cpp diff --git a/libesp32/ESP32-Mail-Client/src/RFC2047.h b/lib/libesp32/ESP32-Mail-Client/src/RFC2047.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/RFC2047.h rename to lib/libesp32/ESP32-Mail-Client/src/RFC2047.h diff --git a/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp b/lib/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp rename to lib/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp diff --git a/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h b/lib/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h rename to lib/libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h diff --git a/libesp32/ESP32-Mail-Client/src/ssl_client32.cpp b/lib/libesp32/ESP32-Mail-Client/src/ssl_client32.cpp similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ssl_client32.cpp rename to lib/libesp32/ESP32-Mail-Client/src/ssl_client32.cpp diff --git a/libesp32/ESP32-Mail-Client/src/ssl_client32.h b/lib/libesp32/ESP32-Mail-Client/src/ssl_client32.h similarity index 100% rename from libesp32/ESP32-Mail-Client/src/ssl_client32.h rename to lib/libesp32/ESP32-Mail-Client/src/ssl_client32.h diff --git a/libesp32/ESP32-to-ESP8266-compat/README.adoc b/lib/libesp32/ESP32-to-ESP8266-compat/README.adoc similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/README.adoc rename to lib/libesp32/ESP32-to-ESP8266-compat/README.adoc diff --git a/libesp32/ESP32-to-ESP8266-compat/keywords.txt b/lib/libesp32/ESP32-to-ESP8266-compat/keywords.txt similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/keywords.txt rename to lib/libesp32/ESP32-to-ESP8266-compat/keywords.txt diff --git a/libesp32/ESP32-to-ESP8266-compat/library.properties b/lib/libesp32/ESP32-to-ESP8266-compat/library.properties similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/library.properties rename to lib/libesp32/ESP32-to-ESP8266-compat/library.properties diff --git a/libesp32/ESP32-to-ESP8266-compat/src/AddrList.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/AddrList.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/AddrList.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/AddrList.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP8266HTTPClient.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266HTTPClient.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP8266HTTPClient.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266HTTPClient.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WebServer.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WebServer.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP8266WebServer.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WebServer.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP8266httpUpdate.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266httpUpdate.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP8266httpUpdate.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266httpUpdate.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ESP8266mDNS.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266mDNS.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ESP8266mDNS.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266mDNS.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/c_types.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/c_types.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/c_types.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/c_types.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/eboot_command.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/eboot_command.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/eboot_command.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/eboot_command.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp rename to lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/ets_sys.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ets_sys.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/ets_sys.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/ets_sys.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/gpio.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/gpio.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/gpio.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/gpio.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/os_type.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/os_type.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/os_type.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/os_type.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/osapi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/osapi.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/osapi.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/osapi.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/sntp.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/sntp.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/sntp.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/sntp.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/spi_flash.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/spi_flash.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/spi_flash.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/spi_flash.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/twi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/twi.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/twi.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/twi.h diff --git a/libesp32/ESP32-to-ESP8266-compat/src/user_interface.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/user_interface.h similarity index 100% rename from libesp32/ESP32-to-ESP8266-compat/src/user_interface.h rename to lib/libesp32/ESP32-to-ESP8266-compat/src/user_interface.h diff --git a/libesp32/ESP32README.md b/lib/libesp32/ESP32README.md similarity index 100% rename from libesp32/ESP32README.md rename to lib/libesp32/ESP32README.md diff --git a/libesp32/NimBLE-Arduino/CHANGELOG.md b/lib/libesp32/NimBLE-Arduino/CHANGELOG.md similarity index 100% rename from libesp32/NimBLE-Arduino/CHANGELOG.md rename to lib/libesp32/NimBLE-Arduino/CHANGELOG.md diff --git a/libesp32/NimBLE-Arduino/LICENSE b/lib/libesp32/NimBLE-Arduino/LICENSE similarity index 100% rename from libesp32/NimBLE-Arduino/LICENSE rename to lib/libesp32/NimBLE-Arduino/LICENSE diff --git a/libesp32/NimBLE-Arduino/README.md b/lib/libesp32/NimBLE-Arduino/README.md similarity index 100% rename from libesp32/NimBLE-Arduino/README.md rename to lib/libesp32/NimBLE-Arduino/README.md diff --git a/libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md b/lib/libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md similarity index 100% rename from libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md rename to lib/libesp32/NimBLE-Arduino/docs/Improvements_and_updates.md diff --git a/libesp32/NimBLE-Arduino/docs/Migration_guide.md b/lib/libesp32/NimBLE-Arduino/docs/Migration_guide.md similarity index 100% rename from libesp32/NimBLE-Arduino/docs/Migration_guide.md rename to lib/libesp32/NimBLE-Arduino/docs/Migration_guide.md diff --git a/libesp32/NimBLE-Arduino/docs/New_user_guide.md b/lib/libesp32/NimBLE-Arduino/docs/New_user_guide.md similarity index 100% rename from libesp32/NimBLE-Arduino/docs/New_user_guide.md rename to lib/libesp32/NimBLE-Arduino/docs/New_user_guide.md diff --git a/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino b/lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino rename to lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.ino diff --git a/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md b/lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md rename to lib/libesp32/NimBLE-Arduino/examples/BLE_Beacon_Scanner/BLE_Beacon_Scanner.md diff --git a/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino b/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino rename to lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.ino diff --git a/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md b/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md rename to lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneTLM_Beacon/BLE_EddystoneTLM_Beacon.md diff --git a/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino b/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino rename to lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.ino diff --git a/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md b/lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md similarity index 100% rename from libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md rename to lib/libesp32/NimBLE-Arduino/examples/BLE_EddystoneURL_Beacon/BLE_EddystoneURL_Beacon.md diff --git a/libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino b/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino rename to lib/libesp32/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino diff --git a/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino b/lib/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino rename to lib/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_client/BLE_client.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_iBeacon/BLE_iBeacon.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_notify/BLE_notify.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_scan/BLE_scan.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server/BLE_server.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_server_multiconnect/BLE_server_multiconnect.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_uart/BLE_uart.ino diff --git a/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino b/lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino similarity index 100% rename from libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino rename to lib/libesp32/NimBLE-Arduino/examples/Refactored_original_examples/BLE_write/BLE_write.ino diff --git a/libesp32/NimBLE-Arduino/library.properties b/lib/libesp32/NimBLE-Arduino/library.properties similarity index 100% rename from libesp32/NimBLE-Arduino/library.properties rename to lib/libesp32/NimBLE-Arduino/library.properties diff --git a/libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md b/lib/libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md similarity index 100% rename from libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md rename to lib/libesp32/NimBLE-Arduino/src/CODING_STANDARDS.md diff --git a/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp b/lib/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/FreeRTOS.cpp rename to lib/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp diff --git a/libesp32/NimBLE-Arduino/src/FreeRTOS.h b/lib/libesp32/NimBLE-Arduino/src/FreeRTOS.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/FreeRTOS.h rename to lib/libesp32/NimBLE-Arduino/src/FreeRTOS.h diff --git a/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h b/lib/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h rename to lib/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h diff --git a/libesp32/NimBLE-Arduino/src/HIDTypes.h b/lib/libesp32/NimBLE-Arduino/src/HIDTypes.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/HIDTypes.h rename to lib/libesp32/NimBLE-Arduino/src/HIDTypes.h diff --git a/libesp32/NimBLE-Arduino/src/NOTICE b/lib/libesp32/NimBLE-Arduino/src/NOTICE similarity index 100% rename from libesp32/NimBLE-Arduino/src/NOTICE rename to lib/libesp32/NimBLE-Arduino/src/NOTICE diff --git a/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLE2904.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLE2904.h b/lib/libesp32/NimBLE-Arduino/src/NimBLE2904.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLE2904.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLE2904.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAddress.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAddress.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAddress.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEBeacon.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h b/lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEClient.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEClient.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEClient.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEClient.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEClient.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDevice.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEDevice.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEDevice.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLELog.h b/lib/libesp32/NimBLE-Arduino/src/NimBLELog.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLELog.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLELog.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h b/lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLERemoteService.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEScan.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEScan.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEScan.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEScan.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEScan.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLESecurity.h b/lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLESecurity.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLESecurity.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEServer.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEServer.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEServer.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEServer.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEServer.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEService.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEService.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEService.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEService.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEService.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEService.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEService.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEService.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUUID.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEUUID.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEUUID.h diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp b/lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp rename to lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUtils.h b/lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/NimBLEUtils.h rename to lib/libesp32/NimBLE-Arduino/src/NimBLEUtils.h diff --git a/libesp32/NimBLE-Arduino/src/README.md b/lib/libesp32/NimBLE-Arduino/src/README.md similarity index 100% rename from libesp32/NimBLE-Arduino/src/README.md rename to lib/libesp32/NimBLE-Arduino/src/README.md diff --git a/libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md b/lib/libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md similarity index 100% rename from libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md rename to lib/libesp32/NimBLE-Arduino/src/RELEASE_NOTES.md diff --git a/libesp32/NimBLE-Arduino/src/console/console.h b/lib/libesp32/NimBLE-Arduino/src/console/console.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/console/console.h rename to lib/libesp32/NimBLE-Arduino/src/console/console.h diff --git a/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c b/lib/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c rename to lib/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c diff --git a/libesp32/NimBLE-Arduino/src/esp_compiler.h b/lib/libesp32/NimBLE-Arduino/src/esp_compiler.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/esp_compiler.h rename to lib/libesp32/NimBLE-Arduino/src/esp_compiler.h diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h b/lib/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h rename to lib/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h b/lib/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/esp_nimble_hci.h rename to lib/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h b/lib/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/esp_nimble_mem.h rename to lib/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/AUTHORS diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/LICENSE diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/README b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/README similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/README rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/README diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/VERSION diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/documentation/tinycrypt.rst diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_decrypt.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/aes_encrypt.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cbc_mode.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ccm_mode.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/cmac_mode.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_mode.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ctr_prng.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dh.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_dsa.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/ecc_platform_specific.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/hmac_prng.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/sha256.c diff --git a/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c b/lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c rename to lib/libesp32/NimBLE-Arduino/src/ext/tinycrypt/src/utils.c diff --git a/libesp32/NimBLE-Arduino/src/hal/hal_timer.h b/lib/libesp32/NimBLE-Arduino/src/hal/hal_timer.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/hal/hal_timer.h rename to lib/libesp32/NimBLE-Arduino/src/hal/hal_timer.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_att.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_att.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_att.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_att.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_eddystone.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_eddystone.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_eddystone.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_eddystone.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_gap.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_gap.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_gap.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_gap.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_gatt.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_gatt.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_gatt.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_gatt.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_adv.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_hci.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_id.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_id.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_id.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_id.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_log.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_log.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_log.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_log.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_mbuf.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_pvcy.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_hs_stop.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_ibeacon.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_l2cap.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_l2cap.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_l2cap.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_l2cap.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_monitor.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_monitor.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_monitor.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_monitor.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_sm.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_sm.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_sm.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_sm.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_store.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_store.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_store.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_store.h diff --git a/libesp32/NimBLE-Arduino/src/host/ble_uuid.h b/lib/libesp32/NimBLE-Arduino/src/host/ble_uuid.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/ble_uuid.h rename to lib/libesp32/NimBLE-Arduino/src/host/ble_uuid.h diff --git a/libesp32/NimBLE-Arduino/src/host/util/util.h b/lib/libesp32/NimBLE-Arduino/src/host/util/util.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/host/util/util.h rename to lib/libesp32/NimBLE-Arduino/src/host/util/util.h diff --git a/libesp32/NimBLE-Arduino/src/log/log.h b/lib/libesp32/NimBLE-Arduino/src/log/log.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/log/log.h rename to lib/libesp32/NimBLE-Arduino/src/log/log.h diff --git a/libesp32/NimBLE-Arduino/src/mem/mem.h b/lib/libesp32/NimBLE-Arduino/src/mem/mem.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mem/mem.h rename to lib/libesp32/NimBLE-Arduino/src/mem/mem.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/access.h b/lib/libesp32/NimBLE-Arduino/src/mesh/access.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/access.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/access.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h b/lib/libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/cfg_cli.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h b/lib/libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/cfg_srv.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/glue.h b/lib/libesp32/NimBLE-Arduino/src/mesh/glue.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/glue.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/glue.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/health_cli.h b/lib/libesp32/NimBLE-Arduino/src/mesh/health_cli.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/health_cli.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/health_cli.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/health_srv.h b/lib/libesp32/NimBLE-Arduino/src/mesh/health_srv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/health_srv.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/health_srv.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/main.h b/lib/libesp32/NimBLE-Arduino/src/mesh/main.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/main.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/main.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/mesh.h b/lib/libesp32/NimBLE-Arduino/src/mesh/mesh.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/mesh.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/mesh.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/model_cli.h b/lib/libesp32/NimBLE-Arduino/src/mesh/model_cli.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/model_cli.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/model_cli.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/model_srv.h b/lib/libesp32/NimBLE-Arduino/src/mesh/model_srv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/model_srv.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/model_srv.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/porting.h b/lib/libesp32/NimBLE-Arduino/src/mesh/porting.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/porting.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/porting.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/proxy.h b/lib/libesp32/NimBLE-Arduino/src/mesh/proxy.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/proxy.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/proxy.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/slist.h b/lib/libesp32/NimBLE-Arduino/src/mesh/slist.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/slist.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/slist.h diff --git a/libesp32/NimBLE-Arduino/src/mesh/testing.h b/lib/libesp32/NimBLE-Arduino/src/mesh/testing.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/mesh/testing.h rename to lib/libesp32/NimBLE-Arduino/src/mesh/testing.h diff --git a/libesp32/NimBLE-Arduino/src/modlog/modlog.h b/lib/libesp32/NimBLE-Arduino/src/modlog/modlog.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/modlog/modlog.h rename to lib/libesp32/NimBLE-Arduino/src/modlog/modlog.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/ble.h b/lib/libesp32/NimBLE-Arduino/src/nimble/ble.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/ble.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/ble.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h b/lib/libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/ble_hci_trans.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/hci_common.h b/lib/libesp32/NimBLE-Arduino/src/nimble/hci_common.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/hci_common.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/hci_common.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/access.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/adv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/atomic.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/beacon.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_att_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_gatt_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_hs_conn_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_coc_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/ble_l2cap_sig_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_cli.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/cfg_srv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/crypto.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/foundation.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/friend.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/glue.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_cli.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/health_srv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/light_model.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/lpn.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/mesh_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_cli.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/model_srv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/net.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/prov.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/proxy.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/settings.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/shell.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_cmd_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_att_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gatt_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_adv_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_atomic_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_conn_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_dbg_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_flow_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_hci_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_mbuf_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_periodic_sync_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_startup_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_coc_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_l2cap_sig_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_monitor_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_uuid_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/testing.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/transport.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ans/src/ble_svc_ans.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/bas/src/ble_svc_bas.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gap/src/ble_svc_gap.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/gatt/src/ble_svc_gatt.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ias/src/ble_svc_ias.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/ipss/src/ble_svc_ipss.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/lls/src/ble_svc_lls.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_hs_hci_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/services/tps/src/ble_svc_tps.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_clt.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_svr.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_eddystone.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatt_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gattc.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts_lcl.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_adv_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_atomic_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_cfg.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_dbg_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_flow_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_cmd.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_util.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_id_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_log.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mbuf_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_mqueue.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_periodic_sync_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_pvcy_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_resolv_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_shutdown.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_startup_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_stop.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_ibeacon.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_coc_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_monitor_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_alg.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_lgcy.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_sc.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_uuid_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h b/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_config_priv.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/store/ram/src/ble_store_ram.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c b/lib/libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c rename to lib/libesp32/NimBLE-Arduino/src/nimble/host/util/src/addr.c diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_npl_os.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_opt_auto.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_port.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h b/lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/nimble_port_freertos.h diff --git a/libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h b/lib/libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h rename to lib/libesp32/NimBLE-Arduino/src/nimble/npl_freertos.h diff --git a/libesp32/NimBLE-Arduino/src/nimconfig.h b/lib/libesp32/NimBLE-Arduino/src/nimconfig.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/nimconfig.h rename to lib/libesp32/NimBLE-Arduino/src/nimconfig.h diff --git a/libesp32/NimBLE-Arduino/src/os/endian.h b/lib/libesp32/NimBLE-Arduino/src/os/endian.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/endian.h rename to lib/libesp32/NimBLE-Arduino/src/os/endian.h diff --git a/libesp32/NimBLE-Arduino/src/os/os.h b/lib/libesp32/NimBLE-Arduino/src/os/os.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os.h rename to lib/libesp32/NimBLE-Arduino/src/os/os.h diff --git a/libesp32/NimBLE-Arduino/src/os/os_cputime.h b/lib/libesp32/NimBLE-Arduino/src/os/os_cputime.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os_cputime.h rename to lib/libesp32/NimBLE-Arduino/src/os/os_cputime.h diff --git a/libesp32/NimBLE-Arduino/src/os/os_error.h b/lib/libesp32/NimBLE-Arduino/src/os/os_error.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os_error.h rename to lib/libesp32/NimBLE-Arduino/src/os/os_error.h diff --git a/libesp32/NimBLE-Arduino/src/os/os_mbuf.h b/lib/libesp32/NimBLE-Arduino/src/os/os_mbuf.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os_mbuf.h rename to lib/libesp32/NimBLE-Arduino/src/os/os_mbuf.h diff --git a/libesp32/NimBLE-Arduino/src/os/os_mempool.h b/lib/libesp32/NimBLE-Arduino/src/os/os_mempool.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os_mempool.h rename to lib/libesp32/NimBLE-Arduino/src/os/os_mempool.h diff --git a/libesp32/NimBLE-Arduino/src/os/os_trace_api.h b/lib/libesp32/NimBLE-Arduino/src/os/os_trace_api.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/os_trace_api.h rename to lib/libesp32/NimBLE-Arduino/src/os/os_trace_api.h diff --git a/libesp32/NimBLE-Arduino/src/os/queue.h b/lib/libesp32/NimBLE-Arduino/src/os/queue.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/os/queue.h rename to lib/libesp32/NimBLE-Arduino/src/os/queue.h diff --git a/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c b/lib/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c rename to lib/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/include/nimble/nimble_port.h diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/endian.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/hal_timer.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/mem.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/nimble_port.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_cputime_pwr2.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mbuf.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_mempool.c diff --git a/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c b/lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c rename to lib/libesp32/NimBLE-Arduino/src/porting/nimble/src/os_msys_init.c diff --git a/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c b/lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c rename to lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/nimble_port_freertos.c diff --git a/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c b/lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c similarity index 100% rename from libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c rename to lib/libesp32/NimBLE-Arduino/src/porting/npl/freertos/src/npl_os_freertos.c diff --git a/libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h b/lib/libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h rename to lib/libesp32/NimBLE-Arduino/src/services/ans/ble_svc_ans.h diff --git a/libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h b/lib/libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h rename to lib/libesp32/NimBLE-Arduino/src/services/bas/ble_svc_bas.h diff --git a/libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h b/lib/libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h rename to lib/libesp32/NimBLE-Arduino/src/services/gap/ble_svc_gap.h diff --git a/libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h b/lib/libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h rename to lib/libesp32/NimBLE-Arduino/src/services/gatt/ble_svc_gatt.h diff --git a/libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h b/lib/libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h rename to lib/libesp32/NimBLE-Arduino/src/services/ias/ble_svc_ias.h diff --git a/libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h b/lib/libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h rename to lib/libesp32/NimBLE-Arduino/src/services/ipss/ble_svc_ipss.h diff --git a/libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h b/lib/libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h rename to lib/libesp32/NimBLE-Arduino/src/services/lls/ble_svc_lls.h diff --git a/libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h b/lib/libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h rename to lib/libesp32/NimBLE-Arduino/src/services/tps/ble_svc_tps.h diff --git a/libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h b/lib/libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h rename to lib/libesp32/NimBLE-Arduino/src/src/ble_hs_hci_priv.h diff --git a/libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h b/lib/libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h rename to lib/libesp32/NimBLE-Arduino/src/src/ble_sm_priv.h diff --git a/libesp32/NimBLE-Arduino/src/stats/stats.h b/lib/libesp32/NimBLE-Arduino/src/stats/stats.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/stats/stats.h rename to lib/libesp32/NimBLE-Arduino/src/stats/stats.h diff --git a/libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h b/lib/libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h rename to lib/libesp32/NimBLE-Arduino/src/store/config/ble_store_config.h diff --git a/libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h b/lib/libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h rename to lib/libesp32/NimBLE-Arduino/src/store/ram/ble_store_ram.h diff --git a/libesp32/NimBLE-Arduino/src/syscfg/syscfg.h b/lib/libesp32/NimBLE-Arduino/src/syscfg/syscfg.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/syscfg/syscfg.h rename to lib/libesp32/NimBLE-Arduino/src/syscfg/syscfg.h diff --git a/libesp32/NimBLE-Arduino/src/sysinit/sysinit.h b/lib/libesp32/NimBLE-Arduino/src/sysinit/sysinit.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/sysinit/sysinit.h rename to lib/libesp32/NimBLE-Arduino/src/sysinit/sysinit.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/AUTHORS diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/LICENSE diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/README b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/README similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/README rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/README diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/VERSION b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/VERSION similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/VERSION rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/VERSION diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/aes.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/aes.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/aes.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/aes.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/cbc_mode.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ccm_mode.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/cmac_mode.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/constants.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/constants.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/constants.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/constants.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_mode.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ctr_prng.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/documentation/tinycrypt.rst diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dh.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_dsa.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/ecc_platform_specific.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/hmac_prng.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/sha256.h diff --git a/libesp32/NimBLE-Arduino/src/tinycrypt/utils.h b/lib/libesp32/NimBLE-Arduino/src/tinycrypt/utils.h similarity index 100% rename from libesp32/NimBLE-Arduino/src/tinycrypt/utils.h rename to lib/libesp32/NimBLE-Arduino/src/tinycrypt/utils.h diff --git a/libesp32/TTGO_TWatch_Library/LICENSE b/lib/libesp32/TTGO_TWatch_Library/LICENSE similarity index 100% rename from libesp32/TTGO_TWatch_Library/LICENSE rename to lib/libesp32/TTGO_TWatch_Library/LICENSE diff --git a/libesp32/TTGO_TWatch_Library/README.MD b/lib/libesp32/TTGO_TWatch_Library/README.MD similarity index 100% rename from libesp32/TTGO_TWatch_Library/README.MD rename to lib/libesp32/TTGO_TWatch_Library/README.MD diff --git a/libesp32/TTGO_TWatch_Library/library.json b/lib/libesp32/TTGO_TWatch_Library/library.json similarity index 100% rename from libesp32/TTGO_TWatch_Library/library.json rename to lib/libesp32/TTGO_TWatch_Library/library.json diff --git a/libesp32/TTGO_TWatch_Library/library.properties b/lib/libesp32/TTGO_TWatch_Library/library.properties similarity index 100% rename from libesp32/TTGO_TWatch_Library/library.properties rename to lib/libesp32/TTGO_TWatch_Library/library.properties diff --git a/libesp32/TTGO_TWatch_Library/src/axp20x.cpp b/lib/libesp32/TTGO_TWatch_Library/src/axp20x.cpp similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/axp20x.cpp rename to lib/libesp32/TTGO_TWatch_Library/src/axp20x.cpp diff --git a/libesp32/TTGO_TWatch_Library/src/axp20x.h b/lib/libesp32/TTGO_TWatch_Library/src/axp20x.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/axp20x.h rename to lib/libesp32/TTGO_TWatch_Library/src/axp20x.h diff --git a/libesp32/TTGO_TWatch_Library/src/bma.cpp b/lib/libesp32/TTGO_TWatch_Library/src/bma.cpp similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma.cpp rename to lib/libesp32/TTGO_TWatch_Library/src/bma.cpp diff --git a/libesp32/TTGO_TWatch_Library/src/bma.h b/lib/libesp32/TTGO_TWatch_Library/src/bma.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma.h rename to lib/libesp32/TTGO_TWatch_Library/src/bma.h diff --git a/libesp32/TTGO_TWatch_Library/src/bma4.c b/lib/libesp32/TTGO_TWatch_Library/src/bma4.c similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma4.c rename to lib/libesp32/TTGO_TWatch_Library/src/bma4.c diff --git a/libesp32/TTGO_TWatch_Library/src/bma4.h b/lib/libesp32/TTGO_TWatch_Library/src/bma4.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma4.h rename to lib/libesp32/TTGO_TWatch_Library/src/bma4.h diff --git a/libesp32/TTGO_TWatch_Library/src/bma423.c b/lib/libesp32/TTGO_TWatch_Library/src/bma423.c similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma423.c rename to lib/libesp32/TTGO_TWatch_Library/src/bma423.c diff --git a/libesp32/TTGO_TWatch_Library/src/bma423.h b/lib/libesp32/TTGO_TWatch_Library/src/bma423.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma423.h rename to lib/libesp32/TTGO_TWatch_Library/src/bma423.h diff --git a/libesp32/TTGO_TWatch_Library/src/bma4_defs.h b/lib/libesp32/TTGO_TWatch_Library/src/bma4_defs.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/bma4_defs.h rename to lib/libesp32/TTGO_TWatch_Library/src/bma4_defs.h diff --git a/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp b/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp rename to lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp diff --git a/libesp32/TTGO_TWatch_Library/src/i2c_bus.h b/lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.h similarity index 100% rename from libesp32/TTGO_TWatch_Library/src/i2c_bus.h rename to lib/libesp32/TTGO_TWatch_Library/src/i2c_bus.h diff --git a/platformio.ini b/platformio.ini index a30214f4c..728bcafaf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -54,7 +54,7 @@ default_envs = [platformio] description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware src_dir = tasmota -lib_dir = lib +lib_dir = lib/default build_cache_dir = .cache extra_configs = platformio_tasmota32.ini platformio_tasmota_env.ini diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 299452daf..058ad1788 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -82,19 +82,19 @@ shared_libdeps_dir = lib ; *** If you dont know what it is all about, do not change lib_extra_dirs = ; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! - lib/lib_basic + lib/lib_basic ; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled - lib/lib_i2c + lib/lib_i2c ; *** Displays. Disable if you dont have any Display activated -; lib/lib_display + lib/lib_display ; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated -; lib/lib_ssl + lib/lib_ssl ; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable -; lib/lib_audio + lib/lib_audio ; *** RF 433 stuff (not RF Bridge). Recommended to disable -; lib/lib_rf + lib/lib_rf ; *** Mostly not used functions. Recommended to disable -; lib/lib_div + lib/lib_div [core] ; Activate only (one set) if you want to override the standard core defined in platformio.ini !!! diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 310124a30..6cc05dfe7 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -85,19 +85,19 @@ shared_libdeps_dir = lib ; *** If you dont know what it is all about, do not change lib_extra_dirs = ; *** ESP32 lib. ALWAYS needed for ESP32 !!! - libesp32 + lib/libesp32 ; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed! - lib_basic + lib/lib_basic ; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled - lib_i2c + lib/lib_i2c ; *** Displays. Disable if you dont have any Display activated - lib_display + lib/lib_display ; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated - lib_ssl + lib/lib_ssl ; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable - lib_audio + lib/lib_audio ; *** RF 433 stuff (not RF Bridge). Recommended to disable - lib_rf + lib/lib_rf ; *** Mostly not used functions. Recommended to disable - lib_div + lib/lib_div diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index e88e37e8a..9817fdb0f 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -43,19 +43,19 @@ lib_extra_dirs = [env:tasmota-knx] build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_extra_dirs = lib_basic, lib_div +lib_extra_dirs = lib/lib_basic, lib/lib_div [env:tasmota-sensors] build_flags = ${common.build_flags} -DFIRMWARE_SENSORS -lib_extra_dirs = lib_basic, lib_i2c, lib_rf, lib_div +lib_extra_dirs = lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div [env:tasmota-display] build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS -lib_extra_dirs = lib_basic, lib_display +lib_extra_dirs = lib/lib_basic, lib/lib_display [env:tasmota-ir] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR -lib_extra_dirs = lib_basic +lib_extra_dirs = lib/lib_basic [env:tasmota-ircustom] build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM @@ -63,7 +63,7 @@ build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_I [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE board_build.f_cpu = 160000000L -lib_extra_dirs = lib_ssl +lib_extra_dirs = lib/lib_ssl [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG diff --git a/platformio_tasmota_env.ini.new b/platformio_tasmota_env.ini.new deleted file mode 100644 index 6cee57be9..000000000 --- a/platformio_tasmota_env.ini.new +++ /dev/null @@ -1,144 +0,0 @@ -[env] -platform = ${common.platform} -platform_packages = ${common.platform_packages} -framework = ${common.framework} -board = ${common.board} -board_build.ldscript = ${common.board_build.ldscript} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_flash = ${common.board_build.f_flash} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -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} -lib_extra_dirs = ${common.shared_libdeps_dir} - -[env:tasmota] -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-minimal] -build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -lib_ignore = ${lib_minimal.lib_ignore} - -[env:tasmota-lite] -build_flags = ${common.build_flags} -DFIRMWARE_LITE -lib_ignore = ${lib_lite.lib_ignore} - -[env:tasmota-knx] -build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_ignore = ${lib_knx.lib_ignore} - -[env:tasmota-sensors] -build_flags = ${common.build_flags} -DFIRMWARE_SENSORS -lib_ignore = ${lib_sensors.lib_ignore} - -[env:tasmota-display] -build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS -lib_ignore = ${lib_display.lib_ignore} - -[env:tasmota-ir] -build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR -lib_ignore = ${lib_ir.lib_ignore} - -[env:tasmota-ircustom] -build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-zbbridge] -build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE -lib_ignore = ${lib_zbbridge.lib_ignore} - -[env:tasmota-BG] -build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-BR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_BR -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-CN] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_CN -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-CZ] -build_flags = ${common.build_flags} -DMY_LANGUAGE=cs_CZ -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-DE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=de_DE -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-ES] -build_flags = ${common.build_flags} -DMY_LANGUAGE=es_ES -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-FR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=fr_FR -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-GR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=el_GR -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-HE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=he_HE -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-HU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=hu_HU -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-IT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=it_IT -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-KO] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ko_KO -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-NL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=nl_NL -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-PL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pl_PL -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-PT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt_PT -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-RO] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ro_RO -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-RU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ru_RU -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-SE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sv_SE -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-SK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sk_SK -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-TR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=tr_TR -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-TW] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh_TW -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-UK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=uk_UA -lib_ignore = ${lib_Tasmota.lib_ignore} - -[env:tasmota-VN] -build_flags = ${common.build_flags} -DMY_LANGUAGE=vi_VN -lib_ignore = ${lib_Tasmota.lib_ignore} diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index cb42e1e72..58eb34a4a 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -32,37 +32,37 @@ extends = env:tasmota32 board = esp32cam board_build.f_cpu = 240000000L build_flags = ${common32.build_flags} -DFIRMWARE_WEBCAM -lib_extra_dirs = libesp32, lib_basic +lib_extra_dirs = lib/libesp32, lib/lib_basic [env:tasmota32-minimal] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_MINIMAL -lib_extra_dirs = libesp32 +lib_extra_dirs = lib/libesp32 [env:tasmota32-lite] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_LITE -lib_extra_dirs = libesp32 +lib_extra_dirs = lib/libesp32 [env:tasmota32-knx] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_KNX_NO_EMULATION -lib_extra_dirs = libesp32, lib_basic, lib_div +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_div [env:tasmota32-sensors] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_SENSORS -lib_extra_dirs = libesp32, lib_basic, lib_i2c, lib_rf, lib_div +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div [env:tasmota32-display] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_DISPLAYS -lib_extra_dirs = libesp32, lib_basic, lib_display +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_display [env:tasmota32-ir] extends = env:tasmota32 build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR -lib_extra_dirs = libesp32, lib_basic +lib_extra_dirs = lib/libesp32, lib/lib_basic [env:tasmota32-ircustom] extends = env:tasmota32 diff --git a/tasmota/tasmota.ino.cpp b/tasmota/tasmota.ino.cpp new file mode 100644 index 000000000..b3dc46cc3 --- /dev/null +++ b/tasmota/tasmota.ino.cpp @@ -0,0 +1,115375 @@ +# 1 "/tmp/tmpjvshbmyn" +#include +# 1 "/workspace/Tasmota/tasmota/tasmota.ino" +# 37 "/workspace/Tasmota/tasmota/tasmota.ino" +#include +#include "tasmota_compat.h" +#include "tasmota_version.h" +#include "tasmota.h" +#include "my_user_config.h" +#ifdef USE_TLS + #include +#endif +#include "tasmota_globals.h" +#include "i18n.h" +#include "tasmota_template.h" + + +#include +#include +#include +#include +#include +#ifdef USE_ARDUINO_OTA + #include + #ifndef USE_DISCOVERY + #define USE_DISCOVERY + #endif +#endif +#ifdef USE_DISCOVERY + #include +#endif + + #include + +#ifdef USE_SPI + #include +#endif + + +#include "settings.h" + + + + + +WiFiUDP PortUdp; + +unsigned long feature_drv1; +unsigned long feature_drv2; +unsigned long feature_sns1; +unsigned long feature_sns2; +unsigned long feature5; +unsigned long feature6; +unsigned long feature7; +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 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 blinks = 201; +uint32_t uptime = 0; +uint32_t loop_load_avg = 0; +uint32_t global_update = 0; +uint32_t web_log_index = 1; +uint32_t baudrate = APP_BAUDRATE; +float global_temperature_celsius = NAN; +float global_humidity = 0.0f; +float global_pressure_hpa = 0.0f; +uint16_t tele_period = 9999; +uint16_t blink_counter = 0; +uint16_t seriallog_timer = 0; +uint16_t syslog_timer = 0; +uint16_t gpio_pin[MAX_GPIO_PIN] = { 0 }; +int16_t save_data_counter; +RulesBitfield rules_flag; +uint8_t mqtt_cmnd_blocked = 0; +uint8_t mqtt_cmnd_blocked_reset = 0; +uint8_t state_250mS = 0; +uint8_t latching_relay_pulse = 0; +uint8_t ssleep; +uint8_t blinkspeed = 1; +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_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 masterlog_level = 0; +uint8_t seriallog_level; +uint8_t syslog_level; +uint8_t my_module_type; +uint8_t last_source = 0; +uint8_t shutters_present = 0; +uint8_t prepped_loglevel = 0; + +bool serial_local = false; +bool serial_buffer_overrun = 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 is_8285 = false; +bool skip_light_fade; +bool restart_halt = false; +myio my_module; +StateBitfield global_state; +char my_version[33]; +char my_image[33]; +char my_hostname[33]; +char mqtt_client[TOPSZ]; +char mqtt_topic[TOPSZ]; +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 +void setup(void); +void BacklogLoop(void); +void SleepDelay(uint32_t mseconds); +void loop(void); +uint16_t SendMail(char *buffer); +void xsend_message_txt(char *msg); +void attach_File(char *path); +void attach_Array(char *aname); +uint16_t SendMail(char *buffer); +void attach_Array(char *aname); +void send_message_txt(char *txt); +uint32_t GetRtcSettingsCrc(void); +void RtcSettingsSave(void); +void RtcSettingsLoad(void); +bool RtcSettingsValid(void); +uint32_t GetRtcRebootCrc(void); +void RtcRebootSave(void); +void RtcRebootReset(void); +void RtcRebootLoad(void); +bool RtcRebootValid(void); +void SetFlashModeDout(void); +bool VersionCompatible(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); +void UpdateQuickPowerCycle(bool update); +uint32_t GetSettingsTextLen(void); +bool SettingsUpdateFinished(void); +bool SettingsUpdateText(uint32_t index, const char* replace_me); +char* SettingsText(uint32_t index); +void UpdateBackwardCompatibility(void); +uint32_t GetSettingsAddress(void); +void SettingsSave(uint8_t rotate); +void SettingsLoad(void); +void EspErase(uint32_t start_sector, uint32_t end_sector); +void SettingsErase(uint8_t type); +void SettingsSdkErase(void); +void SettingsDefault(void); +void SettingsDefaultSet1(void); +void SettingsDefaultSet2(void); +void SettingsResetStd(void); +void SettingsResetDst(void); +void SettingsDefaultWebColor(void); +void SettingsEnableAllI2cDrivers(void); +void SettingsDelta(void); +void OsWatchTicker(void); +void OsWatchInit(void); +void OsWatchLoop(void); +bool OsWatchBlockedLoop(void); +uint32_t ResetReason(void); +String GetResetReason(void); +String GetBinary8(uint8_t value, size_t count); +size_t strchrspn(const char *str1, int character); +uint32_t ChrCount(const char *str, const char *delim); +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* RemoveControlCharacter(char* p); +char* ReplaceCommaWithDot(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); +void SetShortcutDefault(void); +uint8_t Shortcut(void); +bool ValidIpAddress(const char* str); +bool ParseIp(uint32_t* addr, const char* str); +uint32_t ParseParameters(uint32_t count, uint32_t *params); +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); +void GetEspHardwareType(void); +String GetDeviceHardware(void); +float ConvertTemp(float c); +float ConvertTempToCelsius(float c); +char TempUnit(void); +float ConvertHumidity(float h); +float CalcTempHumToDew(float t, float h); +float ConvertPressure(float p); +String PressureUnit(void); +float ConvertSpeed(float s); +String SpeedUnit(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); +String GetSerialConfig(void); +void SetSerialBegin(void); +void SetSerialConfig(uint32_t serial_config); +void SetSerialBaudrate(uint32_t ubaudrate); +void SetSerial(uint32_t ubaudrate, uint32_t serial_config); +void ClaimSerial(void); +void SerialSendRaw(char *codes); +void SerialSendDecimal(char *values); +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 ResponseAppendTHD(float f_temperature, float f_humidity); +int ResponseJsonEnd(void); +int ResponseJsonEndEnd(void); +uint16_t GpioConvert(uint8_t gpio); +uint16_t Adc0Convert(uint8_t adc0); +void TemplateConvert(uint8_t template8[], uint16_t template16[]); +void ConvertGpios(void); +uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index); +bool PinUsed(uint32_t gpio, uint32_t index); +uint32_t GetPin(uint32_t lpin); +void SetPin(uint32_t lpin, uint32_t gpio); +void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state); +uint8_t ModuleNr(void); +bool ValidTemplateModule(uint32_t index); +bool ValidModule(uint32_t index); +bool ValidTemplate(const char *search); +String AnyModuleName(uint32_t index); +String ModuleName(void); +void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option); +void ModuleGpios(myio *gp); +gpio_flag ModuleFlag(void); +void ModuleDefault(uint32_t module); +void SetModuleType(void); +bool FlashPin(uint32_t pin); +uint32_t ValidPin(uint32_t pin, uint32_t gpio); +bool ValidGPIO(uint32_t pin, uint32_t gpio); +bool GetUsedInModule(uint32_t val, uint16_t *arr); +bool JsonTemplate(char* dataBuf); +void TemplateJson(void); +inline int32_t TimeDifference(uint32_t prev, uint32_t next); +int32_t TimePassedSince(uint32_t timestamp); +bool TimeReached(uint32_t timer); +void SetNextTimeInterval(unsigned long& timer, const unsigned long step); +int32_t TimePassedSinceUsec(uint32_t timestamp); +bool TimeReachedUsec(uint32_t timer); +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); +void I2cSetActiveFound(uint32_t addr, const char *types); +bool I2cActive(uint32_t addr); +bool I2cSetDevice(uint32_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 PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...); +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(const char *sensor, uint32_t misses); +void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size); +String Decompress(const char * compressed, size_t uncompressed_size); +uint32_t HwRandom(void); +void ButtonPullupFlag(uint8 button_bit); +void ButtonInvertFlag(uint8 button_bit); +void ButtonTouchFlag(uint8 button_bit); +void ButtonInit(void); +uint8_t ButtonSerial(uint8_t serial_in_byte); +void ButtonHandler(void); +void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold); +void ButtonLoop(void); +void ResponseCmndNumber(int value); +void ResponseCmndFloat(float value, uint32_t decimals); +void ResponseCmndIdxNumber(int value); +void ResponseCmndChar_P(const char* value); +void ResponseCmndChar(const char* value); +void ResponseCmndStateText(uint32_t value); +void ResponseCmndDone(void); +void ResponseCmndIdxChar(const char* value); +void ResponseCmndAll(uint32_t text_index, uint32_t count); +void ExecuteCommand(const char *cmnd, uint32_t source); +void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len); +void CmndBacklog(void); +void CmndDelay(void); +void CmndPower(void); +void CmndStatus(void); +void CmndState(void); +void CmndTempOffset(void); +void CmndHumOffset(void); +void CmndGlobalTemp(void); +void CmndGlobalHum(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 CmndSpeedUnit(void); +void CmndModule(void); +void CmndModules(void); +void CmndGpio(void); +void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines); +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 CmndSerialConfig(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 CmndWifi(void); +void CmndDevicename(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 CmndLedPwmOff(void); +void CmndLedPwmOn(void); +void CmndLedPwmMode(void); +void CmndWifiPower(void); +void CmndI2cScan(void); +void CmndI2cDriver(void); +void CmndDevGroupName(void); +void CmndDevGroupSend(void); +void CmndDevGroupShare(void); +void CmndDevGroupStatus(void); +void CmndSensor(void); +void CmndDriver(void); +void CmndCpuFrequency(void); +void CmndTouchCal(void); +void CmndTouchThres(void); +void CmndTouchNum(void); +void resetPins(); +void HwWdtDisable(void); +void HwWdtEnable(void); +void WdtDisable(void); +void WdtEnable(void); +void CmndCrash(void); +void CmndWDT(void); +void CmndBlockedLoop(void); +void CrashDumpClear(void); +bool CrashFlag(void); +void CrashDump(void); +bool DeviceGroupItemShared(bool incoming, uint8_t item); +void DeviceGroupsInit(void); +void DeviceGroupsStart(); +void DeviceGroupsStop(); +void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received); +bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...); +void ProcessDeviceGroupMessage(uint8_t * message, int message_length); +void DeviceGroupStatus(uint8_t device_group_index); +void DeviceGroupsLoop(void); +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff); +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff); +uint32_t eeprom_init(uint32_t size); +uint32_t eeprom_init(uint32_t size); +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff); +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff); +uint32_t eeprom_init(uint32_t size); +void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf); +void eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf); +uint32_t ESP_ResetInfoReason(void); +String ESP_getResetReason(void); +uint32_t ESP_getChipId(void); +uint32_t ESP_getSketchSize(void); +uint32_t ESP_getFreeHeap(void); +uint32_t ESP_getMaxAllocHeap(void); +void ESP_Restart(void); +void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen); +void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen); +void NvmErase(const char *sNvsName); +void SettingsErase(uint8_t type); +void SettingsRead(void *data, size_t size); +void SettingsWrite(const void *pSettings, unsigned nSettingsLen); +void QPCRead(void *pSettings, unsigned nSettingsLen); +void QPCWrite(const void *pSettings, unsigned nSettingsLen); +void ZigbeeErase(void); +void ZigbeeRead(void *pSettings, unsigned nSettingsLen); +void ZigbeeWrite(const void *pSettings, unsigned nSettingsLen); +void SntpInit(); +uint32_t SntpGetCurrentTimestamp(void); +void CrashDump(void); +bool CrashFlag(void); +void CrashDumpClear(void); +void CmndCrash(void); +void CmndWDT(void); +void CmndBlockedLoop(void); +void DisableBrownout(void); +String ESP32GetResetReason(uint32_t cpu_no); +String ESP_getResetReason(void); +uint32_t ESP_ResetInfoReason(void); +uint32_t ESP_getChipId(void); +uint32_t ESP_getSketchSize(void); +uint32_t ESP_getFreeHeap(void); +uint32_t ESP_getMaxAllocHeap(void); +void ESP_Restart(void); +static bool spiflash_is_ready(void); +static void spi_write_enable(void); +bool EsptoolEraseSector(uint32_t sector); +void EsptoolErase(uint32_t start_sector, uint32_t end_sector); +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); +float ModulusRangef(float f, float a, float b); +float Polynomialf(const float *factors, uint32_t degree, float x); +static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len); +static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); +void createBitmapFileHeader(uint32_t height, uint32_t width, uint8_t *fileHeader); +void createBitmapInfoHeader(uint32_t height, uint32_t width, uint8_t *infoHeader ); +void StartMdns(void); +void MqttDiscoverServer(void); +void MdnsAddServiceHttp(void); +void MdnsUpdate(void); +char* NetworkHostname(void); +IPAddress NetworkAddress(void); +String NetworkMacAddress(void); +bool RotaryButtonPressed(uint32_t button_index); +void ICACHE_RAM_ATTR RotaryIsrArgMiDesk(void *arg); +void ICACHE_RAM_ATTR RotaryIsrArg(void *arg); +void RotaryInit(void); +void RotaryHandler(void); +uint32_t UtcTime(void); +uint32_t LocalTime(void); +uint32_t Midnight(void); +bool MidnightNow(void); +bool IsDst(void); +String GetBuildDateAndTime(void); +String GetMinuteTime(uint32_t minutes); +String GetTimeZone(void); +String GetDuration(uint32_t time); +String GetDT(uint32_t time); +String GetDateAndTime(uint8_t time_type); +uint32_t UpTime(void); +uint32_t MinutesUptime(void); +String GetUptime(void); +uint32_t MinutesPastMidnight(void); +uint32_t RtcMillis(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); +bool equalsSBuffer(const class SBuffer * buf1, const class SBuffer * buf2); +String GetStatistics(void); +String GetStatistics(void); +void SwitchPullupFlag(uint16 switch_bit); +void SwitchSetVirtual(uint32_t index, uint8_t state); +uint8_t SwitchGetVirtual(uint32_t index); +uint8_t SwitchLastState(uint32_t index); +bool SwitchState(uint32_t index); +void SwitchProbe(void); +void SwitchInit(void); +void SwitchHandler(uint8_t mode); +void SwitchLoop(void); +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* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic); +char* GetFallbackTopic_P(char *stopic, 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 SetPowerOnState(void); +void UpdateLedPowerAll(); +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); +void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperature, float f_humidity); +bool MqttShowSensor(void); +void MqttPublishSensor(void); +void PerformEverySecond(void); +void Every100mSeconds(void); +void Every250mSeconds(void); +void ArduinoOTAInit(void); +void ArduinoOtaLoop(void); +void SerialInput(void); +void ResetPwm(void); +void GpioInit(void); +bool UdpDisconnect(void); +bool UdpConnect(void); +void PollUdp(void); +int WifiGetRssiAsQuality(int rssi); +bool WifiConfigCounter(void); +void WifiConfig(uint8_t type); +void WifiSetMode(WiFiMode_t wifi_mode); +void WiFiSetSleepMode(void); +void WifiBegin(uint8_t flag, uint8_t channel); +void WifiBeginAfterScan(void); +uint16_t WifiLinkCount(void); +String WifiDowntime(void); +void WifiSetState(uint8_t state); +bool WifiCheckIPv6(void); +String WifiGetIPv6(void); +bool WifiCheckIPAddrStatus(void); +void WifiCheckIp(void); +void WifiCheck(uint8_t param); +int WifiState(void); +String WifiGetOutputPower(void); +void WifiSetOutputPower(void); +void WifiConnect(void); +void EspRestart(void); +void stationKeepAliveNow(void); +void wifiKeepAlive(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 HttpHeaderCors(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); +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 WSContentSend_THD(const char *types, float f_temperature, float f_humidity); +void WSContentEnd(void); +void WSContentStop(void); +void WebRestart(uint32_t type); +void HandleWifiLogin(void); +void WebSliderColdWarm(void); +void HandleRoot(void); +bool HandleRootStatusRefresh(void); +int32_t IsShutterWebButton(uint32_t idx); +void HandleConfiguration(void); +void WSContentSendNiceLists(uint32_t option); +void WSContentSendAdcNiceList(uint32_t option); +void HandleTemplateConfiguration(void); +uint16_t WebGetGpioArg(uint32_t i); +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); +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); +void CmndWebButton(void); +void CmndCors(void); +bool Xdrv01(uint8_t function); +bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); +void MakeValidMqtt(uint32_t option, char* str); +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 MqttDumpData(char* topic, char* data, uint32_t data_len); +void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len); +void MqttRetryCounter(uint8_t value); +void MqttSubscribe(const char *topic); +void MqttUnsubscribe(const char *topic); +void MqttPublishLogging(const char *mxtime); +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 MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained); +void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic); +void MqttPublishTeleSensor(void); +void MqttPublishPowerState(uint32_t device); +void MqttPublishAllPowerState(void); +void MqttPublishPowerBlinkState(uint32_t device); +uint16_t MqttConnectCount(void); +void MqttDisconnected(int state); +void MqttConnected(void); +void MqttReconnect(void); +void MqttCheck(void); +bool KeyTopicActive(uint32_t key); +void CmndMqttFingerprint(void); +void CmndMqttUser(void); +void CmndMqttPassword(void); +void CmndMqttlog(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); +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); +void EnergyCommandCalResponse(uint32_t nvalue); +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 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 mat3x3(const float *mat33, const float *vec3, float *res3); +uint16_t change8to10(uint8_t v); +uint8_t change10to8(uint16_t v); +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr); +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr); +uint16_t ledGamma10_10(uint16_t v); +uint16_t ledGamma10(uint8_t v); +uint8_t ledGamma(uint8_t v); +void LightPwmOffset(uint32_t offset); +bool LightModuleInit(void); +void LightCalcPWMRange(void); +void LightInit(void); +void LightUpdateColorMapping(void); +uint8_t LightGetDimmer(uint8_t dimmer); +void LightSetDimmer(uint8_t dimmer); +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri); +void LightGetXY(float *X, float *Y); +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); +uint8_t LightGetBri(uint8_t device); +void LightSetBri(uint8_t device, uint8_t bri); +void LightColorOffset(int32_t offset); +bool LightColorTempOffset(int32_t offset); +void LightSetColorTemp(uint16_t ct); +uint16_t LightGetColorTemp(void); +void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); +void LightPowerOn(void); +void ResponseLightState(uint8_t append); +void LightSetPaletteEntry(void); +void LightCycleColor(int8_t direction); +void LightSetPower(void); +void LightAnimate(void); +bool isChannelGammaCorrected(uint32_t channel); +bool isChannelCT(uint32_t channel); +uint16_t fadeGamma(uint32_t channel, uint16_t v); +uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg); +bool LightApplyFade(void); +void LightApplyPower(uint8_t new_color[LST_MAX], power_t power); +void LightSetOutputs(const uint16_t *cur_col_10); +void calcGammaMultiChannels(uint16_t cur_col_10[5]); +void calcGammaBulbs(uint16_t cur_col_10[5]); +void LightSendDeviceGroupStatus(bool status); +void LightHandleDevGroupItem(void); +bool LightColorEntry(char *buffer, uint32_t buffer_length); +void CmndSupportColor(void); +void CmndColor(void); +void CmndWhite(void); +void CmndChannel(void); +void CmndHsbColor(void); +void CmndScheme(void); +void CmndWakeup(void); +void CmndColorTemperature(void); +void LightDimmerOffset(uint32_t index, int32_t offset); +void CmndDimmer(void); +void CmndDimmerRange(void); +void CmndLedTable(void); +void CmndRgbwwTable(void); +void CmndFade(void); +void CmndSpeed(void); +void CmndWakeupDuration(void); +void CmndPalette(void); +void CmndSequenceOffset(void); +void CmndUndocA(void); +bool Xdrv04(uint8_t function); +void IrSendInit(void); +void IrReceiveUpdateThreshold(void); +void IrReceiveInit(void); +void IrReceiveCheck(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); +void IrReceiveInit(void); +String sendIRJsonState(const struct decode_results &results); +void IrReceiveCheck(void); +String listSupportedProtocols(bool hvac); +bool strToBool(class JsonParserToken token, bool def); +uint32_t IrRemoteCmndIrHvacJson(void); +void CmndIrHvac(void); +uint32_t IrRemoteCmndIrSendJson(void); +uint32_t IrRemoteSendGC(char ** pp, uint32_t count, uint32_t repeat); +uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat); +uint32_t IrRemoteParseRawCompact(char * str, uint16_t * arr, size_t arr_len); +uint32_t IrRemoteSendRawStandard(char ** pp, uint32_t count, uint32_t repeat); +uint16_t parsqeFreq(char * str); +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); +void DomoticzUpdateFanState(void); +void MqttPublishDomoticzPowerState(uint8_t device); +void DomoticzUpdatePowerState(uint8_t device); +void DomoticzMqttUpdate(void); +void DomoticzMqttSubscribe(void); +bool DomoticzMqttData(void); +void DomoticzSendSwitch(uint32_t type, uint32_t index, uint32_t state); +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); +void DomoticzSendData(uint32_t sensor_idx, uint32_t idx, char *data); +void DomoticzSensor(uint8_t idx, char *data); +uint8_t DomoticzHumidityState(float h); +void DomoticzSensor(uint8_t idx, uint32_t value); +void DomoticzTempHumPressureSensor(float temp, float hum, float 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 CmndDomoticzSend(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); +uint32_t JulianDate(const struct TIME_T &now); +float InPi(float x); +float TimeFormula(float *DK, uint32_t Tdays); +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); +inline bool IsRuleUncompressed(uint32_t idx); +inline bool IsRuleEmpty(uint32_t idx); +size_t GetRuleLen(uint32_t idx); +size_t GetRuleLenStorage(uint32_t idx); +void GetRule_decompress(String &rule, const char *rule_head); +String GetRule(uint32_t idx); +int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, size_t out_len); +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all_rules); +int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); +void RulesVarReplace(String &commands, const String &sfind, const String &replace); +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(void); +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 Script_ticker1_end(void); +void Script_ticker2_end(void); +void Script_ticker3_end(void); +void Script_ticker4_end(void); +void SaveFile(const char *name, const uint8_t *buf, uint32_t len); +void LoadFile(const char *name, uint8_t *buf, uint32_t len); +void f2char(float num, uint32_t dprec, uint32_t lzeros, char *nbuff); +void ScriptEverySecond(void); +void RulesTeleperiod(void); +int16_t Init_Scripter(void); +uint32_t get_fsinfo(uint32_t sel); +void form1000(uint32_t number, char *dp, char sc); +void Restart_globvars(void); +void Script_Stop_UDP(void); +void Script_Init_UDP(); +void Script_PollUdp(void); +void script_udp_sendvar(char *vname,float *fp,char *sp); +void ws2812_set_array(float *array ,uint32_t len, uint32_t offset); +float median_array(float *array, uint16_t len); +float Get_MFVal(uint8_t index, int16_t bind); +void Set_MFVal(uint8_t index, uint16_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); +void ICACHE_RAM_ATTR MP_Timer(void); +uint32_t MeasurePulseTime(int32_t in); +uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind); +uint16_t GetStack(void); +uint16_t GetStack(void); +void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_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); +void esp32_beep(int32_t freq ,uint32_t len); +int16_t Run_Scripter(const char *type, int8_t tlen, char *js); +int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo); +void ScripterEvery100ms(void); +void Scripter_save_pvars(void); +void script_upload_start(void); +void ScriptExecuteUploadSuccess(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 SaveScript(void); +void ScriptSaveSettings(void); +void SaveScriptEnd(void); +void Script_HueStatus(String *response, uint16_t hue_devs); +void Script_Check_Hue(String *response); +void Script_Handle_Hue(String *path); +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 ScriptGetSDCard(void); +void SendFile(char *fname); +void ScriptFullWebpage(void); +void Script_Check_HTML_Setvars(void); +void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); +void ScriptWebShow(char mc); +void ScriptJsonAppend(void); +bool RulesProcessEvent(char *json_event); +void script_task1(void *arg); +void script_task2(void *arg); +uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio); +void script_task1(void *arg); +void script_task2(void *arg); +uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio); +uint32_t call2https(const char *host, const char *path); +void cpy2lf(char *dst, uint32_t dstlen, char *src); +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(void); +void KnxSensor(uint8_t sensor_type, float value); +void HandleKNXConfiguration(void); +void KNX_Save_Settings(void); +void CmndKnxTxCmnd(void); +void CmndKnxTxVal(void); +void CmndKnxTxScene(void); +void CmndKnxEnabled(void); +void CmndKnxEnhanced(void); +void CmndKnxPa(void); +void CmndKnxGa(void); +void CmndKnxCb(void); +bool Xdrv11(uint8_t function); +void HassDiscoveryRelays(struct HASS &Hass); +void NewHAssDiscovery(void); +void TryResponseAppend_P(const char *format, ...); +void HAssAnnounceRelayLight(void); +void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold, uint8_t single, uint8_t trg_start, uint8_t trg_end); +void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint8_t toggle, uint8_t pir); +void HAssAnnounceSwitches(void); +void HAssAnnounceButtons(void); +void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, bool nested, const char* SubKey); +void HAssAnnounceSensors(void); +void HAssAnnounceShutters(void); +void HAssAnnounceDeviceInfoAndStatusSensor(void); +void HAssPublishStatus(void); +void HAssDiscovery(void); +void HAssDiscover(void); +void HAssAnyKey(void); +bool HAssMqttLWT(void); +void HassLwtSubscribe(bool hasslwt); +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); +uint32_t 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 Touch_Init(TwoWire &i2c); +uint32_t Touch_Status(uint32_t sel); +void Touch_MQTT(uint8_t index, const char *cp); +void Touch_RDW_BUTT(uint32_t count, uint32_t pwr); +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); +bool IsModuleTuya(void); +bool AsModuleTuyaMS(void); +bool IsTuyaFanCtrl(void); +bool TuyaModeSet(void); +uint8_t TuyaFanSpeeds(void); +uint8_t TuyaFanState(void); +void CmndTuyaSend(void); +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); +void TuyaSendEnum(uint8_t id, uint32_t value); +void TuyaSendString(uint8_t id, char data[]); +bool TuyaSetPower(void); +bool TuyaSetChannels(void); +void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx); +void TuyaRequestState(uint8_t state_type); +void TuyaResetWifi(void); +void TuyaProcessStatePacket(void); +void TuyaLowPowerModePacketProcess(void); +void TuyaHandleProductInfoPacket(void); +void TuyaSendLowPowerSuccessIfNeeded(void); +void TuyaNormalPowerModePacketProcess(void); +bool TuyaModuleSelected(void); +void TuyaInit(void); +void TuyaSerialInput(void); +bool TuyaButtonPressed(void); +uint8_t TuyaGetTuyaWifiState(void); +void TuyaSetWifiLed(void); +void TuyaSetTime(void); +bool Xnrg32(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 PS16DZSerialSend(const char *tx_buffer); +void PS16DZSerialSendOk(void); +void PS16DZSerialSendUpdateCommand(void); +void PS16DZSerialInput(void); +bool PS16DZSerialSendUpdateCommandIfRequired(void); +void PS16DZInit(void); +bool PS16DZModuleSelected(void); +bool Xdrv19(uint8_t function); +String HueBridgeId(void); +String HueSerialnumber(void); +String HueUuid(void); +void HueRespondToMSearch(void); +String GetHueDeviceId(uint16_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); +bool HueActive(uint8_t device); +void HueLightStatus2(uint8_t device, String *response); +inline uint32_t findEchoGeneration(void); +void HueGlobalConfig(String *path); +void HueAuthentication(String *path); +void CheckHue(String * response, bool &appending); +void HueLightsCommand(uint8_t device, uint32_t device_id, String &response); +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 LogUpnpWithClient(const char *msg); +void HandleUpnpEvent(void); +void HandleUpnpService(void); +void HandleUpnpMetaService(void); +void HandleUpnpSetupWemo(void); +bool Xdrv21(uint8_t function); +bool IsModuleIfan(void); +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); +String getZDPStatusMessage(uint8_t status); +String getEmberStatus(uint8_t status); +String getZigbeeStatusMessage(uint8_t status); +int strcmp_PP(const char *p1, const char *p2); +uint16_t Z_GetLastDevice(void); +uint16_t Z_GetLastGroup(void); +uint16_t Z_GetLastCluster(void); +uint8_t Z_GetLastEndpoint(void); +void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response); +void HueLightStatus2Zigbee(uint16_t shortaddr, String *response); +void ZigbeeHueStatus(String * response, uint16_t shortaddr); +void ZigbeeCheckHue(String * response, bool &appending); +void ZigbeeHueGroups(String * lights); +void ZigbeeHuePower(uint16_t shortaddr, bool power); +void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer); +void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct); +void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y); +void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat); +void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response); +class SBuffer hibernateDevice(const struct Z_Device &device); +class SBuffer hibernateDevices(void); +void hydrateDevices(const SBuffer &buf); +void loadZigbeeDevices(void); +void saveZigbeeDevices(void); +void eraseZigbeeDevices(void); +uint8_t Z_getDatatypeLen(uint8_t t); +bool Z_isDiscreteDataType(uint8_t t); +uint16_t CxToCluster(uint8_t cx); +uint8_t ClusterToCx(uint16_t cluster); +int8_t CmToMultiplier(uint8_t cm); +const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t attr_id, + uint8_t *attr_type, int8_t *multiplier); +uint8_t toPercentageCR2032(uint32_t voltage); +int32_t encodeSingleAttribute(class SBuffer &buf, double val_d, const char *val_str, uint8_t attrtype); +void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +bool Z_parseAttributeKey(class Z_attribute & attr); +void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +inline bool isXYZ(char c); +inline int8_t hexValue(char c); +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz); +void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload); +bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf); +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd); +inline char hexDigit(uint32_t h); +String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z); +uint32_t ZigbeeAliasOrNumber(const char *state_text); +void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h); +void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, int8_t zb_txradio_dbm); +uint8_t ZigbeeGetInstructionSize(uint8_t instr); +void ZigbeeGotoLabel(uint8_t label); +void ZigbeeStateMachine_Run(void); +int32_t ZigbeeProcessInput(class SBuffer &buf); +uint8_t ZNP_RSSI2Lqi(int8_t rssi); +int32_t EZ_RSTACK(uint8_t reset_code); +int32_t EZ_ERROR(uint8_t error_code); +int32_t EZ_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf); +int32_t EZ_GetEUI64(int32_t res, class SBuffer &buf); +int32_t EZ_GetNodeId(int32_t res, class SBuffer &buf); +int32_t EZ_NetworkParameters(int32_t res, class SBuffer &buf); +int32_t EZ_CheckKeyNWK(int32_t res, class SBuffer &buf); +int32_t EZ_RouteError(int32_t res, const class SBuffer &buf); +int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf); +void Z_PermitJoinDisable(void); +int32_t EZ_MessageSent(int32_t res, const class SBuffer &buf); +int32_t Z_EZSPGetEUI64(int32_t res, class SBuffer &buf); +int32_t Z_EZSPGetNodeId(int32_t res, class SBuffer &buf); +int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf); +int32_t ZNP_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); +int32_t ZNP_CheckNVWrite(int32_t res, class SBuffer &buf); +int32_t ZNP_Reboot(int32_t res, class SBuffer &buf); +int32_t ZNP_ReceiveCheckVersion(int32_t res, class SBuffer &buf); +int32_t EZ_ReceiveCheckVersion(int32_t res, class SBuffer &buf); +int32_t EZ_Set_ResetConfig(uint8_t value); +int32_t EZ_GotoIfResetConfig(uint8_t value); +int32_t Z_SwitchDeviceType(int32_t res, class SBuffer &buf); +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); +int32_t ZNP_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf); +int32_t ZNP_ReceiveNodeDesc(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf); +int32_t Z_ClusterToCxBinding(uint16_t cluster); +void Z_AutoBindDefer(uint16_t shortaddr, uint8_t endpoint, const SBuffer &buf, + size_t in_index, size_t in_len, size_t out_index, size_t out_len); +int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf); +int32_t ZNP_DataConfirm(int32_t res, const class SBuffer &buf); +int32_t ZNP_ReceiveStateChange(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); +int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf); +int32_t Z_BindRsp(int32_t res, const class SBuffer &buf); +int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf); +int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf); +int32_t EZ_ParentAnnceRsp(int32_t res, const class SBuffer &buf, bool rsp); +void Z_SendIEEEAddrReq(uint16_t shortaddr); +void Z_SendActiveEpReq(uint16_t shortaddr); +void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +void Z_SendDeviceInfoRequest(uint16_t shortaddr); +void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf); +void Z_IncomingMessage(class ZCLFrame &zcl_received); +void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len); +int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf); +int32_t EZ_Reset_Device(uint8_t value); +int32_t EZ_Recv_Default(int32_t res, const class SBuffer &buf); +void Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +int32_t ZNP_Reset_Device(uint8_t value); +int32_t ZNP_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); +int32_t ZNP_Recv_Default(int32_t res, const class SBuffer &buf); +int32_t Z_Load_Devices(uint8_t value); +void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms); +int32_t Z_Query_Bulbs(uint8_t value); +int32_t Z_State_Ready(uint8_t value); +bool Z_LedStatusSet(bool onoff); +void ZigbeeInputLoop(void); +void ZigbeeInitSerial(void); +void ZigbeeZNPFlush(void); +void ZigbeeZNPSend(const uint8_t *msg, size_t len); +void CmndZbZNPSendOrReceive(bool send); +void CmndZbZNPReceive(void); +void CmndZbZNPSend(void); +void ZigbeeEZSPSend_Out(uint8_t out_byte); +void ZigbeeEZSPSendRaw(const uint8_t *msg, size_t len, bool send_cancel); +void ZigbeeEZSPSendCmd(const uint8_t *msg, size_t len); +void ZigbeeEZSPSendDATA_frm(bool send_cancel, uint8_t to_frm, uint8_t from_ack); +void ZigbeeEZSPSendDATA(const uint8_t *msg, size_t len); +int32_t ZigbeeProcessInputEZSP(class SBuffer &buf); +void EZSP_HandleAck(uint8_t new_ack); +int32_t ZigbeeProcessInputRaw(class SBuffer &buf); +void CmndZbEZSPSendOrReceive(bool send); +void CmndZbEZSPReceive(void); +void CmndZbEZSPSend(void); +void ZigbeeOutputLoop(void); +uint32_t ZigbeeUploadFlashStart(void); +uint32_t ZigbeeUploadAvailable(void); +char ZigbeeUploadFlashRead(void); +void XModemOutputByte(uint8_t out_char); +char XModemWaitACK(void); +bool XModemSendPacket(uint32_t packet_no); +void ZigbeeUploadSetSoftwareBootloader(); +void ZigbeeUploadSetBootloader(uint8_t state); +bool ZigbeeUploadBootloaderPrompt(void); +bool ZigbeeUploadXmodem(void); +bool ZigbeeUploadOtaReady(void); +bool ZigbeeUploadFinish(void); +uint8_t ZigbeeUploadInit(void); +bool ZigbeeUploadWriteBuffer(uint8_t *buf, size_t size); +void ZigbeeUploadDone(void); +void HandleZigbeeXfer(void); +void ZigbeeInit(void); +void CmndZbReset(void); +void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf, + uint16_t cluster, uint8_t cmd, const char *param); +void ZbApplyMultiplier(double &val_d, int8_t multiplier); +bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr, uint8_t transid); +bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok); +void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZigbeeZCLSendMessage & packet); +void ZbSendSend(class JsonParserToken val_cmd, uint16_t device, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint16_t manuf); +void ZbSendRead(JsonParserToken val_attr, ZigbeeZCLSendMessage & packet); +void CmndZbSend(void); +void ZbBindUnbind(bool unbind); +void CmndZbBind(void); +void CmndZbUnbind(void); +void CmndZbBindState(void); +void CmndZbProbe(void); +void CmndZbProbeOrPing(boolean probe); +void CmndZbPing(void); +void CmndZbName(void); +void CmndZbModelId(void); +void CmndZbLight(void); +void CmndZbForget(void); +void CmndZbSave(void); +void CmndZbRestore(void); +void CmndZbPermitJoin(void); +void CmndZbEZSPListen(void); +void ZigbeeGlowPermitJoinLight(void); +void CmndZbStatus(void); +bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root); +void CmndZbData(void); +void CmndZbConfig(void); +void ZigbeeShow(bool json); +bool Xdrv23(uint8_t function); +void BuzzerSet(uint8_t state); +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode); +void BuzzerSetStateToLed(uint32_t state); +void BuzzerBeep(uint32_t count); +void BuzzerEnabledBeep(uint32_t count, uint32_t duration); +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 AriluxRfInterrupt(void); +void AriluxRfHandler(void); +void AriluxRfInit(void); +void AriluxRfDisable(void); +bool Xdrv26(uint8_t function); +void ShutterLogPos(uint32_t i); +void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source); +void ShutterUpdateVelocity(uint8_t i); +void ShutterRtc50mS(void); +int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index); +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index); +void ShutterInit(void); +void ShutterReportPosition(bool always, uint32_t index); +void ShutterLimitRealAndTargetPositions(uint32_t i); +void ShutterCalculateAccelerator(uint8_t i); +void ShutterDecellerateForStop(uint8_t i); +void ShutterPowerOff(uint8_t i); +void ShutterUpdatePosition(void); +bool ShutterState(uint32_t device); +void ShutterAllowPreStartProcedure(uint8_t i); +void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos); +int32_t ShutterCalculatePosition(uint32_t i); +void ShutterRelayChanged(void); +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index); +void ShutterButtonHandler(void); +void ShutterSetPosition(uint32_t device, uint32_t position); +void ShutterToggle(bool dir); +void CmndShutterOpen(void); +void CmndShutterStopOpen(void); +void CmndShutterClose(void); +void CmndShutterStopClose(void); +void CmndShutterToggle(void); +void CmndShutterToggleDir(void); +void CmndShutterStopToggle(void); +void CmndShutterStopToggleDir(void); +void CmndShutterStop(void); +void CmndShutterIncDec(void); +void CmndShutterPosition(void); +void CmndShutterStopPosition(void); +void CmndShutterOpenTime(void); +void CmndShutterCloseTime(void); +void CmndShutterMotorDelay(void); +void CmndShutterMode(void); +void CmndShutterRelay(void); +void CmndShutterButton(void); +void CmndShutterSetHalfway(void); +void CmndShutterFrequency(void); +void CmndShutterSetClose(void); +void CmndShutterSetOpen(void); +void CmndShutterPwmRange(void); +void CmndShutterCalibration(void); +void ShutterOptionsSetHelper(uint16_t option); +void CmndShutterInvert(void); +void CmndShutterLock(void); +void CmndShutterEnableEndStopTime(void); +void CmndShutterInvertWebButtons(void); +bool Xdrv27(uint8_t function); +void Pcf8574SwitchRelay(void); +void Pcf8574Init(void); +void HandlePcf8574(void); +void Pcf8574SaveSettings(void); +bool Xdrv28(uint8_t function); +bool DeepSleepEnabled(void); +void DeepSleepReInit(void); +void DeepSleepPrepare(void); +void DeepSleepStart(void); +void DeepSleepEverySecond(void); +void CmndDeepsleepTime(void); +bool Xdrv29(uint8_t function); +uint8_t crc8(const uint8_t *p, uint8_t len); +void ExsSendCmd(uint8_t cmd, uint8_t value); +void ExsSetPower(uint8_t device, uint8_t power); +void ExsSetBri(uint8_t device, uint8_t bri); +void ExsSyncState(uint8_t device); +bool ExsSyncState(); +void ExsDebugState(); +void ExsPacketProcess(void); +bool ExsModuleSelected(void); +bool ExsSetChannels(void); +bool ExsSetPower(void); +void EsxMcuStart(void); +void ExsInit(void); +void ExsSerialInput(void); +void CmndExsDimm(void); +void CmndExsDimmTbl(void); +void CmndExsDimmVal(void); +void CmndExsDimms(void); +void CmndExsChLock(void); +void CmndExsState(void); +bool Xdrv30(uint8_t function); +uint32_t TasmotaClient_FlashStart(void); +uint8_t TasmotaClient_UpdateInit(void); +void TasmotaClient_Reset(void); +uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout); +uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count); +uint8_t TasmotaClient_execCmd(uint8_t cmd); +uint8_t TasmotaClient_execParam(uint8_t cmd, uint8_t* params, int count); +uint8_t TasmotaClient_exitProgMode(void); +uint8_t TasmotaClient_SetupFlash(void); +uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo); +void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data); +void TasmotaClient_Flash(void); +void TasmotaClient_SetFlagFlashing(bool value); +bool TasmotaClient_GetFlagFlashing(void); +void TasmotaClient_WriteBuffer(uint8_t *buf, size_t size); +void TasmotaClient_Init(void); +bool TasmotaClient_Available(void); +void TasmotaClient_Show(void); +void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param); +void CmndClientReset(void); +void CmndClientSend(void); +void TasmotaClient_ProcessIn(void); +bool Xdrv31(uint8_t function); +void HotPlugInit(void); +void HotPlugEverySecond(void); +void CmndHotPlugTime(void); +bool Xdrv32(uint8_t function); +bool NRF24initRadio(); +bool NRF24Detect(void); +bool Xdrv33(uint8_t function); +void WMotorV1Detect(void); +void WMotorV1Reset(void); +void WMotorV1SetFrequency(uint32_t freq); +void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val); +bool WMotorV1Command(void); +bool Xdrv34(uint8_t function); +void PWMModulePreInit(void); +void PWMDimmerSetBrightnessLeds(int32_t bri); +void PWMDimmerSetPoweredOffLed(void); +void PWMDimmerSetPower(void); +void PWMDimmerHandleDevGroupItem(void); +void PWMDimmerHandleButton(uint32_t button_index, bool pressed); +void CmndBriPreset(void); +void CmndPWMDimmerPWMs(void); +bool Xdrv35(uint8_t function); +void CmdSet(void); +void GenerateDeviceCryptKey(); +void CmdSendButton(void); +void SendBit(byte bitToSend); +void CmndSendRaw(void); +void enterrx(); +void entertx(); +void SendSyncPreamble(int l); +void CreateKeeloqPacket(); +void KeeloqInit(); +bool Xdrv36(uint8_t function); +void SonoffD1Received(void); +bool SonoffD1SerialInput(void); +void SonoffD1Send(); +bool SonoffD1SendPower(void); +bool SonoffD1SendDimmer(void); +bool SonoffD1ModuleSelected(void); +bool Xdrv37(uint8_t function); +void PingResponsePoll(void); +void CmndPing(void); +bool Xdrv38(uint8_t function); +void ThermostatInit(uint8_t ctr_output); +bool ThermostatMinuteCounter(uint8_t ctr_output); +inline bool ThermostatSwitchIdValid(uint8_t switchId); +inline bool ThermostatRelayIdValid(uint8_t relayId); +uint8_t ThermostatInputStatus(uint8_t input_switch); +uint8_t ThermostatOutputStatus(uint8_t output_switch); +int16_t ThermostatCelsiusToFahrenheit(const int32_t deg, uint8_t conv_type); +int16_t ThermostatFahrenheitToCelsius(const int32_t deg, uint8_t conv_type); +void ThermostatSignalPreProcessingSlow(uint8_t ctr_output); +void ThermostatSignalPostProcessingSlow(uint8_t ctr_output); +void ThermostatSignalProcessingFast(uint8_t ctr_output); +void ThermostatCtrState(uint8_t ctr_output); +void ThermostatHybridCtrPhase(uint8_t ctr_output); +bool ThermostatStateAutoToManual(uint8_t ctr_output); +bool ThermostatStateManualToAuto(uint8_t ctr_output); +void ThermostatEmergencyShutdown(uint8_t ctr_output); +void ThermostatState(uint8_t ctr_output); +void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command); +void ThermostatCalculatePI(uint8_t ctr_output); +void ThermostatWorkAutomaticPI(uint8_t ctr_output); +void ThermostatWorkAutomaticRampUp(uint8_t ctr_output); +void ThermostatPeakDetectorInit(uint8_t ctr_output); +void ThermostatPeakDetector(uint8_t ctr_output); +void ThermostatAutotuneParamCalc(uint8_t ctr_output); +void ThermostatWorkAutomaticPIAutotune(uint8_t ctr_output); +void ThermostatCtrWork(uint8_t ctr_output); +void ThermostatWork(uint8_t ctr_output); +void ThermostatDiagnostics(uint8_t ctr_output); +void ThermostatController(uint8_t ctr_output); +bool ThermostatTimerArm(uint8_t ctr_output, int16_t tempVal); +void ThermostatTimerDisarm(uint8_t ctr_output); +void ThermostatVirtualSwitch(uint8_t ctr_output); +void ThermostatVirtualSwitchCtrState(uint8_t ctr_output); +void ThermostatDebug(uint8_t ctr_output); +void ThermostatGetLocalSensor(uint8_t ctr_output); +void CmndThermostatModeSet(void); +void CmndClimateModeSet(void); +void CmndTempFrostProtectSet(void); +void CmndControllerModeSet(void); +void CmndInputSwitchSet(void); +void CmndInputSwitchUse(void); +void CmndSensorInputSet(void); +void CmndOutputRelaySet(void); +void CmndTimeAllowRampupSet(void); +void CmndTempFormatSet(void); +void CmndTempMeasuredSet(void); +void CmndTempTargetSet(void); +void CmndTempMeasuredGrdRead(void); +void CmndStateEmergencySet(void); +void CmndTimeManualToAutoSet(void); +void CmndPropBandSet(void); +void CmndTimeResetSet(void); +void CmndTimePiProportRead(void); +void CmndTimePiIntegrRead(void); +void CmndTimePiCycleSet(void); +void CmndTempAntiWindupResetSet(void); +void CmndTempHystSet(void); +void CmndPerfLevelAutotune(void); +void CmndTimeMaxActionSet(void); +void CmndTimeMinActionSet(void); +void CmndTimeSensLostSet(void); +void CmndTimeMinTurnoffActionSet(void); +void CmndTempRupDeltInSet(void); +void CmndTempRupDeltOutSet(void); +void CmndTimeRampupMaxSet(void); +void CmndTimeRampupCycleSet(void); +void CmndTempRampupPiAccErrSet(void); +void CmndDiagnosticModeSet(void); +void CmndCtrDutyCycleRead(void); +void CmndEnableOutputSet(void); +bool Xdrv39(uint8_t function); +bool TelegramInit(void); +String TelegramConnectToTelegram(String command); +void TelegramGetUpdates(uint32_t offset); +bool TelegramSendMessage(uint32_t chat_id, String text); +String TelegramExecuteCommand(const char *svalue); +void TelegramLoop(void); +void CmndTmState(void); +void CmndTmPoll(void); +void CmndTmToken(void); +void CmndTmChatId(void); +void CmndTmSend(void); +bool Xdrv40(uint8_t function); +void TCPLoop(void); +void TCPInit(void); +void CmndTCPStart(void); +void CmndTCPBaudrate(void); +bool Xdrv41(uint8_t function); +void I2S_Init(void); +void mp3_task(void *arg); +void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str); +void StatusCallback(void *cbData, int code, const char *string); +void Webradio(const char *url); +void mp3_task2(void *arg); +void StopPlaying(); +void Cmd_WebRadio(void); +void I2S_WR_Show(void); +void Play_mp3(const char *path); +void mp3_delete(void); +void Say(char *text); +void Cmd_Play(void); +void Cmd_Gain(void); +void Cmd_Say(void); +void Cmd_Time(void); +bool Xdrv42(uint8_t function); +void MLX90640UpdateGUI(void); +void MLX90640HandleWebGuiResponse(void); +void MLX90640HandleWebGui(void); +bool MLX90640Cmd(void); +void MLX90640init(); +void MLX90640every100msec(); +void MLX90640Show(uint8_t json); +bool Xdrv43(uint8_t function); +static uint8_t +miel_hvac_write(struct miel_hvac_softc *sc, const uint8_t *bytes, size_t len); +static void +miel_hvac_send(struct miel_hvac_softc *sc, uint8_t type, + const void *data, size_t len); +static void +miel_hvac_request(struct miel_hvac_softc *sc, uint8_t type); +static void +miel_hvac_init_update(struct miel_hvac_msg_update *update); +static bool +miel_hvac_set_power(struct miel_hvac_softc *sc); +static void +miel_hvac_respond_unsupported(void); +static void +miel_hvac_cmnd_setfanspeed(void); +static void +miel_hvac_cmnd_setmode(void); +static void +miel_hvac_cmnd_sethamode(void); +static void +miel_hvac_cmnd_settemp(void); +static void +miel_hvac_cmnd_setvane(void); +static void +miel_hvac_cmnd_setwidevane(void); +static void +miel_hvac_cmnd_remotetemp(void); +static void +miel_hvac_cmnd_request(void); +static void +miel_hvac_log_bytes(struct miel_hvac_softc *sc, const char *name, + const void *buf, size_t len); +static void +miel_hvac_input_connected(struct miel_hvac_softc *sc, + const void *buf, size_t len); +static void +miel_hvac_publish_settings(struct miel_hvac_softc *sc); +static void +miel_hvac_input_settings(struct miel_hvac_softc *sc, + const struct miel_hvac_data *d); +static void +miel_hvac_data_response(struct miel_hvac_softc *sc, + const struct miel_hvac_data *d); +static void +miel_hvac_input_sensor(struct miel_hvac_softc *sc, struct miel_hvac_data *dst, + const struct miel_hvac_data *src); +static void +miel_hvac_input_data(struct miel_hvac_softc *sc, + const void *buf, size_t len); +static void +miel_hvac_input_updated(struct miel_hvac_softc *sc, + const void *buf, size_t len); +static void +miel_hvac_pre_init(void); +static void +miel_hvac_loop(struct miel_hvac_softc *sc); +static void +miel_hvac_sensor(struct miel_hvac_softc *sc); +static void +miel_hvac_connect(struct miel_hvac_softc *sc); +static void +miel_hvac_tick(struct miel_hvac_softc *sc); +bool Xdrv44(uint8_t function); +bool WcPinUsed(void); +uint32_t WcSetup(int32_t fsiz); +int32_t WcSetOptions(uint32_t sel, int32_t value); +uint32_t WcGetWidth(void); +uint32_t WcGetHeight(void); +uint32_t WcSetMotionDetect(int32_t value); +void WcDetectMotion(void); +void fd_init(void); +uint32_t WcSetFaceDetect(int32_t value); +uint32_t WcGetPicstore(int32_t num, uint8_t **buff); +uint32_t WcGetFrame(int32_t bnum); +void HandleImage(void); +void HandleImageBasic(void); +void HandleWebcamMjpeg(void); +void HandleWebcamMjpegTask(void); +void HandleWebcamRoot(void); +uint32_t WcSetStreamserver(uint32_t flag); +void WcStreamControl(); +void WcLoop(void); +void WcPicSetup(void); +void WcShowStream(void); +void WcInit(void); +void CmndWebcam(void); +void CmndWebcamStream(void); +void CmndWebcamResolution(void); +void CmndWebcamMirror(void); +void CmndWebcamFlip(void); +void CmndWebcamSaturation(void); +void CmndWebcamBrightness(void); +void CmndWebcamContrast(void); +void CmndWebcamInit(void); +bool Xdrv81(uint8_t function); +void EthernetEvent(WiFiEvent_t event); +void EthernetInit(void); +IPAddress EthernetLocalIP(void); +char* EthernetHostname(void); +String EthernetMacAddress(void); +void CmndEthernet(void); +void CmndEthAddress(void); +void CmndEthType(void); +void CmndEthClockMode(void); +bool Xdrv82(uint8_t function); +void TTGO_Init(void); +void initPower(void); +static uint8_t axpWriteBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len); +static uint8_t axpReadBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len); +void TTGO_GetADC(void); +void TTGO_WebShow(uint32_t json); +void TTGO_audio_power(bool power); +void TTGO_LightSleep(void); +void TTGO_Sleep(int32_t stime); +void TTGO_loop(uint32_t flg); +bool TTGO_doubleclick(void); +bool TTGO_button(void); +bool Xdrv83(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 SetFlashMode(uint8_t mode); +void CmndHelp(void); +void CmndRtcDump(void); +void CmndCfgDump(void); +void CmndCfgPeek(void); +void CmndCfgPoke(void); +void CmndCfgXor(void); +void CmndException(void); +void CmndCpuCheck(void); +void CmndSerBufSize(void); +void CmndFreemem(void); +void CmndSetSensor(void); +void CmndFlashMode(void); +uint32_t DebugSwap32(uint32_t x); +void CmndFlashDump(void); +void CmndI2cWrite(void); +void CmndI2cRead(void); +void CmndI2cStretch(void); +void CmndI2cClock(void); +bool Xdrv99(uint8_t function); +void XsnsDriverState(void); +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(); +void LcdCenter(uint8_t row, char* txt); +bool LcdPrintLog(void); +void LcdTime(void); +void LcdRefresh(void); +bool Xdsp01(uint8_t function); +void SSD1306InitDriver(void); +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); +bool Ili9341Header(void); +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(); +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_RotConvert(int16_t *x, int16_t *y); +void ILI9488_CheckTouch(void); +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_RotConvert(int16_t *x, int16_t *y); +void RA8876_CheckTouch(void); +bool Xdsp10(uint8_t function); +void SevensegWrite(void); +void SevensegClear(void); +void SevensegInitMode(void); +void SevensegInit(uint8_t mode); +void SevensegInitDriver(void); +void SevensegOnOff(void); +void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); +void SevensegTime(boolean time_24); +void SevensegRefresh(void); +bool Xdsp11(uint8_t function); +void ST7789_InitDriver(); +void ST7789_RotConvert(int16_t *x, int16_t *y); +void ST7789_CheckTouch(); +bool Xdsp12(uint8_t function); +uint8_t XdspPresent(void); +bool XdspCall(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 Ws2812Clear(void); +void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); +char* Ws2812GetColor(uint32_t led, char* scolor); +void Ws2812ForceSuspend (void); +void Ws2812ForceUpdate (void); +bool Ws2812SetChannels(void); +void Ws2812ShowScheme(void); +void Ws2812ModuleSelected(void); +void CmndLed(void); +void CmndPixels(void); +void CmndRotation(void); +void CmndWidth(void); +bool Xlgt01(uint8_t function); +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); +bool My92x1SetChannels(void); +void My92x1ModuleSelected(void); +bool Xlgt02(uint8_t function); +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); +void SM16716_Init(void); +bool Sm16716SetChannels(void); +void Sm16716ModuleSelected(void); +bool Xlgt03(uint8_t function); +void Sm2135SetLow(uint8_t pin); +void Sm2135SetHigh(uint8_t pin); +bool Sm2135Init(void); +bool Sm2135Write(uint8_t value); +bool Sm2135Start(uint8_t addr); +void Sm2135Stop(void); +bool Sm2135SetChannels(void); +void Sm2135ModuleSelected(void); +bool Xlgt04(uint8_t function); +void SnfL1Send(const char *buffer); +void SnfL1SerialSendOk(void); +bool SnfL1SerialInput(void); +bool SnfL1SetChannels(void); +void SnfL1ModuleSelected(void); +bool Xlgt05(uint8_t function); +bool ElectriqMoodLSetChannels(void); +void ElectriqMoodLModuleSelected(void); +bool Xlgt06(uint8_t function); +bool XlgtCall(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); +void CseSerialInput(void); +void CseEverySecond(void); +void CseSnsInit(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 PzemEvery250ms(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); +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); +void DDSU666Every250ms(void); +void Ddsu666SnsInit(void); +void Ddsu666DrvInit(void); +bool Xnrg11(uint8_t function); +bool solaxX1_RS485ReceiveReady(void); +void solaxX1_RS485Send(uint16_t msgLen); +uint8_t solaxX1_RS485Receive(uint8_t *value); +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); +void solaxX1_SendInverterAddress(void); +void solaxX1_QueryLiveData(void); +uint8_t solaxX1_ParseErrorCode(uint32_t code); +void solaxX1250MSecond(void); +void solaxX1SnsInit(void); +void solaxX1DrvInit(void); +void solaxX1Show(bool json); +bool Xnrg12(uint8_t function); +void FifLEEvery250ms(void); +void FifLESnsInit(void); +void FifLEDrvInit(void); +void FifLEReset(void); +void FifLEShow(bool json); +bool Xnrg13(uint8_t function); +void Bl0940Received(void); +void Bl0940SerialInput(void); +void Bl0940EverySecond(void); +void Bl0940SnsInit(void); +void Bl0940DrvInit(void); +bool Bl0940Command(void); +void Bl0940Show(bool json); +bool Xnrg14(uint8_t function); +void ADPSCallback(uint8_t phase); +void DataCallback(struct _ValueList * me, uint8_t flags); +void ResponseAppendTInfo(char sep); +void NewFrameCallback(struct _ValueList * me); +void TInfoDrvInit(void); +void TInfoInit(void); +void TInfoEvery250ms(void); +void TInfoShow(bool json); +bool Xnrg15(uint8_t function); +void IEM3000Every250ms(void); +void Iem3000SnsInit(void); +void Iem3000DrvInit(void); +bool Xnrg16(uint8_t function); +void WE517Every250ms(void); +void We517SnsInit(void); +void We517DrvInit(void); +bool Xnrg17(uint8_t function); +bool XnrgCall(uint8_t function); +void ICACHE_RAM_ATTR CounterIsrArg(void *arg); +void CounterInterruptDisable(bool state); +bool CounterPinState(void); +void CounterInit(void); +void CounterEverySecond(void); +void CounterSaveState(void); +void CounterShow(bool json); +void SyncACDimmer(void); +void CmndCounter(void); +void CmndCounterType(void); +void CmndCounterDebounce(void); +void CmndCounterDebounceLow(void); +void CmndCounterDebounceHigh(void); +bool Xsns01(uint8_t function); +bool adcAttachPin(uint8_t pin); +void AdcSaveSettings(uint32_t idx); +void AdcGetSettings(uint32_t idx); +void AdcInitParams(uint8_t idx); +void AdcAttach(uint8_t pin, uint8_t type); +void AdcInit(void); +uint16_t AdcRead(uint32_t pin, uint32_t factor); +void AdcEvery250ms(void); +uint8_t AdcGetButton(uint32_t pin); +uint16_t AdcGetLux(uint32_t idx); +uint16_t AdcGetRange(uint32_t idx); +void AdcGetCurrentPower(uint8_t idx, uint8_t factor); +void AdcEverySecond(void); +void AdcShowContinuation(bool *jsonflg); +void AdcShow(bool json); +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 OneWire1ReadBit(void); +uint8_t OneWire2ReadBit(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); +void Ds18x20Convert(void); +bool Ds18x20Read(uint8_t sensor, float &t); +void Ds18x20Name(uint8_t sensor); +void Ds18x20EverySecond(void); +void Ds18x20Show(bool json); +bool Xsns05(uint8_t function); +bool DhtWaitState(uint32_t sensor, uint32_t level); +bool DhtRead(uint32_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 BmpShow(bool json); +void BMP_EnterSleep(void); +bool Xsns09(uint8_t function); +uint8_t Bh1750Resolution(uint32_t sensor_index); +bool Bh1750SetResolution(uint32_t sensor_index); +bool Bh1750SetMTreg(uint32_t sensor_index); +bool Bh1750Read(uint32_t sensor_index); +void Bh1750Detect(void); +void Bh1750EverySecond(void); +void CmndBh1750Resolution(void); +void CmndBh1750MTime(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 Ads1115Label(char* label, uint32_t maxsize, uint8_t address); +void AdsEvery250ms(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); +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); +size_t PmsSendCmd(uint8_t command_id); +bool PmsReadData(void); +bool PmsCommandSensor(void); +void PmsSecond(void); +void PmsInit(void); +void PmsShow(bool json); +bool Xsns18(uint8_t function); +void MGSInit(void); +void 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); +void Sgp30Update(void); +void Sgp30Show(bool json); +bool Xsns21(uint8_t function); +uint8_t Sr04TModeDetect(void); +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third); +uint16_t Sr04TMode3Distance(); +uint16_t Sr04TMode2Distance(void); +void Sr04TReading(void); +void Sr04Show(bool json); +bool Xsns22(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); +bool Si1145Read(void); +void Si1145Detect(void); +void Si1145Update(void); +void Si1145Show(bool json); +bool Xsns24(uint8_t function); +void LM75ADDetect(void); +float LM75ADGetTemp(void); +void LM75ADShow(bool json); +bool Xsns26(uint8_t function); +void calculateColorTemperature(void); +uint8_t getProxIntLowThresh(void); +inline void setProxIntLowThresh(uint8_t threshold); +uint8_t getProxIntHighThresh(void); +inline void setProxIntHighThresh(uint8_t threshold); +uint8_t getLEDDrive(void); +void setLEDDrive(uint8_t drive); +uint8_t getProximityGain(void); +void setProximityGain(uint8_t drive); +uint8_t getAmbientLightGain(); +void setAmbientLightGain(uint8_t drive); +uint8_t getLEDBoost(void); +void setLEDBoost(uint8_t boost); +uint8_t getProxGainCompEnable(void); +void setProxGainCompEnable(uint8_t enable); +uint8_t getProxPhotoMask(void); +void setProxPhotoMask(uint8_t mask); +uint8_t getGestureEnterThresh(void); +inline void setGestureEnterThresh(uint8_t threshold); +uint8_t getGestureExitThresh(void); +inline void setGestureExitThresh(uint8_t threshold); +uint8_t getGestureGain(void); +void setGestureGain(uint8_t gain); +uint8_t getGestureLEDDrive(void); +void setGestureLEDDrive(uint8_t drive); +uint8_t getGestureWaitTime(void); +void setGestureWaitTime(uint8_t time); +void getLightIntLowThreshold(uint16_t &threshold); +void setLightIntLowThreshold(uint16_t threshold); +void getLightIntHighThreshold(uint16_t &threshold); +void setLightIntHighThreshold(uint16_t threshold); +void getProximityIntLowThreshold(uint8_t &threshold); +void setProximityIntLowThreshold(uint8_t threshold); +void getProximityIntHighThreshold(uint8_t &threshold); +void setProximityIntHighThreshold(uint8_t threshold); +uint8_t getAmbientLightIntEnable(void); +void setAmbientLightIntEnable(uint8_t enable); +uint8_t getProximityIntEnable(void); +void setProximityIntEnable(uint8_t enable); +uint8_t getGestureIntEnable(void); +void setGestureIntEnable(uint8_t enable); +void clearAmbientLightInt(void); +void clearProximityInt(void); +uint8_t getGestureMode(void); +void setGestureMode(uint8_t mode); +bool APDS9960_init(void); +inline 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); +inline void enablePower(void); +inline void disablePower(void); +inline void readAllColorAndProximityData(void); +void APDS9960_adjustATime(void); +void resetGestureParameters(void); +bool processGestureData(void); +bool decodeGesture(void); +void handleGesture(void); +void APDS9960_loop(void); +void 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_Interrupt_Counter_Report(void); +void MCP230xx_Interrupt_Retain_Report(void); +void MCP230xx_SwitchRelay(); +bool Xsns29(uint8_t function); +void Mpr121Init(struct mpr121 *pS, bool initial); +void Mpr121Show(struct mpr121 *pS, uint8_t function); +bool Xsns30(uint8_t function); +void CCS811Detect(void); +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); +void DS3231EverySecond(void); +bool Xsns33(uint8_t function); +bool HxIsReady(uint16_t timeout); +long HxRead(void); +void HxResetPart(void); +void HxReset(void); +void HxCalibrationStateTextJson(uint8_t msg_id); +void SetWeightDelta(); +bool HxCommand(void); +long HxWeight(void); +void HxInit(void); +void HxEvery100mSecond(void); +void HxSaveBeforeRestart(void); +void HxShow(bool json); +void HandleHxAction(void); +void HxSaveSettings(void); +void HxLogUpdates(void); +bool Xsns34(uint8_t function); +void ICACHE_RAM_ATTR TX2xStartRead(void); +bool Tx2xAvailable(void); +float atan2f(float a, float b); +void Tx2xCheckSampleCount(void); +void Tx2xResetStat(void); +void Tx2xResetStatData(void); +void Tx2xRead(void); +void Tx2xInit(void); +int32_t Tx2xNormalize(int32_t value); +void Tx2xShow(bool json); +bool Xsns35(uint8_t function); +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(); +void 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); +int32_t MAX31855_ShiftIn(uint8_t Length); +float MAX31855_GetProbeTemperature(int32_t RawData); +float MAX31855_GetReferenceTemperature(int32_t RawData); +void MAX31855_GetResult(void); +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); +void Scd30Detect(void); +void Scd30Update(void); +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); +void SPS30_Every_Second(); +void SPS30_Show(bool json); +bool SPS30_cmd(void); +bool Xsns44(byte function); +void Vl53l0Detect(void); +void Vl53l0Every_250MSecond(void); +void Vl53l0Every_Second(void); +void Vl53l0Show(boolean json); +bool Xsns45(byte function); +void MLX90614_Init(void); +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); +void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg); +uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr); +void ChirpReset(uint8_t addr); +void ChirpResetAll(void); +void ChirpClockSet(); +void ChirpSleep(uint8_t addr); +void ChirpSelect(uint8_t sensor); +uint8_t ChirpReadVersion(uint8_t addr); +bool ChirpSet(uint8_t addr); +bool ChirpScan(); +void ChirpDetect(void); +void ChirpServiceAllSensors(uint8_t job); +void ChirpEvery100MSecond(void); +void ChirpShow(bool json); +bool ChirpCmd(void); +bool Xsns48(uint8_t function); +void PAJ7620SelectBank(uint8_t bank); +void PAJ7620DecodeGesture(void); +void PAJ7620ReadGesture(void); +void PAJ7620Detect(void); +void PAJ7620Init(void); +void PAJ7620Loop(void); +void PAJ7620Show(bool json); +bool PAJ7620CommandSensor(void); +bool Xsns50(uint8_t function); +uint8_t RDM6300HexNibble(char chr); +void RDM6300HexStringToArray(uint8_t array[], uint8_t len, char buffer[]); +void RDM6300Init(); +void RDM6300ScanForTag(); +void RDM6300Show(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,const char *uid,const char *major,const char *minor); +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 ICACHE_RAM_ATTR SML_CounterUpd(uint8_t index); +void ICACHE_RAM_ATTR SML_CounterUpd1(void); +void ICACHE_RAM_ATTR SML_CounterUpd2(void); +void ICACHE_RAM_ATTR SML_CounterUpd3(void); +void ICACHE_RAM_ATTR SML_CounterUpd4(void); +uint32_t SML_getlinelen(char *lp); +uint32_t SML_getscriptsize(char *lp); +uint32_t SML_getscriptsize(char *lp); +bool Gpio_used(uint8_t gpiopin); +void SML_Init(void); +uint32_t SML_SetBaud(uint32_t meter, uint32_t br); +uint32_t SML_Status(uint32_t meter); +uint32_t SML_Write(uint32_t meter,char *hstr); +uint32_t SML_Read(int32_t meter,char *str, uint32_t slen); +float SML_GetVal(uint32_t index); +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); +uint8_t CalcEvenParity(uint8_t data); +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 Ina226Index); +bool Ina226TestPresence(uint8_t device); +void Ina226ResetActive(void); +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 Hih6Read(void); +void Hih6Detect(void); +void Hih6EverySecond(void); +void Hih6Show(bool json); +bool Xsns55(uint8_t function); +void HpmaSecond(void); +void HpmaInit(void); +void HpmaShow(bool json); +bool Xsns56(uint8_t function); +void Tsl2591Init(void); +bool Tsl2591Read(void); +void Tsl2591EverySecond(void); +void Tsl2591Show(bool json); +bool Xsns57(uint8_t function); +bool Dht12Read(void); +void Dht12Detect(void); +void Dht12EverySecond(void); +void Dht12Show(bool json); +bool Xsns58(uint8_t function); +uint32_t DS1624_Idx2Addr(uint32_t idx); +void DS1624_Restart(uint8_t config, uint32_t idx); +void DS1624_HotPlugUp(uint32_t idx); +void DS1624_HotPlugDown(int idx); +bool DS1624GetTemp(float *value, int idx); +void DS1624HotPlugScan(void); +void DS1624EverySecond(void); +void DS1624Show(bool json); +bool Xsns59(uint8_t function); +void UBXcalcChecksum(char* CK, size_t msgSize); +bool UBXcompareMsgHeader(const char* msgHeader); +void UBXinitCFG(void); +void UBXsendCFGLine(uint8_t _line); +void UBXTriggerTele(void); +void UBXDetect(void); +uint32_t UBXprocessGPS(); +void UBXsendHeader(void); +void UBXsendRecord(uint8_t *buf); +void UBXsendFooter(void); +void UBXsendFile(void); +void UBXSetRate(uint16_t interval); +void UBXSelectMode(uint16_t mode); +bool UBXHandlePOSLLH(); +void UBXHandleSTATUS(); +void UBXHandleTIME(); +void UBXHandleOther(void); +void UBXLoop50msec(void); +void UBXLoop(void); +void UBXShow(bool json); +bool UBXCmd(void); +bool Xsns60(uint8_t function); +void MINRFinit(void); +bool MINRFinitBLE(uint8_t _mode); +void MINRFhopChannel(); +bool MINRFreceivePacket(void); +void MINRFswapbuf(uint8_t *buf, uint8_t len); +void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr); +void MINRFhandleScan(void); +void MINRFstartBeacon(uint16_t entry); +void MINRFbeaconCounter(void); +int MINRFdecryptPacket(char *_buf); +int MINRFdecryptMJYD2SPacket(char *_buf, uint8_t _light, char* _output); +void MINRFreverseMAC(uint8_t _MAC[]); +void MINRFAddKey(char* payload); +void MINRFKeyMACStringToBytes(char* _string,uint8_t _keyMAC[]); +void MINRFMACStringToBytes(char* _string, uint8_t _MAC[]); +void MINRFcomputefirstUsedPacketMode(void); +void MINRFrecalcBuffer(uint8_t *_buf, uint32_t offset); +void MINRFchangePacketModeTo(uint8_t _mode); +void MINRFpurgeFakeSensors(void); +void MINRFconfirmSensors(void); +void MINRFtriggerTele(void); +void MINRFhandleMiBeaconPacket(void); +void MINRFhandleCGD1Packet(void); +void MINRFhandleNlightPacket(void); +void MINRFhandleMJYD2SPacket(void); +void MINRFhandleLightPacket(void); +void MINRFaddLight(uint8_t _MAC[], uint8_t _type); +void MINRFhandleATCPacket(void); +void MINRF_EVERY_50_MSECOND(); +bool NRFCmd(void); +void MINRFShow(bool json); +bool Xsns61(uint8_t function); +void MI32stripColon(char* _string); +void MI32HexStringToBytes(char* _string, uint8_t* _byteArray); +void MI32_ReverseMAC(uint8_t _mac[]); +void MI32AddKey(char* payload); +int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type); +void MI32nullifyEndOfMQTT_DATA(); +void MI32triggerTele(void); +void MI32StatusInfo(); +void MI32Init(void); +void MI32StartTask(uint32_t task); +bool MI32ConnectActiveSensor(); +void MI32StartScanTask(); +void MI32ScanTask(void *pvParameters); +void MI32StartSensorTask(); +void MI32SensorTask(void *pvParameters); +bool MI32connectLYWSD03forNotification(); +void MI32StartTimeTask(); +void MI32TimeTask(void *pvParameters); +void MI32StartUnitTask(); +void MI32UnitTask(void *pvParameters); +void MI32StartBatteryTask(); +void MI32BatteryTask(void *pvParameters); +void MI32batteryRead(uint32_t _type); +void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize); +void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI); +void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI); +void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI); +void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID); +void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, uint8_t* addr); +void MI32addBeacon(uint8_t index, char* data); +void MI32showScanResults(); +void MI32readHT_LY(char *_buf); +bool MI32readBat(char *_buf); +void MI32Every50mSecond(); +void MI32EverySecond(bool restart); +bool MI32Cmd(void); +void MI32Show(bool json); +bool Xsns62(uint8_t function); +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay); +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot); +void HM10_ReverseMAC(uint8_t _mac[]); +void HM10_Reset(void); +void HM10_Discovery_Scan(void); +void HM10_Read_LYWSD03(void); +void HM10_Read_LYWSD02(void); +void HM10_Time_LYWSD02(void); +void HM10_Read_Flora(void); +void HM10_Read_CGD1(void); +void HM10_Read_MJ_HT_V1(void); +void HM10SerialInit(void); +void HM10parseMiBeacon(char * _buf, uint32_t _slot); +void HM10parseATC(char * _buf, uint32_t _slot); +char* HM10ParseResponse(char *buf, uint16_t bufsize); +void HM10readHT_LY(char *_buf); +void HM10readHT_CGD1(char *_buf); +void HM10readHT_MJ_HT_V1(char *_buf); +void HM10readTLMF(char *_buf); +bool HM10readBat(char *_buf); +bool HM10SerialHandleFeedback(); +void HM10_TaskEvery100ms(); +void HM10StatusInfo(); +void HM10EverySecond(bool restart); +bool HM10Cmd(void); +void HM10triggerTele(void); +void HM10Show(bool json); +bool Xsns62(uint8_t function); +bool AHT1XWrite(uint8_t aht1x_idx); +bool AHT1XRead(uint8_t aht1x_idx); +void AHT1XPoll(void); +unsigned char AHT1XReadStatus(uint8_t aht1x_address); +void AHT1XReset(uint8_t aht1x_address); +bool AHT1XInit(uint8_t aht1x_address); +void AHT1XDetect(void); +void AHT1XShow(bool json); +bool Xsns63(uint8_t function); +void HRXLInit(void); +void HRXLEverySecond(void); +void HRXLShow(bool json); +bool Xsns64(uint8_t function); +uint16_t HdcReadDeviceId(void); +uint16_t HdcReadManufacturerId(void); +void HdcConfig(uint16_t config); +void HdcReset(void); +int8_t HdcTransactionOpen(uint8_t addr, uint8_t reg); +int8_t HdcTransactionClose(uint8_t addr, uint8_t *reg_data, uint16_t len); +void HdcInit(void); +bool HdcTriggerRead(void); +bool HdcRead(void); +void HdcDetect(void); +void HdcEverySecond(void); +void HdcShow(bool json); +bool Xsns65(uint8_t function); +void IAQ_Init(void); +void IAQ_Read(void); +void IAQ_Show(uint8_t json); +bool Xsns66(byte function); +void ICACHE_RAM_ATTR AS3935Isr(void); +uint8_t AS3935ReadRegister(uint8_t reg, uint8_t mask, uint8_t shift); +void AS3935WriteRegister(uint8_t reg, uint8_t mask, uint8_t shift, uint8_t data); +void ICACHE_RAM_ATTR AS3935CountFreq(void); +bool AS3935AutoTuneCaps(uint8_t irqpin); +bool AS3935CalRCOResult(void); +bool AS3935CalibrateRCO(void); +void AS3935Reset(void); +void AS3935PwrDown(void); +void AS3935PwrUp(void); +uint8_t AS3935GetPwrStat(void); +uint8_t AS3935GetIRQ(void); +uint8_t AS3935TranslIrq(uint8_t irq, uint8_t distance); +uint8_t AS3935GetDistance(void); +int16_t AS3935CalcDistance(void); +uint32_t AS3935GetIntensity(void); +uint8_t AS3935GetTuneCaps(void); +void AS3935SetTuneCaps(uint8_t tune); +uint8_t AS3935GetDisturber(void); +void AS3935SetDisturber(uint8_t stat); +uint8_t AS3935GetMinLights(void); +void AS3935SetMinLights(uint8_t stat); +uint8_t AS3935TransMinLights(uint8_t min_lights); +uint8_t AS3935TranslMinLightsInt(uint8_t min_lights); +uint8_t AS3935GetNoiseFloor(void); +void AS3935SetNoiseFloor(uint8_t noise); +uint8_t AS3935GetGain(void); +void AS3935SetGain(uint8_t room); +uint8_t AS3935GetGainInt(void); +void AS3935CalcVrmsLevel(uint16_t &vrms, uint8_t &stage); +uint8_t AS3935GetSpikeRejection(void); +void AS3935SetSpikeRejection(uint8_t rej); +uint8_t AS3935GetWdth(void); +void AS3935SetWdth(uint8_t wdth); +bool AS3935AutoTune(void); +bool AS3935LowerNoiseFloor(void); +bool AS3935RaiseNoiseFloor(void); +bool AS3935SetDefault(void); +void AS3935InitSettings(void); +bool AS3935Setup(void); +bool AS3935init(void); +void AS3935Detect(void); +void AS3935EverySecond(void); +bool AS3935Cmd(void); +void AH3935Show(bool json); +bool Xsns67(uint8_t function); +void ICACHE_RAM_ATTR WindMeterUpdateSpeed(void); +void WindMeterInit(void); +void WindMeterEverySecond(void); +bool WindMeterShouldTriggerTele(); +void WindMeterResetStatData(void); +void WindMeterCheckSampleCount(void); +void WindMeterShow(bool json); +void WindMeterTriggerTele(void); +bool Xsns68Cmnd(void); +bool Xsns68(uint8_t function); +void sns_opentherm_init_boiler_status(); +void ICACHE_RAM_ATTR sns_opentherm_handleInterrupt(); +void sns_opentherm_processResponseCallback(unsigned long response, int st); +bool sns_opentherm_Init(); +void sns_opentherm_stat(bool json); +void sns_ot_start_handshake(); +void sns_ot_process_handshake(unsigned long response, int st); +void sns_opentherm_CheckSettings(void); +uint8_t sns_opentherm_parse_flag(char *flag); +uint8_t sns_opentherm_read_flags(char *data, uint32_t len); +void sns_opentherm_cmd(void); +void sns_opentherm_boiler_setpoint_cmd(void); +void sns_opentherm_hot_water_setpoint_cmd(void); +void sns_opentherm_save_settings_cmd(void); +void sns_opentherm_flags_cmd(void); +void sns_opentherm_set_central_heating_cmd(void); +bool Xsns69(uint8_t function); +unsigned long sns_opentherm_set_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); +void sns_opentherm_parse_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_slave_flags(struct OpenThermCommandT *self); +unsigned long sns_opentherm_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); +void sns_opentherm_parse_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_boiler_temperature(struct OpenThermCommandT *self); +unsigned long sns_opentherm_set_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); +void sns_opentherm_parse_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_boiler_dhw_temperature(struct OpenThermCommandT *self); +unsigned long sns_opentherm_get_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); +void sns_opentherm_parse_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_flags(struct OpenThermCommandT *self); +unsigned long sns_opentherm_get_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); +void sns_opentherm_parse_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self); +unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); +void sns_opentherm_parse_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_tele_generic_float(struct OpenThermCommandT *self); +void sns_opentherm_parse_dhw_setpoint(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_parse_flame_modulation(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_parse_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +unsigned long sns_opentherm_get_next_request(struct OT_BOILER_STATUS_T *boilerStatus); +void sns_opentherm_check_retry_request(); +void sns_opentherm_process_success_response(struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); +void sns_opentherm_dump_telemetry(); +uint16_t VEML6075read16 (uint8_t reg); +void VEML6075write16 (uint8_t reg, uint16_t val); +float VEML6075calcUVA (void); +float VEML6075calcUVB (void); +float VEML6075calcUVI (void); +void VEML6075SetHD(uint8_t val); +uint8_t VEML6075ReadHD(void); +void VEML6075SetUvIt(uint8_t val); +uint8_t VEML6075GetUvIt(void); +void VEML6075Pwr(uint8_t val); +uint8_t VEML6075GetPwr(void); +void VEML6075ReadData(void); +bool VEML6075init(void); +void VEML6075Detect(void); +void VEML6075EverySecond(void); +bool VEML6075Cmd(void); +void VEML6075Show(bool json); +bool Xsns70(uint8_t function); +void VEML7700Detect(void); +uint16_t VEML7700TranslateItMs (uint8_t ittime); +uint8_t VEML7700TranslateItInt (uint16_t ittimems); +void VEML7700EverySecond(void); +void VEML7700Show(bool json); +bool VEML7700Cmd(void); +bool Xsns71(uint8_t function); +float MCP9808Read(uint8_t addr); +void MCP9808Detect(void); +void MCP9808EverySecond(void); +void MCP9808Show(bool json); +bool Xsns72(uint8_t function); +bool HP303B_Read(uint32_t hp303b_idx); +void HP303B_Detect(void); +void HP303B_EverySecond(void); +void HP303B_Show(bool json); +bool Xsns73(uint8_t function); +void LMT01_Init(void); +void ICACHE_RAM_ATTR LMT01_countPulse(void); +void LMT01_GetTemperature(void); +int LMT01_getPulses(void); +void LMT01_Show(bool Json); +bool Xsns74(uint8_t function); +void HandleMetrics(void); +bool Xsns75(uint8_t function); +void DYPInit(void); +void DYPEverySecond(void); +void DYPShow(bool json); +bool Xsns76(uint8_t function); +void Vl53l1Detect(void); +void Vl53l1Every_250MSecond(void); +void Vl53l1Every_Second(void); +void Vl53l1Show(bool json); +bool Xsns77(uint8_t function); +bool Xsns78(uint8_t function); +bool XsnsEnabled(uint32_t sns_index); +void XsnsSensorState(void); +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); +bool XsnsCall(uint8_t Function); +bool I2cEnabled(uint32_t i2c_index); +void I2cDriverState(void); +#line 191 "/workspace/Tasmota/tasmota/tasmota.ino" +void setup(void) { +#ifdef ESP32 +#ifdef DISABLE_ESP32_BROWNOUT + DisableBrownout(); +#endif +#endif + + global_state.data = 0xF; + + RtcRebootLoad(); + if (!RtcRebootValid()) { + RtcReboot.fast_reboot_count = 0; + } +#ifdef FIRMWARE_MINIMAL + RtcReboot.fast_reboot_count = 0; +#else + RtcReboot.fast_reboot_count++; +#endif + RtcRebootSave(); + + Serial.begin(baudrate); + + 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); + } + + snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); + + SettingsLoad(); + SettingsDelta(); + + OsWatchInit(); + + GetFeatures(); + + if (1 == RtcReboot.fast_reboot_count) { + UpdateQuickPowerCycle(true); + XdrvCall(FUNC_SETTINGS_OVERRIDE); + } + + + 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; + ssleep = 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { + Settings.module = Settings.fallback_module; + + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("FRC: " D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); + } + } + + Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); + Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP_getChipId() & 0x1FFF); + } else { + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); + } + + GetEspHardwareType(); + GpioInit(); + + + + WifiConnect(); + + SetPowerOnState(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE), PROJECT, SettingsText(SET_DEVICENAME), my_version, my_image); +#ifdef FIRMWARE_MINIMAL + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); +#endif + + memcpy_P(log_data, VERSION_MARKER, 1); + + RtcInit(); + +#ifdef USE_ARDUINO_OTA + ArduinoOTAInit(); +#endif + + XdrvCall(FUNC_INIT); + XsnsCall(FUNC_INIT); +#ifdef USE_SCRIPT + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">BS",3,0); +#endif + + rules_flag.system_init = 1; +} + +void BacklogLoop(void) { + if (TimeReached(backlog_delay)) { + if (!BACKLOG_EMPTY && !backlog_mutex) { + backlog_mutex = true; + bool nodelay = false; + bool nodelay_detected = false; + String cmd; + do { +#ifdef SUPPORT_IF_STATEMENT + cmd = backlog.shift(); +#else + cmd = backlog[backlog_pointer]; + backlog[backlog_pointer] = (const char*) nullptr; + backlog_pointer++; + if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } +#endif + nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY)); + if (nodelay_detected) { nodelay = true; } + } while (!BACKLOG_EMPTY && nodelay_detected); + if (!nodelay_detected) { ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); } + if (nodelay) { backlog_delay = 0; } + backlog_mutex = false; + } + } +} + +void SleepDelay(uint32_t mseconds) { + if (mseconds) { + for (uint32_t wait = 0; wait < mseconds; wait++) { + delay(1); + if (Serial.available()) { break; } + } + } else { + delay(0); + } +} + +void loop(void) { + uint32_t my_sleep = millis(); + + XdrvCall(FUNC_LOOP); + XsnsCall(FUNC_LOOP); + + OsWatchLoop(); + + ButtonLoop(); + SwitchLoop(); +#ifdef USE_DEVICE_GROUPS + DeviceGroupsLoop(); +#endif + BacklogLoop(); + + if (TimeReached(state_50msecond)) { + SetNextTimeInterval(state_50msecond, 50); +#ifdef ROTARY_V1 + RotaryHandler(); +#endif + 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 (TimeReached(state_second)) { + SetNextTimeInterval(state_second, 1000); + PerformEverySecond(); + XdrvCall(FUNC_EVERY_SECOND); + XsnsCall(FUNC_EVERY_SECOND); + } + + if (!serial_local) { SerialInput(); } + +#ifdef USE_ARDUINO_OTA + ArduinoOtaLoop(); +#endif + + uint32_t my_activity = millis() - my_sleep; + + if (Settings.flag3.sleep_normal) { + + SleepDelay(ssleep); + } else { + if (my_activity < (uint32_t)ssleep) { + SleepDelay((uint32_t)ssleep - my_activity); + } else { + if (global_state.network_down) { + SleepDelay(my_activity /2); + } + } + } + + if (!my_activity) { my_activity++; } + uint32_t loop_delay = ssleep; + 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 "/workspace/Tasmota/tasmota/sendemail.ino" +#ifdef USE_SENDMAIL + +#ifndef USE_ESP32MAIL + +#include "sendemail.h" +# 27 "/workspace/Tasmota/tasmota/sendemail.ino" +#ifndef SEND_MAIL_MINRAM +#define SEND_MAIL_MINRAM 12*1024 +#endif + +void script_send_email_body(void(*func)(char *)); + +#define xPSTR(a) a + +uint16_t SendMail(char *buffer) { + char *params,*oparams; + const char *mserv; + uint16_t port; + 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; + + + + 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; +} + + + +#ifdef ESP8266 +WiFiClient *g_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)) { +} +#else +WiFiClient *g_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 WiFiClientSecure()) { +} +#endif + +String SendEmail::readClient() { + delay(0); + String r = client->readStringUntil('\n'); + + r.trim(); + while (client->available()) { + delay(0); + r += client->readString(); + } + return r; +} + +bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { +bool status=false; +String buffer; + + if (!host.length()) { + return status; + } + + client->setTimeout(timeout); + +#ifdef DEBUG_EMAIL_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 + AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); +#endif + goto exit; + } + + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("220"))) { + goto exit; + } + + buffer = F("EHLO "); + buffer += client->localIP().toString(); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + 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("AUTH LOGIN"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("334"))) + { + goto exit; + } + base64 b; + buffer = b.encode(user); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("334"))) { + goto exit; + } + buffer = b.encode(passwd); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("235"))) { + goto exit; + } + } + + + buffer = F("MAIL FROM:"); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("250"))) { + goto exit; + } + buffer = F("RCPT TO:"); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("250"))) { + goto exit; + } + + buffer = F("DATA"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("354"))) { + goto exit; + } + + buffer = F("MIME-Version: 1.0\r\n"); + client->print(buffer); + buffer = F("Content-Type: Multipart/mixed; boundary=frontier\r\n"); + client->print(buffer); + + buffer = F("From: "); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = F("To: "); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + 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 + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + + +#ifdef USE_SCRIPT + if (*msg=='*' && *(msg+1)==0) { + g_client=client; + script_send_email_body(xsend_message_txt); + } else { + client->println(msg); + } +#else + client->println(msg); +#endif + client->println('.'); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + + buffer = F("QUIT"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + + status=true; +exit: + + return status; +} + +void xsend_message_txt(char *msg) { +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),msg); +#endif +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + if (*msg=='@') { + msg++; + attach_File(msg); + } else if (*msg=='&') { + msg++; + attach_Array(msg); + } else { + g_client->print(F("--frontier\r\n")); + g_client->print(F("Content-Type: text/plain\r\n\r\n")); + g_client->println(msg); + g_client->print(F("\r\n--frontier\r\n")); + } +#else + if (*msg=='&') { + msg++; + attach_Array(msg); + } else { + g_client->print(F("--frontier\r\n")); + g_client->print(F("Content-Type: text/plain\r\n\r\n")); + g_client->println(msg); + g_client->print(F("\r\n--frontier\r\n")); + } +#endif +} + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +#include +extern FS *fsp; + +void attach_File(char *path) { + g_client->print(F("--frontier\r\n")); + g_client->print(F("Content-Type: text/plain\r\n")); + char buff[64]; + char *cp = path; + while (*cp=='/') cp++; + File file = fsp->open(path, "r"); + if (file) { + sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"), cp); + g_client->write(buff); + uint16_t flen = file.size(); + uint8_t fbuff[64]; + uint16_t blen = sizeof(fbuff); + while (flen>0) { + file.read(fbuff, blen); + flen -= blen; + g_client->write(fbuff, blen); + if (flenprint(F("\r\n\r\nfile not found!\r\n")); + } + g_client->print(F("\r\n--frontier\r\n")); +} + +#endif + +float *get_array_by_name(char *name, uint16_t *alen); +void flt2char(float num, char *nbuff); + +void attach_Array(char *aname) { + float *array = 0; + uint16_t alen; + array = get_array_by_name(aname, &alen); + g_client->print(F("--frontier\r\n")); + g_client->print(F("Content-Type: text/plain\r\n")); + if (array && alen) { +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("array found %d"),alen); +#endif + char buff[64]; + sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s.txt\"\r\n\r\n"), aname); + g_client->write(buff); + + strcpy(buff, GetDateAndTime(DT_LOCAL).c_str()); + strcat(buff,"\t"); + g_client->write(buff); + + float *fp=array; + for (uint32_t cnt = 0; cntwrite(nbuff, strlen(nbuff)); + } + } else { + g_client->print(F("\r\n\r\narray not found!\r\n")); + } + g_client->print(F("\r\n--frontier\r\n")); +} + +#else +# 507 "/workspace/Tasmota/tasmota/sendemail.ino" +#include "ESP32_MailClient.h" +#include "SD.h" + + + + +#ifndef SEND_MAIL32_MINRAM +#define SEND_MAIL32_MINRAM 30*1024 +#endif + +void script_send_email_body(void(*func)(char *)); + +#define xPSTR(a) a + +SMTPData smtpData; +#define MAX_ATTCHMENTS 8 +char *attachments[MAX_ATTCHMENTS]; +uint8_t num_attachments; + + + + + +uint16_t SendMail(char *buffer) { + char *params,*oparams; + const char *mserv; + uint16_t port; + const char *user; + const char *pstr; + const char *passwd; + const char *from; + const char *to; + const char *subject; + const char *cmd; + uint16_t status=1; + uint16_t blen; + char *endcmd; + + + uint32_t mem=ESP.getFreeHeap(); + + if (mempicmax) cnt=1; + len=WcGetPicstore(cnt-1,&buff); + if (len) { + char str[12]; + sprintf(str,"img_%1d.jpg",cnt+1); + smtpData.addAttachData(str, "image/jpg",buff,len); + } +#endif + } else { + smtpData.addMessage(txt); + } +} +# 828 "/workspace/Tasmota/tasmota/sendemail.ino" +#endif + + +#endif +# 1 "/workspace/Tasmota/tasmota/settings.ino" +# 24 "/workspace/Tasmota/tasmota/settings.ino" +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(RtcSettings); i++) { + crc += bytes[i]*(i+1); + } + return crc; +} + +void RtcSettingsSave(void) +{ + if (GetRtcSettingsCrc() != rtc_settings_crc) { + RtcSettings.valid = RTC_MEM_VALID; +#ifdef ESP8266 + ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); +#else + RtcDataSettings = RtcSettings; +#endif + rtc_settings_crc = GetRtcSettingsCrc(); + } +} + +void RtcSettingsLoad(void) +{ +#ifdef ESP8266 + ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); +#else + RtcSettings = RtcDataSettings; +#endif + if (RtcSettings.valid != RTC_MEM_VALID) { + memset(&RtcSettings, 0, sizeof(RtcSettings)); + 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(RtcReboot); i++) { + crc += bytes[i]*(i+1); + } + return crc; +} + +void RtcRebootSave(void) +{ + if (GetRtcRebootCrc() != rtc_reboot_crc) { + RtcReboot.valid = RTC_MEM_VALID; +#ifdef ESP8266 + ESP.rtcUserMemoryWrite(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); +#else + RtcDataReboot = RtcReboot; +#endif + rtc_reboot_crc = GetRtcRebootCrc(); + } +} + +void RtcRebootReset(void) +{ + RtcReboot.fast_reboot_count = 0; + RtcRebootSave(); +} + +void RtcRebootLoad(void) +{ +#ifdef ESP8266 + ESP.rtcUserMemoryRead(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); +#else + RtcReboot = RtcDataReboot; +#endif + if (RtcReboot.valid != RTC_MEM_VALID) { + memset(&RtcReboot, 0, sizeof(RtcReboot)); + RtcReboot.valid = RTC_MEM_VALID; + + RtcRebootSave(); + } + rtc_reboot_crc = GetRtcRebootCrc(); +} + +bool RtcRebootValid(void) +{ + return (RTC_MEM_VALID == RtcReboot.valid); +} +# 155 "/workspace/Tasmota/tasmota/settings.ino" +extern "C" { +#include "spi_flash.h" +} +#include "eboot_command.h" + +#ifdef ESP8266 + +#if AUTOFLASHSIZE + +#include "flash_hal.h" + + +const uint32_t SPIFFS_END = (FS_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; + +#endif + + +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) +{ +#ifdef ESP8266 + 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; +#endif +} + +bool VersionCompatible(void) +{ +#ifdef ESP8266 + + if (Settings.flag3.compatibility_check) { + return true; + } + + eboot_command ebcmd; + eboot_command_read(&ebcmd); + uint32_t start_address = ebcmd.args[0]; + uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; + uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; + + uint32_t version[3] = { 0 }; + bool found = false; + for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { + ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); + if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { + version[1] = 0xFFFFFFFF; + found = true; + } else { + for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { + version[0] = version[1]; + version[1] = version[2]; + version[2] = buffer[i]; + if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { + found = true; + break; + } + } + } + if (found) { break; } + } + delete[] buffer; + + if (!found) { version[1] = 0; } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); + + if (version[1] < VERSION_COMPATIBLE) { + uint32_t eboot_magic = 0; + ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); + return false; + } + +#endif + + return true; +} + +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(Settings); + 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(Settings) -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); +} + + + + + +void UpdateQuickPowerCycle(bool update) { +#ifndef FIRMWARE_MINIMAL + if (Settings.flag3.fast_power_cycle_disable) { return; } + + const uint32_t QPC_COUNT = 7; + const uint32_t QPC_SIGNATURE = 0xFFA55AFF; + +#ifdef ESP8266 + const uint32_t qpc_sector = SETTINGS_LOCATION - CFG_ROTATES; + const uint32_t qpc_location = qpc_sector * SPI_FLASH_SEC_SIZE; + + uint32_t qpc_buffer[QPC_COUNT +1]; + ESP.flashRead(qpc_location, (uint32*)&qpc_buffer, sizeof(qpc_buffer)); + if (update && (QPC_SIGNATURE == qpc_buffer[0])) { + uint32_t counter = 1; + while ((0 == qpc_buffer[counter]) && (counter <= QPC_COUNT)) { counter++; } + if (QPC_COUNT == counter) { + SettingsErase(3); + EspRestart(); + } else { + qpc_buffer[0] = 0; + ESP.flashWrite(qpc_location + (counter * 4), (uint32*)&qpc_buffer, 4); + AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter); + } + } + else if ((qpc_buffer[0] != QPC_SIGNATURE) || (0 == qpc_buffer[1])) { + qpc_buffer[0] = QPC_SIGNATURE; + + if (ESP.flashEraseSector(qpc_sector)) { + ESP.flashWrite(qpc_location, (uint32*)&qpc_buffer, 4); + AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset")); + } + } +#else + uint32_t pc_register; + QPCRead(&pc_register, sizeof(pc_register)); + if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AF0)) { + uint32_t counter = pc_register & 0xF; + if (0xF == counter) { counter = 0; } + counter++; + if (QPC_COUNT == counter) { + SettingsErase(3); + EspRestart(); + } else { + pc_register = 0xFFA55AF0 | counter; + QPCWrite(&pc_register, sizeof(pc_register)); + AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter); + } + } + else if (pc_register != QPC_SIGNATURE) { + pc_register = QPC_SIGNATURE; + QPCWrite(&pc_register, sizeof(pc_register)); + AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset")); + } +#endif + +#endif +} + + + + + +uint32_t GetSettingsTextLen(void) { + char* position = Settings.text_pool; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + } + return position - Settings.text_pool; +} + +bool settings_text_mutex = false; +uint32_t settings_text_busy_count = 0; + +bool SettingsUpdateFinished(void) { + uint32_t wait_loop = 10; + while (settings_text_mutex && wait_loop) { + yield(); + delayMicroseconds(1); + wait_loop--; + } + return (wait_loop > 0); +} + +bool SettingsUpdateText(uint32_t index, const char* replace_me) { + if (index >= SET_MAX) { + return false; + } + + + uint32_t replace_len = strlen_P(replace_me); + char replace[replace_len +1]; + memcpy_P(replace, replace_me, sizeof(replace)); + uint32_t index_save = index; + + uint32_t start_pos = 0; + uint32_t end_pos = 0; + char* position = Settings.text_pool; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + if (1 == index) { + start_pos = position - Settings.text_pool; + } + else if (0 == index) { + end_pos = position - Settings.text_pool -1; + } + index--; + } + uint32_t char_len = position - Settings.text_pool; + + uint32_t current_len = end_pos - start_pos; + int diff = replace_len - current_len; + + + + + int too_long = (char_len + diff) - settings_text_size; + if (too_long > 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); + return false; + } + + if (settings_text_mutex && !SettingsUpdateFinished()) { + settings_text_busy_count++; + } else { + settings_text_mutex = true; + + if (diff != 0) { + + memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); + } + + memmove_P(Settings.text_pool + start_pos, replace, replace_len); + + memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); + + settings_text_mutex = false; + } + +#ifdef DEBUG_FUNC_SETTINGSUPDATETEXT + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d, Busy %d, Id %02d = \"%s\""), GetSettingsTextLen(), settings_text_size, settings_text_busy_count, index_save, replace); +#else + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d, Busy %d"), GetSettingsTextLen(), settings_text_size, settings_text_busy_count); +#endif + + return true; +} + +char* SettingsText(uint32_t index) +{ + char* position = Settings.text_pool; + + if (index >= SET_MAX) { + position += settings_text_size -1; + } else { + SettingsUpdateFinished(); + for (;index > 0; index--) { + while (*position++ != '\0') { } + } + } + return position; +} + + + + + +void UpdateBackwardCompatibility(void) +{ + + strlcpy(Settings.user_template_name, SettingsText(SET_TEMPLATE_NAME), sizeof(Settings.user_template_name)); +} + +uint32_t GetSettingsAddress(void) +{ + return settings_location * SPI_FLASH_SEC_SIZE; +} + +void SettingsSave(uint8_t rotate) +{ +# 525 "/workspace/Tasmota/tasmota/settings.ino" +#ifndef FIRMWARE_MINIMAL + UpdateBackwardCompatibility(); + 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(Settings); + Settings.cfg_crc = GetSettingsCrc(); + Settings.cfg_crc32 = GetSettingsCrc32(); + +#ifdef ESP8266 + if (ESP.flashEraseSector(settings_location)) { + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + } + + 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(Settings)); +#else + SettingsWrite(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "Saved, " D_COUNT " %d, " D_BYTES " %d"), Settings.save_flag, sizeof(Settings)); +#endif + + settings_crc32 = Settings.cfg_crc32; + } +#endif + RtcSettingsSave(); +} + +void SettingsLoad(void) { +#ifdef ESP8266 + + + settings_location = 0; + uint32_t save_flag = 0; + uint32_t flash_location = SETTINGS_LOCATION; + for (uint32_t i = 0; i < CFG_ROTATES; i++) { + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + if ((Settings.cfg_crc32 != 0xFFFFFFFF) && (Settings.cfg_crc32 != 0x00000000) && (Settings.cfg_crc32 == GetSettingsCrc32())) { + if (Settings.save_flag > save_flag) { + save_flag = Settings.save_flag; + settings_location = flash_location; + if (Settings.flag.stop_flash_rotate && (0 == i)) { + break; + } + } + } + flash_location--; + delay(1); + } + if (settings_location > 0) { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); + } +#else + SettingsRead(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded, " D_COUNT " %lu"), Settings.save_flag); +#endif + +#ifndef FIRMWARE_MINIMAL + if ((0 == settings_location) || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { + SettingsDefault(); + } + settings_crc32 = GetSettingsCrc32(); +#endif + + RtcSettingsLoad(); +} + +void EspErase(uint32_t start_sector, uint32_t end_sector) +{ + bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); + for (uint32_t sector = start_sector; sector < end_sector; sector++) { + + bool result = ESP.flashEraseSector(sector); + + + + if (serial_output) { + Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); + delay(10); + } else { + yield(); + } + OsWatchLoop(); + } +} + +#ifdef ESP8266 +void SettingsErase(uint8_t type) +{ +# 654 "/workspace/Tasmota/tasmota/settings.ino" +#ifndef FIRMWARE_MINIMAL + uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; + uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; + if (1 == type) { + + _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; + } + else if (2 == type) { + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; + _sectorEnd = SETTINGS_LOCATION +1; + } + else if (3 == type) { + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; + _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; + } + else if (4 == type) { + + _sectorStart = SETTINGS_LOCATION +1; + _sectorEnd = _sectorStart +1; + } + + + + + + + else { + return; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); + + + EsptoolErase(_sectorStart, _sectorEnd); +#endif +} +#endif + +void SettingsSdkErase(void) +{ + WiFi.disconnect(false); + SettingsErase(1); + 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(Settings)); + + Settings.cfg_holder = (uint16_t)CFG_HOLDER; + Settings.cfg_size = sizeof(Settings); + + Settings.version = VERSION; + + +} + + +const uint8_t default_fingerprint1[] PROGMEM = { MQTT_FINGERPRINT1 }; +const uint8_t default_fingerprint2[] PROGMEM = { MQTT_FINGERPRINT2 }; + +void SettingsDefaultSet2(void) +{ + memset((char*)&Settings +16, 0x00, sizeof(Settings) -16); + + + SysBitfield flag = { 0 }; + SysBitfield2 flag2 = { 0 }; + SysBitfield3 flag3 = { 0 }; + SysBitfield4 flag4 = { 0 }; + SysBitfield5 flag5 = { 0 }; + +#ifdef ESP8266 + Settings.gpio16_converted = 0xF5A0; + +#endif +#ifdef ESP32 + Settings.config_version = 1; +#endif + + flag.stop_flash_rotate |= APP_FLASH_CYCLE; + flag.global_state |= APP_ENABLE_LEDLINK; + flag3.sleep_normal |= APP_NORMAL_SLEEP; + flag3.no_power_feedback |= APP_NO_RELAY_SCAN; + flag3.fast_power_cycle_disable |= APP_DISABLE_POWERCYCLE; + flag3.bootcount_update |= DEEPSLEEP_BOOTCOUNT; + flag3.compatibility_check |= OTA_COMPATIBILITY; + Settings.save_data = SAVE_DATA; + Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; + 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; + } + + + flag.interlock |= APP_INTERLOCK_MODE; + Settings.interlock[0] = APP_INTERLOCK_GROUP_1; + Settings.interlock[1] = APP_INTERLOCK_GROUP_2; + Settings.interlock[2] = APP_INTERLOCK_GROUP_3; + Settings.interlock[3] = APP_INTERLOCK_GROUP_4; + Settings.module = MODULE; + Settings.fallback_module = FALLBACK_MODULE; + ModuleDefault(WEMOS); + + SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME)); + SettingsUpdateText(SET_FRIENDLYNAME2, PSTR(FRIENDLY_NAME"2")); + SettingsUpdateText(SET_FRIENDLYNAME3, PSTR(FRIENDLY_NAME"3")); + SettingsUpdateText(SET_FRIENDLYNAME4, PSTR(FRIENDLY_NAME"4")); + SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); + SettingsUpdateText(SET_OTAURL, PSTR(OTA_URL)); + + + 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.ledpwm_on = 255; + + Settings.pulse_timer[0] = APP_PULSETIME; + + + + Settings.serial_config = TS_SERIAL_8N1; + Settings.baudrate = APP_BAUDRATE / 300; + Settings.sbaudrate = SOFT_BAUDRATE / 300; + Settings.serial_delimiter = 0xff; + Settings.seriallog_level = SERIAL_LOG_LEVEL; + + + flag4.network_ethernet |= 1; +#ifdef ESP32 + Settings.eth_type = ETH_TYPE; + Settings.eth_clk_mode = ETH_CLKMODE; + Settings.eth_address = ETH_ADDR; +#endif + + + flag4.network_wifi |= 1; + flag3.use_wifi_scan |= WIFI_SCAN_AT_RESTART; + flag3.use_wifi_rescan |= WIFI_SCAN_REGULARLY; + Settings.wifi_output_power = 170; + Settings.param[P_ARP_GRATUITOUS] = WIFI_ARP_INTERVAL; + 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; + + SettingsUpdateText(SET_STASSID1, PSTR(STA_SSID1)); + SettingsUpdateText(SET_STASSID2, PSTR(STA_SSID2)); + SettingsUpdateText(SET_STAPWD1, PSTR(STA_PASS1)); + SettingsUpdateText(SET_STAPWD2, PSTR(STA_PASS2)); + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + + + SettingsUpdateText(SET_SYSLOG_HOST, PSTR(SYS_LOG_HOST)); + Settings.syslog_port = SYS_LOG_PORT; + Settings.syslog_level = SYS_LOG_LEVEL; + + + flag2.emulation |= EMULATION; + flag4.alexa_gen_1 |= EMULATION_HUE_1ST_GEN; + flag3.gui_hostname_ip |= GUI_SHOW_HOSTNAME; + flag3.mdns_enabled |= MDNS_ENABLED; + Settings.webserver = WEB_SERVER; + Settings.weblog_level = WEB_LOG_LEVEL; + SettingsUpdateText(SET_WEBPWD, PSTR(WEB_PASSWORD)); + SettingsUpdateText(SET_CORS, PSTR(CORS_DOMAIN)); + + + flag.button_restrict |= KEY_DISABLE_MULTIPRESS; + flag.button_swap |= KEY_SWAP_DOUBLE_PRESS; + flag.button_single |= KEY_ONLY_SINGLE_PRESS; + Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; + + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } + + + flag.mqtt_enabled |= MQTT_USE; + flag.mqtt_response |= MQTT_RESULT_COMMAND; + flag.mqtt_offline |= MQTT_LWT_MESSAGE; + flag.mqtt_power_retain |= MQTT_POWER_RETAIN; + flag.mqtt_button_retain |= MQTT_BUTTON_RETAIN; + flag.mqtt_switch_retain |= MQTT_SWITCH_RETAIN; + flag.mqtt_sensor_retain |= MQTT_SENSOR_RETAIN; + + flag.device_index_enable |= MQTT_POWER_FORMAT; + flag3.time_append_timezone |= MQTT_APPEND_TIMEZONE; + flag3.button_switch_force_local |= MQTT_BUTTON_SWITCH_FORCE_LOCAL; + flag3.no_hold_retain |= MQTT_NO_HOLD_RETAIN; + flag3.use_underscore |= MQTT_INDEX_SEPARATOR; + flag3.grouptopic_mode |= MQTT_GROUPTOPIC_FORMAT; + SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); + Settings.mqtt_port = MQTT_PORT; + SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); + SettingsUpdateText(SET_MQTT_USER, MQTT_USER); + SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); + SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); + Settings.mqtt_retry = MQTT_RETRY_SECS; + SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); + SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); + SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); + SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); + SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); + memcpy_P(Settings.mqtt_fingerprint[0], default_fingerprint1, sizeof(default_fingerprint1)); + memcpy_P(Settings.mqtt_fingerprint[1], default_fingerprint2, sizeof(default_fingerprint2)); + Settings.tele_period = TELE_PERIOD; + Settings.mqttlog_level = MQTT_LOG_LEVEL; + + + flag.no_power_on_check |= ENERGY_VOLTAGE_ALWAYS; + flag2.current_resolution |= 3; + + + flag2.energy_resolution |= ENERGY_RESOLUTION; + flag3.dds2382_model |= ENERGY_DDS2382_MODE; + flag3.hardware_energy_total |= ENERGY_HARDWARE_TOTALS; + 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; +# 911 "/workspace/Tasmota/tasmota/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; + + + flag.ir_receive_decimal |= IR_DATA_RADIX; + flag3.receive_raw |= IR_ADD_RAW_DATA; + Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; + + + flag.rf_receive_decimal |= RF_DATA_RADIX; + + memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); + + + Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; +# 946 "/workspace/Tasmota/tasmota/settings.ino" + flag.temperature_conversion |= TEMP_CONVERSION; + flag.pressure_conversion |= PRESSURE_CONVERSION; + flag2.pressure_resolution |= PRESSURE_RESOLUTION; + flag2.humidity_resolution |= HUMIDITY_RESOLUTION; + flag2.temperature_resolution |= TEMP_RESOLUTION; + flag3.ds18x20_internal_pullup |= DS18X20_PULL_UP; + flag3.counter_reset_on_tele |= COUNTER_RESET; + + + + + + + flag2.calc_resolution |= CALC_RESOLUTION; + + + flag3.timers_enable |= TIMERS_ENABLED; + + + flag.hass_light |= HASS_AS_LIGHT; + flag.hass_discovery |= HOME_ASSISTANT_DISCOVERY_ENABLE; + flag3.hass_tele_on_power |= TELE_ON_POWER; + + + flag.knx_enabled |= KNX_ENABLED; + flag.knx_enable_enhancement |= KNX_ENHANCED; + + + flag.pwm_control |= LIGHT_MODE; + flag.ws_clock_reverse |= LIGHT_CLOCK_DIRECTION; + flag.light_signal |= LIGHT_PAIRS_CO2; + flag.not_power_linked |= LIGHT_POWER_CONTROL; + flag.decimal_text |= LIGHT_COLOR_RADIX; + flag3.pwm_multi_channels |= LIGHT_CHANNEL_MODE; + flag3.slider_dimmer_stay_on |= LIGHT_SLIDER_POWER; + flag4.alexa_ct_range |= LIGHT_ALEXA_CT_RANGE; + flag4.pwm_ct_mode |= LIGHT_PWM_CT_MODE; + flag4.white_blend_mode |= LIGHT_WHITE_BLEND_MODE; + flag4.virtual_ct |= LIGHT_VIRTUAL_CT; + flag4.virtual_ct_cw |= LIGHT_VIRTUAL_CT_CW; + + Settings.pwm_frequency = PWM_FREQ; + Settings.pwm_range = PWM_RANGE; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + Settings.light_color[i] = DEFAULT_LIGHT_COMPONENT; + + } + Settings.light_correction = 1; + Settings.light_dimmer = DEFAULT_LIGHT_DIMMER; + + Settings.light_speed = 1; + + Settings.light_width = 1; + + Settings.light_pixels = WS2812_LEDS; + + Settings.ws_width[WS_SECOND] = 1; + Settings.ws_color[WS_SECOND][WS_RED] = 255; + + Settings.ws_color[WS_SECOND][WS_BLUE] = 255; + Settings.ws_width[WS_MINUTE] = 3; + + Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; + + Settings.ws_width[WS_HOUR] = 5; + Settings.ws_color[WS_HOUR][WS_RED] = 255; + + + + Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; + Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; + + + + 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_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; + + + 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); + } + SettingsUpdateText(SET_NTPSERVER1, PSTR(NTP_SERVER1)); + SettingsUpdateText(SET_NTPSERVER2, PSTR(NTP_SERVER2)); + SettingsUpdateText(SET_NTPSERVER3, PSTR(NTP_SERVER3)); + for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { + SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); + } + Settings.latitude = (int)((double)LATITUDE * 1000000); + Settings.longitude = (int)((double)LONGITUDE * 1000000); + SettingsResetStd(); + SettingsResetDst(); + + 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_startingoffset = STARTING_OFFSET; + + SettingsDefaultWebColor(); + + memset(&Settings.monitors, 0xFF, 20); + SettingsEnableAllI2cDrivers(); + + + flag3.tuya_apply_o20 |= TUYA_SETOPTION_20; + flag3.tuya_serial_mqtt_publish |= MQTT_TUYA_RECEIVED; + + flag3.buzzer_enable |= BUZZER_ENABLE; + flag3.shutter_mode |= SHUTTER_SUPPORT; + flag3.pcf8574_ports_inverted |= PCF8574_INVERT_PORTS; + flag4.zigbee_use_names |= ZIGBEE_FRIENDLY_NAMES; + flag4.remove_zbreceived |= ZIGBEE_RMV_ZBRECEIVED; + flag4.zb_index_ep |= ZIGBEE_INDEX_EP; + flag4.mqtt_tls |= MQTT_TLS_ENABLED; + flag4.mqtt_no_retain |= MQTT_NO_RETAIN; + +#ifdef USER_TEMPLATE + JsonTemplate((char *)USER_TEMPLATE); +#endif + + Settings.flag = flag; + Settings.flag2 = flag2; + Settings.flag3 = flag3; + Settings.flag4 = flag4; +} + + + +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 SettingsDefaultWebColor(void) +{ + char scolor[10]; + for (uint32_t i = 0; i < COL_LAST; i++) { + WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); + } +} + +void SettingsEnableAllI2cDrivers(void) +{ + Settings.i2c_drivers[0] = 0xFFFFFFFF; + Settings.i2c_drivers[1] = 0xFFFFFFFF; + Settings.i2c_drivers[2] = 0xFFFFFFFF; +} + + + +void SettingsDelta(void) +{ + if (Settings.version != VERSION) { + +#ifdef ESP8266 + if (Settings.version < 0x07000002) { + Settings.web_color2[0][0] = Settings.web_color[0][0]; + Settings.web_color2[0][1] = Settings.web_color[0][1]; + Settings.web_color2[0][2] = Settings.web_color[0][2]; + } + if (Settings.version < 0x07000003) { + SettingsEnableAllI2cDrivers(); + } + if (Settings.version < 0x07000004) { + Settings.ex_wifi_output_power = 170; + } + if (Settings.version < 0x07010202) { + Settings.ex_serial_config = TS_SERIAL_8N1; + } + if (Settings.version < 0x07010204) { + if (Settings.flag3.mqtt_buttons == 1) { + strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); + } else { + Settings.ex_cors_domain[0] = 0; + } + } + if (Settings.version < 0x07010205) { + Settings.seriallog_level = Settings.ex_seriallog_level; + Settings.sta_config = Settings.ex_sta_config; + Settings.sta_active = Settings.ex_sta_active; + memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); + } + if (Settings.version < 0x07010206) { + Settings.flag4 = Settings.ex_flag4; + Settings.mqtt_port = Settings.ex_mqtt_port; + memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); + } + if (Settings.version < 0x08000000) { + char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); + char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); + char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); + char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); + char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); + char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); + char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); + char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); + char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); + char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); + char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); + char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); + char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); + char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); + char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); + char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); + char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); + + memset(Settings.text_pool, 0x00, settings_text_size); + SettingsUpdateText(SET_OTAURL, temp); + SettingsUpdateText(SET_MQTTPREFIX1, temp21); + SettingsUpdateText(SET_MQTTPREFIX2, temp22); + SettingsUpdateText(SET_MQTTPREFIX3, temp23); + SettingsUpdateText(SET_STASSID1, temp31); + SettingsUpdateText(SET_STASSID2, temp32); + SettingsUpdateText(SET_STAPWD1, temp41); + SettingsUpdateText(SET_STAPWD2, temp42); + SettingsUpdateText(SET_HOSTNAME, temp5); + SettingsUpdateText(SET_SYSLOG_HOST, temp6); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (!strlen(Settings.ex_mqtt_user)) { + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_USER, temp9); + } else { + char aws_mqtt_host[66]; + snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); + SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); + SettingsUpdateText(SET_MQTT_USER, ""); + } +#else + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_USER, temp9); +#endif + SettingsUpdateText(SET_MQTT_CLIENT, temp8); + SettingsUpdateText(SET_MQTT_PWD, temp10); + SettingsUpdateText(SET_MQTT_TOPIC, temp11); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); + + SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); + SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); + SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); + + SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); + SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); + SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); + SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); + SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); + SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); + SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); + SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); + SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); + SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); + SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); + SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); + + + + + } + if (Settings.version < 0x08020003) { + SettingsUpdateText(SET_TEMPLATE_NAME, Settings.user_template_name); + Settings.zb_channel = 0; + } +#endif + + if (Settings.version < 0x08020004) { + Settings.flag3.mqtt_buttons = 0; +#ifdef ESP8266 + Settings.config_version = 0; +#endif +#ifdef ESP32 + Settings.config_version = 1; +#endif + } + if (Settings.version < 0x08020006) { +#ifdef ESP32 + Settings.module = WEMOS; + ModuleDefault(WEMOS); +#endif + + if (Settings.rules[0][0] == 0) { Settings.rules[0][1] = 0; } + if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; } + if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; } + } + if (Settings.version < 0x08030002) { + SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 255; + Settings.ledpwm_mask = 0; + } + if (Settings.version < 0x08030104) { + Settings.flag4.network_wifi = 1; + Settings.flag4.network_ethernet = 1; + } +#ifdef ESP32 + if (Settings.version < 0x08030105) { + Settings.eth_type = ETH_TYPE; + Settings.eth_clk_mode = ETH_CLKMODE; + Settings.eth_address = ETH_ADDR; + } +#endif + if (Settings.version < 0x08030106) { + Settings.fallback_module = FALLBACK_MODULE; + } + if (Settings.version < 0x08040003) { + Settings.energy_power_delta[0] = Settings.hass_new_discovery; + Settings.energy_power_delta[1] = 0; + Settings.energy_power_delta[2] = 0; + } +#ifdef ESP8266 + if (Settings.version < 0x09000002) { + char parameters[32]; + snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"), + Settings.ex_adc_param_type, Settings.ex_adc_param1, Settings.ex_adc_param2, Settings.ex_adc_param3, Settings.ex_adc_param4); + SettingsUpdateText(SET_ADC_PARAM1, parameters); + } +#endif + + Settings.version = VERSION; + SettingsSave(1); + } + +} +# 1 "/workspace/Tasmota/tasmota/support.ino" +# 20 "/workspace/Tasmota/tasmota/support.ino" +IPAddress syslog_host_addr; +uint32_t syslog_host_hash = 0; + +extern "C" { +extern struct rst_info resetInfo; +} + + + + + +#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 = t - oswatch_last_loop_time; + +#ifdef DEBUG_THEO + int32_t rssi = WiFi.RSSI(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP_getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); +#endif + if (last_run >= (OSWATCH_RESET_TIME * 1000)) { + + RtcSettings.oswatch_blocked_loop = 1; + RtcSettingsSave(); + + + + + + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); + } +} + +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(); + +} + +bool OsWatchBlockedLoop(void) +{ + return oswatch_blocked_loop; +} + +uint32_t ResetReason(void) +{ +# 102 "/workspace/Tasmota/tasmota/support.ino" + return ESP_ResetInfoReason(); +} + +String GetResetReason(void) +{ + if (oswatch_blocked_loop) { + char buff[32]; + strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); + return String(buff); + } else { + return ESP_getResetReason(); + } +} +# 132 "/workspace/Tasmota/tasmota/support.ino" +String GetBinary8(uint8_t value, size_t count) { + if (count > 8) { count = 8; } + value <<= (8 - count); + String result; + result.reserve(count + 1); + for (uint32_t i = 0; i < count; i++) { + result += (value &0x80) ? '1' : '0'; + value <<= 1; + } + return result; +} + + +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; +} + +uint32_t ChrCount(const char *str, const char *delim) { + uint32_t count = 0; + char* read = (char*)str; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (ch == *delim) { count++; } + } + return count; +} + + +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; + if (*pt == '\0') { return 0.0; } + + 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++; + uint32_t max_decimals = 0; + while ((max_decimals < 8) && isdigit(pt[max_decimals])) { max_decimals++; } + pt[max_decimals] = '\0'; + 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; + + + + do { + int 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* RemoveControlCharacter(char* p) { + + char* write = p; + char* read = p; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (!iscntrl(ch)) { + *write++ = ch; + } + } + *write++ = '\0'; + return p; +} + +char* ReplaceCommaWithDot(char* p) { + + char* write = (char*)p; + char* read = (char*)p; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (ch == ',') { + 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) +{ + if (*p != '\0') { + while ((*p != '\0') && isblank(*p)) { p++; } + char* q = p + strlen(p) -1; + while ((q >= p) && isblank(*q)) { q--; } + q++; + *q = '\0'; + } + return p; +} +# 479 "/workspace/Tasmota/tasmota/support.ino" +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(void) +{ + + + + + + + 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(void) +{ + 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); +} + +uint32_t ParseParameters(uint32_t count, uint32_t *params) +{ + char *p; + uint32_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p), i++) { + params[i] = strtoul(str, nullptr, 0); + } + return i; +} + + +bool NewerVersion(char* version_str) +{ + uint32_t version = 0; + uint32_t i = 0; + char *str_ptr; + + char version_dup[strlen(version_str) +1]; + strncpy(version_dup, version_str, sizeof(version_dup)); + + 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)) { + 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++; + } + } + + + 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) +{ + strncpy_P(dest, S_RSLT_POWER, size); + if ((devices_present + option) > 1) { + char sidx[8]; + 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); +} + +void GetEspHardwareType(void) +{ +#ifdef ESP8266 + + uint32_t efuse1 = *(uint32_t*)(0x3FF00050); + uint32_t efuse2 = *(uint32_t*)(0x3FF00054); + + + + is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); + if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { + is_8285 = false; + } +#else + is_8285 = false; +#endif +} + +String GetDeviceHardware(void) +{ + char buff[10]; +#ifdef ESP8266 + if (is_8285) { + strcpy_P(buff, PSTR("ESP8285")); + } else { + strcpy_P(buff, PSTR("ESP8266EX")); + } +#else + strcpy_P(buff, PSTR("ESP32")); +#endif + return String(buff); +} + +float ConvertTemp(float c) +{ + float result = c; + + global_update = uptime; + global_temperature_celsius = c; + + if (!isnan(c) && Settings.flag.temperature_conversion) { + result = c * 1.8 + 32; + } + result = result + (0.1 * Settings.temp_comp); + return result; +} + +float ConvertTempToCelsius(float c) +{ + float result = c; + + if (!isnan(c) && Settings.flag.temperature_conversion) { + result = (c - 32) / 1.8; + } + result = result + (0.1 * Settings.temp_comp); + return result; +} + +char TempUnit(void) +{ + + return (Settings.flag.temperature_conversion) ? D_UNIT_FAHRENHEIT[0] : D_UNIT_CELSIUS[0]; +} + +float ConvertHumidity(float h) +{ + float result = h; + + global_update = uptime; + global_humidity = h; + + result = result + (0.1 * Settings.hum_comp); + + return result; +} + +float CalcTempHumToDew(float t, float h) +{ + if (isnan(h) || isnan(t)) { return NAN; } + + if (Settings.flag.temperature_conversion) { + t = (t - 32) / 1.8; + } + + float gamma = TaylorLog(h / 100) + 17.62 * t / (243.5 + t); + float result = (243.5 * gamma / (17.62 - gamma)); + + if (Settings.flag.temperature_conversion) { + result = result * 1.8 + 32; + } + return result; +} + +float ConvertPressure(float p) +{ + float result = p; + + global_update = uptime; + global_pressure_hpa = 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); +} + +float ConvertSpeed(float s) +{ + + return s * kSpeedConversionFactor[Settings.flag2.speed_conversion]; +} + +String SpeedUnit(void) +{ + char speed[8]; + return String(GetTextIndexed(speed, sizeof(speed), Settings.flag2.speed_conversion, kSpeedUnit)); +} + +void ResetGlobalValues(void) +{ + if ((uptime - global_update) > GLOBAL_VALUES_VALID) { + global_update = 0; + global_temperature_celsius = NAN; + global_humidity = 0.0f; + global_pressure_hpa = 0.0f; + } +} + +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); + if (prefix_length) { + char prefix[prefix_length +1]; + snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); + if (strcasecmp(prefix, XdrvMailbox.command)) { + return false; + } + } + 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 "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" + "ON|" D_ON "|TRUE|" D_TRUE "|START|" 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,0,0, + 1,1,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; +} + +String GetSerialConfig(void) { + + + + + + const char kParity[] = "NEOI"; + + char config[4]; + config[0] = '5' + (Settings.serial_config & 0x3); + config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; + config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); + config[3] = '\0'; + return String(config); +} + +void SetSerialBegin(void) { + baudrate = Settings.baudrate * 300; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); + Serial.flush(); + Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); +} + +void SetSerialConfig(uint32_t serial_config) { + if (serial_config > TS_SERIAL_8O2) { + serial_config = TS_SERIAL_8N1; + } + if (serial_config != Settings.serial_config) { + Settings.serial_config = serial_config; + SetSerialBegin(); + } +} + +void SetSerialBaudrate(uint32_t ubaudrate) { + baudrate = ubaudrate; + Settings.baudrate = baudrate / 300; + if (Serial.baudRate() != baudrate) { + SetSerialBegin(); + } +} + +void SetSerial(uint32_t ubaudrate, uint32_t serial_config) { + Settings.flag.mqtt_serial = 0; + Settings.serial_config = serial_config; + baudrate = ubaudrate; + Settings.baudrate = baudrate / 300; + SetSeriallog(LOG_LEVEL_NONE); + SetSerialBegin(); +} + +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 > 1) { + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, &p, 16); + Serial.write(code); + size -= 2; + codes += 2; + } +} + + +void SerialSendDecimal(char *values) +{ + char *p; + uint8_t code; + for (char* str = strtok_r(values, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { + code = (uint8_t)atoi(str); + Serial.write(code); + } +} + +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); + + + + + + + uint32_t j = sizeof(Settings.web_color) / 3; +# 1027 "/workspace/Tasmota/tasmota/support.ino" + if (i >= j) { + + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + 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 j = sizeof(Settings.web_color) / 3; + + + + + if (i >= j) { + + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + 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; + case 3: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL_MILLIS).c_str()); + 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 ResponseAppendTHD(float f_temperature, float f_humidity) +{ + char temperature[FLOATSZ]; + dtostrfd(f_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[FLOATSZ]; + dtostrfd(f_humidity, Settings.flag2.humidity_resolution, humidity); + char dewpoint[FLOATSZ]; + dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings.flag2.temperature_resolution, dewpoint); + + return ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_DEWPOINT "\":%s"), temperature, humidity, dewpoint); +} + +int ResponseJsonEnd(void) +{ + return ResponseAppend_P(PSTR("}")); +} + +int ResponseJsonEndEnd(void) +{ + return ResponseAppend_P(PSTR("}}")); +} + + + + + +#ifdef ESP8266 +uint16_t GpioConvert(uint8_t gpio) { + if (gpio > ARRAY_SIZE(kGpioConvert)) { + return AGPIO(GPIO_USER); + } + return pgm_read_word(kGpioConvert + gpio); +} + +uint16_t Adc0Convert(uint8_t adc0) { + if (adc0 > 7) { + return AGPIO(GPIO_USER); + } + else if (0 == adc0) { + return GPIO_NONE; + } + return AGPIO(GPIO_ADC_INPUT + adc0 -1); +} + +void TemplateConvert(uint8_t template8[], uint16_t template16[]) { + for (uint32_t i = 0; i < (sizeof(mytmplt) / 2) -2; i++) { + template16[i] = GpioConvert(template8[i]); + } + template16[(sizeof(mytmplt) / 2) -2] = Adc0Convert(template8[sizeof(mytmplt8285) -1]); + + + + +} + +void ConvertGpios(void) { + if (Settings.gpio16_converted != 0xF5A0) { + + TemplateConvert((uint8_t*)&Settings.ex_user_template8, (uint16_t*)&Settings.user_template); + + for (uint32_t i = 0; i < sizeof(Settings.ex_my_gp8.io); i++) { + Settings.my_gp.io[i] = GpioConvert(Settings.ex_my_gp8.io[i]); + } + Settings.my_gp.io[(sizeof(myio) / 2) -1] = Adc0Convert(Settings.ex_my_adc0); + Settings.gpio16_converted = 0xF5A0; + + + + + } +} +# 1231 "/workspace/Tasmota/tasmota/support.ino" +#endif + +uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index = 0); +uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) { + uint16_t real_gpio = gpio << 5; + uint16_t mask = 0xFFE0; + if (index < GPIO_ANY) { + real_gpio += index; + mask = 0xFFFF; + } + for (uint32_t i = 0; i < ARRAY_SIZE(gpio_pin); i++) { + if ((gpio_pin[i] & mask) == real_gpio) { + return i; + } + } + return 99; +} + +bool PinUsed(uint32_t gpio, uint32_t index = 0); +bool PinUsed(uint32_t gpio, uint32_t index) { + return (Pin(gpio, index) < 99); +} + +uint32_t GetPin(uint32_t lpin) { + if (lpin < ARRAY_SIZE(gpio_pin)) { + return gpio_pin[lpin]; + } else { + return GPIO_NONE; + } +} + +void SetPin(uint32_t lpin, uint32_t gpio) { + gpio_pin[lpin] = gpio; +} + +void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) +{ + if (PinUsed(gpio_pin, index)) { + digitalWrite(Pin(gpio_pin, index), state &1); + } +} + +uint8_t ModuleNr(void) +{ + + + 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); +} + +bool ValidTemplate(const char *search) { + char template_name[strlen(SettingsText(SET_TEMPLATE_NAME)) +1]; + char search_name[strlen(search) +1]; + + LowerCase(template_name, SettingsText(SET_TEMPLATE_NAME)); + LowerCase(search_name, search); + + return (strstr(template_name, search_name) != nullptr); +} + +String AnyModuleName(uint32_t index) +{ + if (USER_MODULE == index) { + return String(SettingsText(SET_TEMPLATE_NAME)); + } else { + char name[TOPSZ]; + return String(GetTextIndexed(name, sizeof(name), index, kModuleNames)); + } +} + +String ModuleName(void) +{ + return AnyModuleName(Settings.module); +} + +#ifdef ESP8266 +void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option) { + uint8_t module_template = pgm_read_byte(kModuleTemplateList + module); + + + + + uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE }; + if (module_template < TMP_WEMOS) { + memcpy_P(&template8, &kModules8266[module_template], 6); + memcpy_P(&template8[8], &kModules8266[module_template].gp.io[6], 6); + } else { + memcpy_P(&template8, &kModules8285[module_template - TMP_WEMOS], sizeof(template8)); + } + + + + + uint16_t template16[(sizeof(mytmplt) / 2)] = { GPIO_NONE }; + TemplateConvert(template8, template16); + + uint32_t index = 0; + uint32_t size = sizeof(mycfgio); + switch (option) { + case 2: { + index = (sizeof(mytmplt) / 2) -1; + size = 2; + break; + } + case 3: { + size = sizeof(mytmplt); + break; + } + } + memcpy(ptr, &template16[index], size); + + + +} +#endif + +void ModuleGpios(myio *gp) +{ + uint16_t *dest = (uint16_t *)gp; + uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)]; + + memset(dest, GPIO_NONE, sizeof(myio)); + if (USER_MODULE == Settings.module) { + memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); + } else { +#ifdef ESP8266 + GetInternalTemplate(&src, Settings.module, 1); +#else + memcpy_P(&src, &kModules.gp, sizeof(mycfgio)); +#endif + } + + + + + uint32_t j = 0; + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + dest[j] = src[i]; + j++; + } + + + +} + +gpio_flag ModuleFlag(void) +{ + gpio_flag flag; + + if (USER_MODULE == Settings.module) { + flag = Settings.user_template.flag; + } else { +#ifdef ESP8266 + GetInternalTemplate(&flag, Settings.module, 2); +#else + memcpy_P(&flag, &kModules.flag, sizeof(gpio_flag)); +#endif + } + + return flag; +} + +void ModuleDefault(uint32_t module) +{ + if (USER_MODULE == module) { module = WEMOS; } + Settings.user_template_base = module; + char name[TOPSZ]; + SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames)); +#ifdef ESP8266 + GetInternalTemplate(&Settings.user_template, module, 3); +#else + memcpy_P(&Settings.user_template, &kModules, sizeof(mytmplt)); +#endif +} + +void SetModuleType(void) +{ + my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; +} + +bool FlashPin(uint32_t pin) +{ + return (((pin > 5) && (pin < 9)) || (11 == pin)); +} + +uint32_t ValidPin(uint32_t pin, uint32_t gpio) +{ + if (FlashPin(pin)) { + return GPIO_NONE; + } + + + if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { + if ((9 == pin) || (10 == pin)) { + return GPIO_NONE; + } + } + + return gpio; +} + +bool ValidGPIO(uint32_t pin, uint32_t gpio) +{ +#ifdef ESP8266 +#ifdef USE_ADC_VCC + if (ADC0_PIN == pin) { return false; } +#endif +#endif + return (GPIO_USER == ValidPin(pin, BGPIO(gpio))); +} + +bool GetUsedInModule(uint32_t val, uint16_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(char* dataBuf) +{ + + + + + + if (strlen(dataBuf) < 9) { return false; } + + JsonParser parser((char*) dataBuf); + JsonParserObject root = parser.getRootObject(); + if (!root) { return false; } + + + JsonParserToken val = root[PSTR(D_JSON_NAME)]; + if (val) { + SettingsUpdateText(SET_TEMPLATE_NAME, val.getStr()); + } + JsonParserArray arr = root[PSTR(D_JSON_GPIO)]; + if (arr) { +#ifdef ESP8266 + bool old_template = false; + uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE }; + if (13 == arr.size()) { + uint32_t gpio = 0; + for (uint32_t i = 0; i < ARRAY_SIZE(template8) -1; i++) { + gpio = arr[i].getUInt(); + if (gpio > 255) { + break; + } + template8[i] = gpio; + } + old_template = (gpio < 256); + } + if (old_template) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TPL: Converting template ...")); + + val = root[PSTR(D_JSON_FLAG)]; + if (val) { + template8[ARRAY_SIZE(template8) -1] = val.getUInt() & 0x0F; + } + TemplateConvert(template8, Settings.user_template.gp.io); + Settings.user_template.flag.data = 0; + } else { +#endif + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + JsonParserToken val = arr[i]; + if (!val) { break; } + uint16_t gpio = val.getUInt(); + if (gpio == (AGPIO(GPIO_NONE) +1)) { + gpio = AGPIO(GPIO_USER); + } + Settings.user_template.gp.io[i] = gpio; + } + val = root[PSTR(D_JSON_FLAG)]; + if (val) { + Settings.user_template.flag.data = val.getUInt(); + } + } +#ifdef ESP8266 + } +#endif + val = root[PSTR(D_JSON_BASE)]; + if (val) { + uint32_t base = val.getUInt(); + if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } + Settings.user_template_base = base -1; + } + + + + + return true; +} + +void TemplateJson(void) +{ + + + + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME)); + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + uint16_t gpio = Settings.user_template.gp.io[i]; + if (gpio == AGPIO(GPIO_USER)) { + gpio = AGPIO(GPIO_NONE) +1; + } + ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", gpio); + } + ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); +} + + + + + +inline int32_t TimeDifference(uint32_t prev, uint32_t next) +{ + return ((int32_t) (next - prev)); +} + +int32_t TimePassedSince(uint32_t timestamp) +{ + + + return TimeDifference(timestamp, millis()); +} + +bool TimeReached(uint32_t 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); +} + +int32_t TimePassedSinceUsec(uint32_t timestamp) +{ + return TimeDifference(timestamp, micros()); +} + +bool TimeReachedUsec(uint32_t timer) +{ + + const long passed = TimePassedSinceUsec(timer); + return (passed >= 0); +} + + + + + +#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) +{ + 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--; + } + if (!retry) Wire.endTransmission(); + 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 "\"}")); + } +} + +void I2cResetActive(uint32_t addr, uint32_t count = 1) +{ + addr &= 0x7F; + count &= 0x7F; + while (count-- && (addr < 128)) { + i2c_active[addr / 32] &= ~(1 << (addr % 32)); + addr++; + } + +} + +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++; + } + +} + +void I2cSetActiveFound(uint32_t addr, const char *types) +{ + I2cSetActive(addr); + AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr); +} + +bool I2cActive(uint32_t addr) +{ + addr &= 0x7F; + if (i2c_active[addr / 32] & (1 << (addr % 32))) { + return true; + } + return false; +} + +bool I2cSetDevice(uint32_t addr) +{ + addr &= 0x7F; + if (I2cActive(addr)) { + return false; + } + Wire.beginTransmission((uint8_t)addr); + return (0 == Wire.endTransmission()); +} +#endif +# 1919 "/workspace/Tasmota/tasmota/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) +{ + + + uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; + WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); + } + if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { + char syslog_preamble[64]; + snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), NetworkHostname()); + 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) && + (masterlog_level <= seriallog_level)) { + Serial.printf("%s%s\r\n", mxtime, log_data); + } +#ifdef USE_WEBSERVER + if (Settings.webserver && + (loglevel <= Settings.weblog_level) && + (masterlog_level <= 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 (Settings.flag.mqtt_enabled && + !global_state.mqtt_down && + (loglevel <= Settings.mqttlog_level) && + (masterlog_level <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } + + if (!global_state.network_down && + (loglevel <= syslog_level) && + (masterlog_level <= syslog_level)) { Syslog(); } + + prepped_loglevel = 0; +} + +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 PrepLog_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); + + prepped_loglevel = 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) +{ +# 2087 "/workspace/Tasmota/tasmota/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(const char *sensor, uint32_t misses) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); +} + +void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size) { + snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); + for (uint32_t i = 0; i < count; i++) { + if (1 == size) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer)); + } else { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X%02X"), log_data, *(buffer +1), *(buffer)); + } + buffer += size; + } + AddLog(loglevel); +} + + + + + +#ifdef USE_UNISHOX_COMPRESSION + +#include + +Unishox compressor; + +String Decompress(const char * compressed, size_t uncompressed_size) { + String content(""); + + uncompressed_size += 2; + + + + + + content.reserve(uncompressed_size); + char * buffer = content.begin(); + + int32_t len = compressor.unishox_decompress(compressed, strlen_P(compressed), buffer, uncompressed_size); + if (len > 0) { + buffer[len] = 0; + content = buffer; + } + return content; +} + +#endif + + + + + + +uint32_t HwRandom(void) { +#if ESP8266 + + #define _RAND_ADDR 0x3FF20E44UL +#else + #define _RAND_ADDR 0x3FF75144UL +#endif + static uint32_t last_ccount = 0; + uint32_t ccount; + uint32_t result = 0; + do { + ccount = ESP.getCycleCount(); + result ^= *(volatile uint32_t *)_RAND_ADDR; + } while (ccount - last_ccount < 64); + last_ccount = ccount; + return result ^ *(volatile uint32_t *)_RAND_ADDR; +#undef _RAND_ADDR +} +# 1 "/workspace/Tasmota/tasmota/support_button.ino" +# 20 "/workspace/Tasmota/tasmota/support_button.ino" +#define BUTTON_V2 +#ifdef BUTTON_V2 + + + + +#define MAX_RELAY_BUTTON1 5 +#ifdef ESP32 +#define TOUCH_PIN_THRESHOLD 12 +#define TOUCH_HIT_THRESHOLD 3 +#endif + +const char kMultiPress[] PROGMEM = + "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; + +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; +#ifdef ESP32 + uint8_t touch_mask = 0; + uint8_t touch_hits[MAX_KEYS] = { 0 }; +#endif + uint8_t present = 0; +} Button; + +#ifdef ESP32 +struct TOUCH_BUTTON { + uint8_t pin_threshold = TOUCH_PIN_THRESHOLD; + uint8_t hit_threshold = TOUCH_HIT_THRESHOLD; + uint8_t calibration = 0; +} TOUCH_BUTTON; +#endif + + + +void ButtonPullupFlag(uint8 button_bit) +{ + bitSet(Button.no_pullup_mask, button_bit); +} + +void ButtonInvertFlag(uint8 button_bit) +{ + bitSet(Button.inverted_mask, button_bit); +} +#ifdef ESP32 +void ButtonTouchFlag(uint8 button_bit) +{ + bitSet(Button.touch_mask, button_bit); +} +#endif +void ButtonInit(void) +{ + Button.present = 0; +#ifdef ESP8266 + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + Button.present++; + } +#endif + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if (PinUsed(GPIO_KEY1, i)) { + Button.present++; +#ifdef ESP8266 + pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_KEY1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); +#else + pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : INPUT_PULLUP); +#endif + } +#ifdef USE_ADC + else if (PinUsed(GPIO_ADC_BUTTON, i) || PinUsed(GPIO_ADC_BUTTON_INV, i)) { + Button.present++; + } +#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; +} +# 136 "/workspace/Tasmota/tasmota/support_button.ino" +void ButtonHandler(void) +{ + if (uptime < 4) { return; } + + 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++) { + uint8_t button = NOT_PRESSED; + uint8_t button_present = 0; + +#ifdef ESP8266 + 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 +#endif + if (PinUsed(GPIO_KEY1, button_index)) { + button_present = 1; +#ifdef ESP32 + if (bitRead(Button.touch_mask, button_index)) { + uint32_t _value = touchRead(Pin(GPIO_KEY1, button_index)); + button = NOT_PRESSED; + if (_value != 0) { + if (_value < TOUCH_BUTTON.pin_threshold) { + if (++Button.touch_hits[button_index] > TOUCH_BUTTON.hit_threshold) { + if (!bitRead(TOUCH_BUTTON.calibration, button_index+1)) { + button = PRESSED; + } + } + } else { + Button.touch_hits[button_index] = 0; + } + } else { + Button.touch_hits[button_index] = 0; + } + if (bitRead(TOUCH_BUTTON.calibration, button_index+1)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("PLOT: %u, %u, %u,"), button_index+1, _value, Button.touch_hits[button_index]); + } + } else +#endif + { + button = (digitalRead(Pin(GPIO_KEY1, button_index)) != bitRead(Button.inverted_mask, button_index)); + } + } +#ifdef USE_ADC + else if (PinUsed(GPIO_ADC_BUTTON, button_index)) { + button_present = 1; + button = AdcGetButton(Pin(GPIO_ADC_BUTTON, button_index)); + } + else if (PinUsed(GPIO_ADC_BUTTON_INV, button_index)) { + button_present = 1; + button = AdcGetButton(Pin(GPIO_ADC_BUTTON_INV, button_index)); + } +#endif + if (button_present) { + XdrvMailbox.index = button_index; + XdrvMailbox.payload = button; + if (XdrvCall(FUNC_BUTTON_PRESSED)) { + + } +#ifdef ESP8266 + 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 (!Settings.flag3.mqtt_buttons) { + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); + } + } else { + MqttButtonTopic(button_index +1, 1, 0); + } + } + } +#endif + else { + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + + if (Settings.flag.button_single) { + if (!Settings.flag3.mqtt_buttons) { + 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 { + MqttButtonTopic(button_index +1, 1, 0); + } + } 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 (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { + Button.press_counter[button_index] = 0; + if (Settings.flag3.mqtt_buttons) { + MqttButtonTopic(button_index +1, 3, 1); + } else { + SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); + } + } else { + if (!Settings.flag.button_restrict) { + 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] < 7)) { + + bool single_press = false; + if (Button.press_counter[button_index] < 3) { +#ifdef ESP8266 + if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + single_press = true; + } else +#endif + { + 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; + } + } + } + } +#ifdef ROTARY_V1 + if (!RotaryButtonPressed(button_index)) { +#endif + if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { + + } else { + if (Button.press_counter[button_index] < 6) { + if (WifiState() > WIFI_RESTART) { + restart_flag = 1; + } + if (!Settings.flag3.mqtt_buttons) { + if (Button.press_counter[button_index] == 1) { + ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); + } else { + SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); + if (0 == button_index) { + bool valid_relay = PinUsed(GPIO_REL1, Button.press_counter[button_index]-1); +#ifdef ESP8266 + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + valid_relay = (Button.press_counter[button_index] <= devices_present); + } +#endif + if ((Button.press_counter[button_index] > 1) && valid_relay && (Button.press_counter[button_index] <= MAX_RELAY_BUTTON1)) { + ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); + + } + } + } + } + + } else { + if (!Settings.flag.button_restrict) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + if (Settings.flag3.mqtt_buttons) { + if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) { + MqttButtonTopic(button_index +1, Button.press_counter[button_index], 0); + } + } + } +#ifdef ROTARY_V1 + } +#endif + Button.press_counter[button_index] = 0; + } + } + } + + } + } + Button.last_state[button_index] = button; + } +} + +void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) +{ + char scommand[CMDSZ]; + char stopic[TOPSZ]; + char mqttstate[7]; + + SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); + + if (!Settings.flag.hass_discovery) { + GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); + snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); + MqttPublish(stopic); + } +} + +void ButtonLoop(void) +{ + if (Button.present) { + if (TimeReached(Button.debounce)) { + SetNextTimeInterval(Button.debounce, Settings.button_debounce); + ButtonHandler(); + } + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_command.ino" +# 20 "/workspace/Tasmota/tasmota/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_SO "|" 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_SERIALCONFIG "|" + 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_DEVICENAME "|" 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 "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|" + D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_WIFI "|" +#ifdef USE_I2C + D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" +#endif +#ifdef USE_DEVICE_GROUPS + D_CMND_DEVGROUP_NAME "|" +#ifdef USE_DEVICE_GROUPS_SEND + D_CMND_DEVGROUP_SEND "|" +#endif + D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" +#endif + D_CMND_SENSOR "|" D_CMND_DRIVER +#ifdef ESP32 + "|" D_CMND_TOUCH_CAL "|" D_CMND_TOUCH_THRES "|" D_CMND_TOUCH_NUM "|" D_CMND_CPU_FREQUENCY +#endif + ; + +void (* const TasmotaCommand[])(void) PROGMEM = { + &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, + &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, + &CmndSetoption, &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, &CmndSerialConfig, + &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, + &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, + &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode, + &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndWifi, +#ifdef USE_I2C + &CmndI2cScan, CmndI2cDriver, +#endif +#ifdef USE_DEVICE_GROUPS + &CmndDevGroupName, +#ifdef USE_DEVICE_GROUPS_SEND + &CmndDevGroupSend, +#endif + &CmndDevGroupShare, &CmndDevGroupStatus, +#endif + &CmndSensor, &CmndDriver +#ifdef ESP32 + ,&CmndTouchCal, &CmndTouchThres, &CmndTouchNum, &CmndCpuFrequency +#endif + }; + +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) +{ + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); +} + +void ResponseCmndFloat(float value, uint32_t decimals) +{ + char stemp1[TOPSZ]; + dtostrfd(value, decimals, stemp1); + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); +} + +void ResponseCmndIdxNumber(int value) +{ + Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); +} + +void ResponseCmndChar_P(const char* value) +{ + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); +} + +void ResponseCmndChar(const char* value) +{ + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, EscapeJSONString(value).c_str()); +} + +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, EscapeJSONString(value).c_str()); +} + +void ResponseCmndAll(uint32_t text_index, uint32_t count) +{ + uint32_t real_index = text_index; + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < count; i++) { + if ((SET_MQTT_GRP_TOPIC == text_index) && (1 == i)) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, EscapeJSONString(SettingsText(real_index +i)).c_str()); + } + ResponseJsonEnd(); +} + + + +void ExecuteCommand(const char *cmnd, uint32_t source) +{ + + + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("ExecuteCommand")); +#endif + ShowSource(source); + + const char *pos = cmnd; + while (*pos && isspace(*pos)) { + pos++; + } + + const char *start = pos; + + while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { + if ('/' == *pos) { + start = pos + 1; + } + pos++; + } + if ('\0' == *start || pos <= start) { + return; + } + + uint32_t size = pos - start; + char stopic[size + 2]; + stopic[0] = '/'; + memcpy(stopic+1, start, size); + stopic[size+1] = '\0'; + + char svalue[strlen(pos) +1]; + strlcpy(svalue, pos, sizeof(svalue)); + CommandHandler(stopic, svalue, strlen(svalue)); +} +# 179 "/workspace/Tasmota/tasmota/support_command.ino" +void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) +{ +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("CommandHandler")); +#endif + + while (*dataBuf && isspace(*dataBuf)) { + dataBuf++; + data_len--; + } + + bool grpflg = false; + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + char *group_topic = SettingsText(real_index +i); + if (*group_topic && strstr(topicBuf, group_topic) != nullptr) { + grpflg = true; + break; + } + } + + char stemp1[TOPSZ]; + GetFallbackTopic_P(stemp1, ""); + fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); + + char *type = strrchr(topicBuf, '/'); + + uint32_t index = 1; + bool user_index = false; + if (type != nullptr) { + type++; + uint32_t i; + int nLen; + char *s = type; + for (nLen = 0; *s; s++, nLen++) { + *s=toupper(*s); + } + i = nLen; + if (i > 0) { + while (isdigit(type[i-1])) { + i--; + } + } + if (i < nLen) { + index = atoi(type + i); + user_index = true; + } + type[i] = '\0'; + } + + 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 "\"}")); + + 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() + Settings.param[P_BACKLOG_DELAY]; + + char command[CMDSZ] = { 0 }; + 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; + +#ifdef USE_SCRIPT_SUB_COMMAND + + if (!Script_SubCmd()) { + if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = nullptr; + } + } + } + } +#else + if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = nullptr; + } + } + } +#endif + + } + + if (type == nullptr) { + blinks = 201; + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); + type = (char*)stemp1; + } + + if (mqtt_data[0] != '\0') { +# 303 "/workspace/Tasmota/tasmota/support_command.ino" + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, type); + } + 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] = blcommand; + backlog_index++; + if (backlog_index >= MAX_BACKLOG) backlog_index = 0; +#endif + } + blcommand = strtok(nullptr, ";"); + } + + mqtt_data[0] = '\0'; + backlog_delay = 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 / 100)) && (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); + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + mqtt_data[0] = '\0'; + } +} + +void CmndStatus(void) +{ + uint32_t payload = XdrvMailbox.payload; + + if (payload > MAX_STATUS) { return; } + if (!Settings.flag.mqtt_enabled && (6 == payload)) { return; } + if (!energy_flg && (9 == payload)) { return; } + if (!CrashFlag() && (12 == payload)) { return; } + if (!Settings.flag3.shutter_mode && (13 == payload)) { return; } + + char stemp[200]; + char stemp2[TOPSZ]; + + if (0 == 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 ? "," : ""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); + } + 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_DEVICENAME "\":\"%s\",\"" 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(), EscapeJSONString(SettingsText(SET_DEVICENAME)).c_str(), stemp, mqtt_topic, + SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, + Settings.ledmask, Settings.save_data, + Settings.flag.save_state, + SettingsText(SET_MQTT_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(STAT, PSTR(D_CMND_STATUS)); + } + + if ((0 == payload) || (1 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" 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,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d" +#ifdef ESP8266 + ",\"" D_JSON_SAVEADDRESS "\":\"%X\"" +#endif + "}}"), + baudrate, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), + GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, + Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag +#ifdef ESP8266 + , GetSettingsAddress() +#endif + ); + MqttPublishPrefixTopic_P(STAT, 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\"" +#ifdef ESP8266 + ",\"" D_JSON_BOOTVERSION "\":%d" +#endif + ",\"" D_JSON_COREVERSION "\":\"" ARDUINO_CORE_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"CpuFrequency\":%d,\"Hardware\":\"%s\"" + "%s}}"), + my_version, my_image, GetBuildDateAndTime().c_str() +#ifdef ESP8266 + , ESP.getBootVersion() +#endif + , ESP.getSdkVersion(), + ESP.getCpuFreqMHz(), GetDeviceHardware().c_str(), + GetStatistics().c_str()); + MqttPublishPrefixTopic_P(STAT, 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_MQTTLOG "\":%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\",\"%08X\",\"%08X\"]}}"), + Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, + SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings.tele_period, + Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), + Settings.flag3.data, Settings.flag4.data, Settings.flag5.data); + MqttPublishPrefixTopic_P(STAT, 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,\"" +#ifdef ESP32 + D_JSON_PSRMAXMEMORY "\":%d,\"" D_JSON_PSRFREEMEMORY "\":%d,\"" +#endif + D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d" +#ifdef ESP8266 + ",\"" D_JSON_FLASHCHIPID "\":\"%06X\"" +#endif + ",\"FlashFrequency\":%d,\"" D_JSON_FLASHMODE "\":%d,\"" + D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), + ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP_getFreeHeap()/1024, +#ifdef ESP32 + ESP.getPsramSize()/1024, ESP.getFreePsram()/1024, +#endif + ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024 +#ifdef ESP8266 + , ESP.getFlashChipId() +#endif + , ESP.getFlashChipSpeed()/1000000, ESP.getFlashChipMode(), + LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6, feature7); + XsnsDriverState(); + ResponseAppend_P(PSTR(",\"Sensors\":")); + XsnsSensorState(); + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(STAT, 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,\"" D_CMND_WIFIPOWER "\":%s}}"), + NetworkHostname(), NetworkAddress().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(), NetworkMacAddress().c_str(), + Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "5")); + } + + if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { + 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}}"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, EscapeJSONString(SettingsText(SET_MQTT_CLIENT)).c_str(), + mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + MqttPublishPrefixTopic_P(STAT, 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\"}}"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).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}}"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp); +#endif + MqttPublishPrefixTopic_P(STAT, 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,%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[0], Settings.energy_power_delta[1], Settings.energy_power_delta[2], 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(STAT, 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(STAT, PSTR(D_CMND_STATUS "8")); + } else { + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "10")); + } + } + + if ((0 == payload) || (11 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); + MqttShowState(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "11")); + } + + if (CrashFlag()) { + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "12")); + } + } + +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + if ((0 == payload) || (13 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS13_SHUTTER "\":")); + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (0 == Settings.shutter_startrelay[i]) { break; } + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("{\"" D_STATUS13_SHUTTER "%d\":{\"Relay1\":%d,\"Relay2\":%d,\"Open\":%d,\"Close\":%d," + "\"50perc\":%d,\"Delay\":%d,\"Opt\":\"%s\"," + "\"Calib\":[%d,%d,%d,%d,%d]," + "\"Mode\":\"%d\"}}"), + i, Settings.shutter_startrelay[i], Settings.shutter_startrelay[i] +1, Settings.shutter_opentime[i], Settings.shutter_closetime[i], + Settings.shutter_set50percent[i], Settings.shutter_motordelay[i], GetBinary8(Settings.shutter_options[i], 4).c_str(), + Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], + Settings.shutter_mode); + } + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "13")); + } + } +#endif + +#ifdef USE_SCRIPT_STATUS + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); +#endif + + if (payload) { + XdrvRulesProcess(); + } + + 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 CmndTempOffset(void) +{ + if (XdrvMailbox.data_len > 0) { + int value = (int)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > -127) && (value < 127)) { + Settings.temp_comp = value; + } + } + ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1); +} + +void CmndHumOffset(void) +{ + if (XdrvMailbox.data_len > 0) { + int value = (int)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > -101) && (value < 101)) { + Settings.hum_comp = value; + } + } + ResponseCmndFloat((float)(Settings.hum_comp) / 10, 1); +} + +void CmndGlobalTemp(void) +{ + if (XdrvMailbox.data_len > 0) { + float temperature = CharToFloat(XdrvMailbox.data); + if (!isnan(temperature) && Settings.flag.temperature_conversion) { + temperature = (temperature - 32) / 1.8; + } + if ((temperature >= -50.0f) && (temperature <= 100.0f)) { + ConvertTemp(temperature); + global_update = 1; + } + } + ResponseCmndFloat(global_temperature_celsius, 1); +} + +void CmndGlobalHum(void) +{ + if (XdrvMailbox.data_len > 0) { + float humidity = CharToFloat(XdrvMailbox.data); + if ((humidity >= 0.0) && (humidity <= 100.0)) { + ConvertHumidity(humidity); + global_update = 1; + } + } + ResponseCmndFloat(global_humidity, 1); +} + +void CmndSleep(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { + Settings.sleep = XdrvMailbox.payload; + ssleep = XdrvMailbox.payload; + WiFiSetSleepMode(); + } + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, ssleep); + +} + +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) { + SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? PSTR(OTA_URL) : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_OTAURL)); +} + +void CmndSeriallog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { + 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 2: + restart_flag = 2; + restart_halt = true; + ResponseCmndChar(D_JSON_HALTING); + break; + case -1: + CmndCrash(); + break; + case -2: + CmndWDT(); + break; + case -3: + CmndBlockedLoop(); + break; + case 99: + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + EspRestart(); + break; + default: + ResponseCmndChar_P(PSTR(D_JSON_ONE_TO_RESTART)); + } +} + +void CmndPowerOnState(void) +{ +#ifdef ESP8266 + if (my_module_type != MOTOR) +#endif + { + + + + + + + + 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)) { + uint32_t items = 1; + if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { + items = MAX_PULSETIMERS; + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { + Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; + SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); + } + } + 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, index, + Settings.pulse_timer[index -1], GetPulseTimer(index -1)); + } + ResponseJsonEnd(); + } +} + +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) +{ + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR(D_CMND_SETOPTION)); + + if (XdrvMailbox.index < 146) { + uint32_t ptype; + uint32_t pindex; + if (XdrvMailbox.index <= 31) { + ptype = 2; + pindex = XdrvMailbox.index; + } + else if (XdrvMailbox.index <= 49) { + ptype = 1; + pindex = XdrvMailbox.index -32; + } + else if (XdrvMailbox.index <= 81) { + ptype = 3; + pindex = XdrvMailbox.index -50; + } + else if (XdrvMailbox.index <= 113) { + ptype = 4; + pindex = XdrvMailbox.index -82; + } + else { + ptype = 5; + pindex = XdrvMailbox.index -114; + } + + if (XdrvMailbox.payload >= 0) { + if (1 == ptype) { + 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; +#ifdef USE_LIGHT + if (P_RGB_REMAP == pindex) { + LightUpdateColorMapping(); + restart_flag = 2; + } +#endif +#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) + if (P_IR_UNKNOW_THRESHOLD == pindex) { + IrReceiveUpdateThreshold(); + } +#endif + } else { + ptype = 99; + } + } else { + if (XdrvMailbox.payload <= 1) { + if (2 == ptype) { + 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 (3 == ptype) { + bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); + switch (pindex) { + case 5: + if (0 == XdrvMailbox.payload) { + restart_flag = 2; + } + break; + case 10: + WiFiSetSleepMode(); + break; + case 18: + case 25: + restart_flag = 2; + break; + } + } + else if (4 == ptype) { + bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); + switch (pindex) { + case 3: + case 6: + case 15: + case 20: + case 21: + case 22: + case 24: + case 25: + restart_flag = 2; + break; + } + } + else if (5 == ptype) { + bitWrite(Settings.flag5.data, pindex, XdrvMailbox.payload); + } + } else { + ptype = 99; + } + } + } + + if (ptype < 99) { + if (1 == ptype) { + ResponseCmndIdxNumber(Settings.param[pindex]); + } else { + uint32_t flag = Settings.flag.data; + if (3 == ptype) { + flag = Settings.flag3.data; + } + else if (4 == ptype) { + flag = Settings.flag4.data; + } + else if (5 == ptype) { + flag = Settings.flag5.data; + } + ResponseCmndIdxChar(GetStateText(bitRead(flag, 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 CmndSpeedUnit(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { + Settings.flag2.speed_conversion = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.speed_conversion); +} + +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) { + if (XdrvMailbox.index == 2) { + Settings.fallback_module = XdrvMailbox.payload; + } else { + Settings.last_module = Settings.module; + Settings.module = XdrvMailbox.payload; + SetModuleType(); + if (Settings.last_module != XdrvMailbox.payload) { + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + restart_flag = 2; + } + } + } + uint8_t module_real = Settings.module; + uint8_t module_number = ModuleNr(); + if (XdrvMailbox.index == 2) { + module_real = Settings.fallback_module; + module_number = (USER_MODULE == Settings.fallback_module) ? 0 : Settings.fallback_module +1; + strcat(XdrvMailbox.command, "2"); + } + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, module_number, AnyModuleName(module_real).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, XdrvMailbox.command); + jsflg = false; + lines++; + } + } + mqtt_data[0] = '\0'; +} + +void CmndGpio(void) +{ + if (XdrvMailbox.index < ARRAY_SIZE(Settings.my_gp.io)) { + myio cmodule; + ModuleGpios(&cmodule); + if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) { + bool present = false; + for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { + uint32_t midx = pgm_read_word(kGpioNiceList + i); + if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < midx)) { + present = true; + break; + } + } + if (present) { + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { + if (ValidGPIO(i, cmodule.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) { + if (jsflg) { ResponseAppend_P(PSTR(",")); } + jsflg = true; + uint32_t sensor_type = Settings.my_gp.io[i]; + if (!ValidGPIO(i, cmodule.io[i])) { + sensor_type = cmodule.io[i]; + if (AGPIO(GPIO_USER) == sensor_type) { + sensor_type = GPIO_NONE; + } + } + char sindex[4] = { 0 }; + uint32_t sensor_name_idx = BGPIO(sensor_type); + uint32_t nice_list_search = sensor_type & 0xFFE0; + for (uint32_t j = 0; j < ARRAY_SIZE(kGpioNiceList); j++) { + uint32_t nls_idx = pgm_read_word(kGpioNiceList + j); + if (((nls_idx & 0xFFE0) == nice_list_search) && ((nls_idx & 0x001F) > 0)) { + snprintf_P(sindex, sizeof(sindex), PSTR("%d"), (sensor_type & 0x001F) +1); + break; + } + } + const char *sensor_names = kSensorNames; + if (sensor_name_idx > GPIO_FIX_START) { + sensor_name_idx = sensor_name_idx - GPIO_FIX_START -1; + sensor_names = kSensorNamesFixed; + } + char stemp1[TOPSZ]; + ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s%s\"}"), + i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex); + } + } + if (jsflg) { + ResponseJsonEnd(); + } else { + ResponseCmndChar(D_JSON_NOT_SUPPORTED); + } + } +} + +void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines) { + myio cmodule; + ModuleGpios(&cmodule); + bool jsflg = false; + for (uint32_t i = offset; i < size; i++) { + uint32_t ridx = pgm_read_word(NiceList + i) & 0xFFE0; + uint32_t midx = BGPIO(ridx); + 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\""), ridx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == size -1)) { + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); + jsflg = false; + lines++; + } + } +} + +void CmndGpios(void) +{ + + + + + + + uint32_t lines = 1; + ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines); +#ifdef ESP8266 +#ifndef USE_ADC_VCC + ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines); +#endif +#endif + 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); + } + SettingsUpdateText(SET_TEMPLATE_NAME, "Merged"); + uint32_t j = 0; + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); 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_P(PSTR(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) && PinUsed(GPIO_PWM1, XdrvMailbox.index -1)) { + 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))) { + uint32_t pwm_range = XdrvMailbox.payload; + uint32_t pwm_resolution = 0; + while (pwm_range) { + pwm_resolution++; + pwm_range >>= 1; + } + pwm_range = (1 << pwm_resolution) - 1; + uint32_t old_pwm_range = Settings.pwm_range; + Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : pwm_range; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (Settings.pwm_value[i] > Settings.pwm_range) { + Settings.pwm_value[i] = Settings.pwm_range; + } + } + if (Settings.pwm_range != old_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 < 1010)) { + 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(baudrate); +} + +void CmndSerialConfig(void) +{ + + + + + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len < 3) { + if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { + SetSerialConfig(XdrvMailbox.payload); + } + } + else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { + uint8_t serial_config = XdrvMailbox.payload -5; + + bool valid = true; + char parity = (XdrvMailbox.data[1] & 0xdf); + if ('E' == parity) { + serial_config += 0x08; + } + else if ('O' == parity) { + serial_config += 0x10; + } + else if ('N' != parity) { + valid = false; + } + + if ('2' == XdrvMailbox.data[2]) { + serial_config += 0x04; + } + else if ('1' != XdrvMailbox.data[2]) { + valid = false; + } + + if (valid) { + SetSerialConfig(serial_config); + } + } + } + ResponseCmndChar(GetSerialConfig().c_str()); +} + +void CmndSerialSend(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + 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)); + } + else if (6 == XdrvMailbox.index) { + SerialSendDecimal(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_DEBUG_MORE)) { + 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) { + SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_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 <= MAX_NTP_SERVERS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); + } else { + uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(ntp_server, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? PSTR(NTP_SERVER1) : (2 == XdrvMailbox.index) ? PSTR(NTP_SERVER2) : PSTR(NTP_SERVER3) : XdrvMailbox.data); + SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); + + ntp_force_sync = true; + } + ResponseCmndIdxChar(SettingsText(ntp_server)); + } + } +} + +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; + } + Settings.wifi_channel = 0; + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str()); +} + +void CmndSsid(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_STASSID1, MAX_SSIDS); + } else { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); + Settings.sta_active = XdrvMailbox.index -1; + restart_flag = 2; + } + ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); + } + } +} + +void CmndPassword(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { + SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); + Settings.sta_active = XdrvMailbox.index -1; + restart_flag = 2; + ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + 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)) { + SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + } + restart_flag = 2; + } + ResponseCmndChar(SettingsText(SET_HOSTNAME)); +} + +void CmndWifiConfig(void) +{ + 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; + if (WifiState() > WIFI_RESTART) { + restart_flag = 2; + } + } + char stemp1[TOPSZ]; + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); +} + +void CmndWifi(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag4.network_wifi = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndStateText(Settings.flag4.network_wifi); +} + +void CmndDevicename(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + SettingsUpdateText(SET_DEVICENAME, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? SettingsText(SET_FRIENDLYNAME1) : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_DEVICENAME)); +} + +void CmndFriendlyname(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { + if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { + ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); + } else { + if (XdrvMailbox.data_len > 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); + } + SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); + } + ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + 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); + } + } +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + ShutterInit(); + } +#endif + } + 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 = APP_INTERLOCK_MODE; + 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; + ResponseCmndNumber(Settings.tele_period); +} + +void CmndReset(void) +{ + switch (XdrvMailbox.payload) { + case 1: + restart_flag = 211; + ResponseCmndChar(PSTR(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; + Settings.bootcount_reset_time = 0; + ResponseCmndDone(); + break; + default: + ResponseCmndChar(PSTR(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 < 5)) { + 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 (!PinUsed(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 (!PinUsed(GPIO_LEDLNK)) { + SetLedPower(Settings.ledstate &8); + } else { + SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); + } + } + bool state = bitRead(led_power, XdrvMailbox.index -1); + if (!PinUsed(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) { +#ifdef USE_PWM_DIMMER + PWMDimmerSetBrightnessLeds(0); +#endif + Settings.ledmask = XdrvMailbox.payload; +#ifdef USE_PWM_DIMMER + PWMDimmerSetBrightnessLeds(-1); +#endif + } + char stemp1[TOPSZ]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); + ResponseCmndChar(stemp1); +} + +void CmndLedPwmOff(void) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { + Settings.ledpwm_off = 0; + } + else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_off = 255; + } else { + Settings.ledpwm_off = XdrvMailbox.payload; + } + UpdateLedPowerAll(); + } + ResponseCmndNumber(Settings.ledpwm_off); +} + +void CmndLedPwmOn(void) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { + Settings.ledpwm_on = 0; + } + else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_on = 255; + } else { + Settings.ledpwm_on = XdrvMailbox.payload; + } + UpdateLedPowerAll(); + } + ResponseCmndNumber(Settings.ledpwm_on); +} + +void CmndLedPwmMode(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { + if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + uint32_t mask = 1 << (XdrvMailbox.index -1); + switch (XdrvMailbox.payload) { + case 0: + Settings.ledpwm_mask &= (0xFF ^ mask); + break; + case 1: + Settings.ledpwm_mask |= mask; + break; + case 2: + Settings.ledpwm_mask ^= mask; + break; + } + UpdateLedPowerAll(); + } + bool state = bitRead(Settings.ledpwm_mask, XdrvMailbox.index -1); + ResponseCmndIdxChar(GetStateText(state)); + } +} + +void CmndWifiPower(void) +{ + if (XdrvMailbox.data_len > 0) { + Settings.wifi_output_power = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); + if (Settings.wifi_output_power > 205) { + Settings.wifi_output_power = 205; + } + WifiSetOutputPower(); + } + ResponseCmndChar(WifiGetOutputPower().c_str()); +} + +#ifdef USE_I2C +void CmndI2cScan(void) +{ + if (i2c_flg) { + I2cScan(mqtt_data, sizeof(mqtt_data)); + } +} + +void CmndI2cDriver(void) +{ + if (XdrvMailbox.index < MAX_I2C_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + restart_flag = 2; + } + } + Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); + I2cDriverState(); + ResponseJsonEnd(); +} +#endif + +#ifdef USE_DEVICE_GROUPS +void CmndDevGroupName(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DEV_GROUP_NAMES)) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len > TOPSZ) + XdrvMailbox.data[TOPSZ - 1] = 0; + else if (1 == XdrvMailbox.data_len && ('"' == XdrvMailbox.data[0] || '0' == XdrvMailbox.data[0])) + XdrvMailbox.data[0] = 0; + SettingsUpdateText(SET_DEV_GROUP_NAME1 + XdrvMailbox.index - 1, XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndAll(SET_DEV_GROUP_NAME1, MAX_DEV_GROUP_NAMES); + } +} + +#ifdef USE_DEVICE_GROUPS_SEND +void CmndDevGroupSend(void) +{ + uint8_t device_group_index = (XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0); + if (device_group_index < device_group_count) { + if (!_SendDeviceGroupMessage(device_group_index, (DevGroupMessageType)(DGR_MSGTYPE_UPDATE_COMMAND + DGR_MSGTYPFLAG_WITH_LOCAL))) { + ResponseCmndChar(XdrvMailbox.data); + } + } +} +#endif + +void CmndDevGroupShare(void) +{ + uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out }; + ParseParameters(2, parm); + Settings.device_group_share_in = parm[0]; + Settings.device_group_share_out = parm[1]; + Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":\"%X\",\"Out\":\"%X\"}}"), Settings.device_group_share_in, Settings.device_group_share_out); +} + +void CmndDevGroupStatus(void) +{ + DeviceGroupStatus((XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0)); +} +#endif + +void CmndSensor(void) +{ + XsnsCall(FUNC_COMMAND_SENSOR); +} + +void CmndDriver(void) +{ + XdrvCall(FUNC_COMMAND_DRIVER); +} + +#ifdef ESP32 + +void CmndCpuFrequency(void) { + if ((80 == XdrvMailbox.payload) || (160 == XdrvMailbox.payload) || (240 == XdrvMailbox.payload)) { + setCpuFrequencyMhz(XdrvMailbox.payload); + } + ResponseCmndNumber(getCpuFrequencyMhz()); +} + +void CmndTouchCal(void) +{ + if (XdrvMailbox.payload >= 0) { + if (XdrvMailbox.payload < MAX_KEYS + 1) TOUCH_BUTTON.calibration = bitSet(TOUCH_BUTTON.calibration, XdrvMailbox.payload); + if (XdrvMailbox.payload == 0) TOUCH_BUTTON.calibration = 0; + if (XdrvMailbox.payload == 255) TOUCH_BUTTON.calibration = 255; + } + Response_P(PSTR("{\"" D_CMND_TOUCH_CAL "\": %u"), TOUCH_BUTTON.calibration); + ResponseJsonEnd(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Button Touchvalue Hits,")); +} + +void CmndTouchThres(void) +{ + if (XdrvMailbox.payload >= 0) { + if (XdrvMailbox.payload<256){ + TOUCH_BUTTON.pin_threshold = XdrvMailbox.payload; + } + } + Response_P(PSTR("{\"" D_CMND_TOUCH_THRES "\": %u"), TOUCH_BUTTON.pin_threshold); + ResponseJsonEnd(); +} + +void CmndTouchNum(void) +{ + if (XdrvMailbox.payload >= 0) { + if (XdrvMailbox.payload<32){ + TOUCH_BUTTON.hit_threshold = XdrvMailbox.payload; + } + } + Response_P(PSTR("{\"" D_CMND_TOUCH_NUM "\": %u"), TOUCH_BUTTON.hit_threshold); + ResponseJsonEnd(); + +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_cores.ino" +# 26 "/workspace/Tasmota/tasmota/support_cores.ino" +void resetPins() +{ +# 37 "/workspace/Tasmota/tasmota/support_cores.ino" +} + + + + + +#ifdef ESP8266 + +void HwWdtDisable(void) { + *((volatile uint32_t*) 0x60000900) &= ~(1); +} + +void HwWdtEnable(void) { + *((volatile uint32_t*) 0x60000900) |= 1; +} + +void WdtDisable(void) { + ESP.wdtDisable(); + HwWdtDisable(); +} + +void WdtEnable(void) { + HwWdtEnable(); + ESP.wdtEnable(0); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_crash_recorder.ino" +# 20 "/workspace/Tasmota/tasmota/support_crash_recorder.ino" +#ifdef ESP8266 + +const uint32_t crash_magic = 0x53415400; +const uint32_t crash_rtc_offset = 32; +const uint32_t crash_dump_max_len = 31; + + + + + + +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) +{ + uint32_t addr_written = 0; + uint32_t value; + + for (uint32_t i = stack; i < stack_end; i += 4) { + value = *((uint32_t*) i); + if ((value >= 0x40000000) && (value < 0x40300000)) { + ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); + addr_written++; + if (addr_written >= crash_dump_max_len) { break; } + } + } + value = crash_magic + addr_written; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); +} + + +void CmndCrash(void) +{ + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); +} + + +void CmndWDT(void) +{ + volatile uint32_t dummy = 0; + while (1) { + dummy++; + } +} + + +void CmndBlockedLoop(void) +{ + while (1) { + delay(1000); + } +} + + +void CrashDumpClear(void) +{ + uint32_t value = 0; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); +} + + + + + +bool CrashFlag(void) +{ + return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); +} + +void CrashDump(void) +{ + ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), + resetInfo.exccause, + GetResetReason().c_str(), + resetInfo.epc1, + resetInfo.epc2, + resetInfo.epc3, + resetInfo.excvaddr, + resetInfo.depc); + + uint32_t value; + ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); + if (crash_magic == (value & 0xFFFFFF00)) { + ResponseAppend_P(PSTR(",\"CallChain\":[")); + uint32_t count = value & 0x3F; + for (uint32_t i = 0; i < count; i++) { + ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_device_groups.ino" +# 24 "/workspace/Tasmota/tasmota/support_device_groups.ino" +#ifdef USE_DEVICE_GROUPS + + +#define DGR_MEMBER_TIMEOUT 45000 +#define DGR_ANNOUNCEMENT_INTERVAL 60000 +#define DEVICE_GROUP_MESSAGE "TASMOTA_DGR" + +const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE; + +struct device_group_member { + struct device_group_member * flink; + IPAddress ip_address; + uint16_t received_sequence; + uint16_t acked_sequence; + uint32_t unicast_count; +}; + +struct device_group { + uint32_t next_announcement_time; + uint32_t next_ack_check_time; + uint32_t member_timeout_time; + uint16_t outgoing_sequence; + uint16_t last_full_status_sequence; + uint16_t message_length; + uint16_t ack_check_interval; + uint8_t message_header_length; + uint8_t initial_status_requests_remaining; + char group_name[TOPSZ]; + uint8_t message[128]; + struct device_group_member * device_group_members; +#ifdef USE_DEVICE_GROUPS_SEND + uint8_t values_8bit[DGR_ITEM_LAST_8BIT]; + uint16_t values_16bit[DGR_ITEM_LAST_16BIT - DGR_ITEM_MAX_8BIT - 1]; + uint32_t values_32bit[DGR_ITEM_LAST_32BIT - DGR_ITEM_MAX_16BIT - 1]; +#endif +}; + +WiFiUDP device_groups_udp; +struct device_group * device_groups; +uint32_t next_check_time; +bool device_groups_initialized = false; +bool device_groups_up = false; +bool building_status_message = false; +bool ignore_dgr_sends = false; + +char * IPAddressToString(const IPAddress& ip_address) +{ + static char buffer[16]; + sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); + return buffer; +} + +uint8_t * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t flags, bool hold_sequence = false) +{ + uint8_t * message_ptr = &device_group->message[device_group->message_header_length]; + if (!hold_sequence && !++device_group->outgoing_sequence) device_group->outgoing_sequence = 1; + *message_ptr++ = device_group->outgoing_sequence & 0xff; + *message_ptr++ = device_group->outgoing_sequence >> 8; + *message_ptr++ = flags & 0xff; + *message_ptr++ = flags >> 8; + return message_ptr; +} + + +bool DeviceGroupItemShared(bool incoming, uint8_t item) +{ + uint32_t mask; + if (item == DGR_ITEM_LIGHT_BRI || item == DGR_ITEM_BRI_POWER_ON) + mask = DGR_SHARE_LIGHT_BRI; + else if (item == DGR_ITEM_POWER) + mask = DGR_SHARE_POWER; + else if (item == DGR_ITEM_LIGHT_SCHEME) + mask = DGR_SHARE_LIGHT_SCHEME; + else if (item == DGR_ITEM_LIGHT_FIXED_COLOR || DGR_ITEM_LIGHT_CHANNELS) + mask = DGR_SHARE_LIGHT_COLOR; + else if (item == DGR_ITEM_LIGHT_FADE || item == DGR_ITEM_LIGHT_SPEED) + mask = DGR_SHARE_LIGHT_FADE; + else if (item == DGR_ITEM_BRI_PRESET_LOW || item == DGR_ITEM_BRI_PRESET_HIGH) + mask = DGR_SHARE_DIMMER_SETTINGS; + else if (item == DGR_ITEM_EVENT) + mask = DGR_SHARE_EVENT; + else + return true; + return mask & (incoming ? Settings.device_group_share_in : Settings.device_group_share_out); +} + +void DeviceGroupsInit(void) +{ + + if (!device_group_count) { + + + + if (Settings.flag4.multiple_device_groups) { + for (uint32_t relay_index = 0; relay_index < MAX_RELAYS; relay_index++) { + if (PinUsed(GPIO_REL1, relay_index)) device_group_count = relay_index + 1; + } + if (device_group_count > MAX_DEV_GROUP_NAMES) device_group_count = MAX_DEV_GROUP_NAMES; + } + + + else { + device_group_count = 1; + } + } + + + + for (; device_group_count < MAX_DEV_GROUP_NAMES; device_group_count++) { + if (!*SettingsText(SET_DEV_GROUP_NAME1 + device_group_count)) break; + } + + + device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); + if (!device_groups) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating %u-element array"), device_group_count); + return; + } + + struct device_group * device_group = device_groups; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { + strcpy(device_group->group_name, SettingsText(SET_DEV_GROUP_NAME1 + device_group_index)); + + + + if (!device_group->group_name[0]) { + strcpy(device_group->group_name, SettingsText(SET_MQTT_GRP_TOPIC)); + if (device_group_index) { + snprintf_P(device_group->group_name, sizeof(device_group->group_name), PSTR("%s%u"), device_group->group_name, device_group_index + 1); + } + } + device_group->message_header_length = sprintf_P((char *)device_group->message, PSTR("%s%s"), kDeviceGroupMessage, device_group->group_name) + 1; + device_group->last_full_status_sequence = -1; + } + + + if (!Settings.device_group_share_in && !Settings.device_group_share_out) { + Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; + } + + device_groups_initialized = true; +} + +void DeviceGroupsStart() +{ + if (Settings.flag4.device_groups_enabled && !device_groups_up && !restart_flag) { + + + if (!device_groups_initialized) { + DeviceGroupsInit(); + if (!device_groups_initialized) return; + } + + + if (!device_groups_udp.beginMulticast(WiFi.localIP(), IPAddress(DEVICE_GROUPS_ADDRESS), DEVICE_GROUPS_PORT)) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error subscribing")); + return; + } + device_groups_up = true; + + + + + next_check_time = millis() + 2000; + struct device_group * device_group = device_groups; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { + device_group->next_announcement_time = -1; + device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message; + device_group->initial_status_requests_remaining = 10; + device_group->next_ack_check_time = next_check_time; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering members")); + } +} + +void DeviceGroupsStop() +{ + device_groups_udp.flush(); + device_groups_up = false; +} + +void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received) +{ + char log_buffer[512]; + bool item_processed = false; + uint16_t message_sequence; + uint16_t flags; + int device_group_index = device_group - device_groups; + int log_length; + int log_remaining; + char * log_ptr; + + + uint8_t * message_end_ptr = message + message_length; + uint8_t * message_ptr = message + strlen((char *)message) + 1; + + + if (message_ptr + 4 > message_end_ptr) goto badmsg; + message_sequence = *message_ptr++; + message_sequence |= *message_ptr++ << 8; + flags = *message_ptr++; + flags |= *message_ptr++ << 8; + + + log_length = sprintf(log_buffer, PSTR("DGR: %s %s message %s %s: seq=%u, flags=%u"), (received ? PSTR("Received") : PSTR("Sending")), device_group->group_name, (received ? PSTR("from") : PSTR("to")), (device_group_member ? IPAddressToString(device_group_member->ip_address) : received ? PSTR("local") : PSTR("network")), message_sequence, flags); + log_ptr = log_buffer + log_length; + log_remaining = sizeof(log_buffer) - log_length; + + + if (flags == DGR_FLAG_ANNOUNCEMENT) goto write_log; + + + + if (flags == DGR_FLAG_ACK) { + if (received && device_group_member && (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536)) { + device_group_member->acked_sequence = message_sequence; + } + goto write_log; + } + + + if (device_group_member) { + if (received) { + if (!(flags & DGR_FLAG_MORE_TO_COME)) { + *(message_ptr - 2) = DGR_FLAG_ACK; + *(message_ptr - 1) = 0; + SendReceiveDeviceGroupMessage(device_group, device_group_member, message, message_ptr - message, false); + } + } + + + else { + log_length = snprintf(log_ptr, log_remaining, PSTR(", last ack=%u"), device_group_member->acked_sequence); + log_ptr += log_length; + log_remaining -= log_length; + goto write_log; + } + } + + + if ((flags & DGR_FLAG_STATUS_REQUEST)) goto write_log; + + + if (received) { + + + if (device_group_member) { + if (message_sequence <= device_group_member->received_sequence) { + if (message_sequence == device_group_member->received_sequence || device_group_member->received_sequence - message_sequence > 64536) { + log_length = snprintf(log_ptr, log_remaining, PSTR(" (old)")); + log_ptr += log_length; + log_remaining -= log_length; + goto write_log; + } + } + device_group_member->received_sequence = message_sequence; + } +# 294 "/workspace/Tasmota/tasmota/support_device_groups.ino" + XdrvMailbox.command = nullptr; + XdrvMailbox.index = flags | message_sequence << 16; + if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index |= DGR_FLAG_LOCAL; + XdrvMailbox.topic = (char *)&device_group_index; + if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true; + + + + ignore_dgr_sends = true; + } + + uint8_t item; + int32_t value; + for (;;) { + if (message_ptr >= message_end_ptr) goto badmsg; + item = *message_ptr++; + if (!item) break; + +#ifdef DEVICE_GROUPS_DEBUG + switch (item) { + case DGR_ITEM_FLAGS: + case DGR_ITEM_LIGHT_FADE: + case DGR_ITEM_LIGHT_SPEED: + case DGR_ITEM_LIGHT_BRI: + case DGR_ITEM_LIGHT_SCHEME: + case DGR_ITEM_LIGHT_FIXED_COLOR: + case DGR_ITEM_BRI_PRESET_LOW: + case DGR_ITEM_BRI_PRESET_HIGH: + case DGR_ITEM_BRI_POWER_ON: + case DGR_ITEM_POWER: + case DGR_ITEM_EVENT: + case DGR_ITEM_LIGHT_CHANNELS: + break; + default: + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: *** Invalid item=%u"), item); + } +#endif + + log_length = snprintf(log_ptr, log_remaining, PSTR(", %u="), item); + log_ptr += log_length; + log_remaining -= log_length; + log_length = 0; + if (item <= DGR_ITEM_LAST_32BIT) { + value = *message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + value |= *message_ptr++ << 8; + if (item > DGR_ITEM_MAX_16BIT) { + value |= *message_ptr++ << 16; + value |= *message_ptr++ << 24; +#ifdef USE_DEVICE_GROUPS_SEND + device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1] = (item == DGR_ITEM_POWER ? value & 0xffffff : value); +#endif + } +#ifdef USE_DEVICE_GROUPS_SEND + else { + device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] = value; + } +#endif + } +#ifdef USE_DEVICE_GROUPS_SEND + else { + device_group->values_8bit[item] = value; + } +#endif + log_length = snprintf(log_ptr, log_remaining, PSTR("%u"), value); + } + else { + value = *message_ptr++; + if (received) XdrvMailbox.data = (char *)message_ptr; + if (message_ptr + value >= message_end_ptr) goto badmsg; + if (item <= DGR_ITEM_MAX_STRING) { + log_length = snprintf(log_ptr, log_remaining, PSTR("'%s'"), message_ptr); + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + log_length = snprintf(log_ptr, log_remaining, PSTR("%u,%u,%u,%u,%u,%u"), *message_ptr, *(message_ptr + 1), *(message_ptr + 2), *(message_ptr + 3), *(message_ptr + 4), *(message_ptr + 5)); + break; + } + } + message_ptr += value; + } + log_ptr += log_length; + log_remaining -= log_length; + + if (received && DeviceGroupItemShared(true, item)) { + item_processed = true; + XdrvMailbox.command_code = item; + XdrvMailbox.payload = value; + XdrvMailbox.data_len = value; + *log_ptr++ = '*'; + log_remaining--; + switch (item) { + case DGR_ITEM_POWER: + if (Settings.flag4.multiple_device_groups) { + if (device_group_index < devices_present) { + bool on = (value & 1); + if (on != (power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); + } + } + else if (XdrvMailbox.index & DGR_FLAG_LOCAL) { + uint8_t mask_devices = value >> 24; + if (mask_devices > devices_present) mask_devices = devices_present; + for (uint32_t i = 0; i < mask_devices; i++) { + uint32_t mask = 1 << i; + bool on = (value & mask); + if (on != (power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); + } + } + break; +#ifdef USE_RULES + case DGR_ITEM_EVENT: + CmndEvent(); + break; +#endif + case DGR_ITEM_COMMAND: + ExecuteCommand(XdrvMailbox.data, SRC_REMOTE); + break; + } + XdrvCall(FUNC_DEVICE_GROUP_ITEM); + } + } + + if (received) { + if (item_processed) { + XdrvMailbox.command_code = DGR_ITEM_EOL; + XdrvCall(FUNC_DEVICE_GROUP_ITEM); + } + } + +write_log: + *log_ptr++ = 0; + AddLog_P(LOG_LEVEL_DEBUG_MORE, log_buffer); + + + + if (received) { + if ((flags & DGR_FLAG_STATUS_REQUEST)) { + if ((flags & DGR_FLAG_RESET) || device_group_member->acked_sequence != device_group->last_full_status_sequence) { + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } + } + } + + + else { + int attempt; + IPAddress ip_address = (device_group_member ? device_group_member->ip_address : IPAddress(DEVICE_GROUPS_ADDRESS)); + for (attempt = 1; attempt <= 5; attempt++) { + if (device_groups_udp.beginPacket(ip_address, DEVICE_GROUPS_PORT)) { + device_groups_udp.write(message, message_length); + if (device_groups_udp.endPacket()) break; + } + delay(10); + } + if (attempt > 5) AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending message")); + } + goto cleanup; + +badmsg: + AddLog_P(LOG_LEVEL_ERROR, PSTR("%s ** incorrect length"), log_buffer); + +cleanup: + if (received) { + skip_light_fade = false; + ignore_dgr_sends = false; + } +} + +bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...) +{ + + if (!device_groups_up) return 1; + + + if (device_group_index >= device_group_count) return 0; + + + bool with_local = ((message_type & DGR_MSGTYPFLAG_WITH_LOCAL) != 0); + message_type = (DevGroupMessageType)(message_type & 0x7F); + + + if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0; + + + struct device_group * device_group = &device_groups[device_group_index]; + + + if (device_group->initial_status_requests_remaining) return 1; + + +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Building %s %spacket"), device_group->group_name, (message_type == DGR_MSGTYP_FULL_STATUS ? PSTR("full status ") : PSTR(""))); +#endif + uint16_t original_sequence = device_group->outgoing_sequence; + uint16_t flags = 0; + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) + flags = DGR_FLAG_MORE_TO_COME; + else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) + flags = DGR_FLAG_DIRECT; + uint8_t * message_ptr = BeginDeviceGroupMessage(device_group, flags, building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE); + + + + + if (message_type == DGR_MSGTYP_FULL_STATUS) { + device_group->last_full_status_sequence = device_group->outgoing_sequence; + device_group->message_length = 0; + + + + building_status_message = true; + + + SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + XdrvMailbox.index = 0; + if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL; + XdrvMailbox.command_code = DGR_ITEM_STATUS; + XdrvMailbox.topic = (char *)&device_group_index; + XdrvCall(FUNC_DEVICE_GROUP_ITEM); + building_status_message = false; + + + *(message_ptr - 2) |= DGR_FLAG_FULL_STATUS; + + + if (!device_group->message_length) { + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + } + } + + else { +#ifdef USE_DEVICE_GROUPS_SEND + uint8_t out_buffer[128]; + bool escaped; + char chr; + char oper; + uint32_t old_value; + uint8_t * out_ptr = out_buffer; +#endif + struct item { + uint8_t item; + uint32_t value; + void * value_ptr; + } item_array[32]; + bool shared; + uint8_t item; + uint32_t value; + uint8_t * value_ptr; + uint8_t * first_item_ptr = message_ptr; + struct item * item_ptr; + va_list ap; + + + item_ptr = item_array; +#ifdef USE_DEVICE_GROUPS_SEND + if (message_type == DGR_MSGTYPE_UPDATE_COMMAND) { + value_ptr = (uint8_t *)XdrvMailbox.data; + while ((item = strtoul((char *)value_ptr, (char **)&value_ptr, 0))) { + item_ptr->item = item; + if (*value_ptr != '=') return 1; + value_ptr++; + if (item <= DGR_ITEM_MAX_32BIT) { + oper = 0; + if (*value_ptr == '@') { + oper = value_ptr[1]; + value_ptr += 2; + } + value = (isdigit(*value_ptr) ? strtoul((char *)value_ptr, (char **)&value_ptr, 0) : 1); + if (oper) { + old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1])); + value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value))); + } + item_ptr->value = value; + } + else { + item_ptr->value_ptr = out_ptr; + if (item <= DGR_ITEM_MAX_STRING) { + escaped = false; + while ((chr = *value_ptr++)) { + if (chr == ' ' && !escaped) break; + if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr; + } + *out_ptr = 0; + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + for (int i = 0; i < 6; i++) { + *out_ptr++ = strtoul((char *)value_ptr, (char **)&value_ptr, 0); + if (*value_ptr == ',') value_ptr++; + } + break; + } + } + } + item_ptr++; + } + } + else { +#endif + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + item_ptr->item = item; + if (item <= DGR_ITEM_MAX_32BIT) + item_ptr->value = va_arg(ap, int); + else if (item <= DGR_ITEM_MAX_STRING) + item_ptr->value_ptr = va_arg(ap, char *); + else { + item_ptr->value_ptr = va_arg(ap, uint8_t *); + } + item_ptr++; + } + va_end(ap); +#ifdef USE_DEVICE_GROUPS_SEND + } +#endif + item_ptr->item = 0; + + + + + + if (device_group->message_length) { + int kept_item_count = 0; + + + + uint8_t * previous_message_ptr = message_ptr; + while (item = *previous_message_ptr++) { + + + if (item <= DGR_ITEM_MAX_32BIT) { + value = 1; + if (item > DGR_ITEM_MAX_8BIT) { + value = 2; + if (item > DGR_ITEM_MAX_16BIT) { + value = 4; + } + } + } + else { + value = *previous_message_ptr + 1; + } + + + for (item_ptr = item_array; item_ptr->item; item_ptr++) { + if (item_ptr->item == item) break; + } + + + if (!item_ptr->item) { + kept_item_count++; + *message_ptr++ = item; + memmove(message_ptr, previous_message_ptr, value); + message_ptr += value; + } + + + previous_message_ptr += value; + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: %u items carried over"), kept_item_count); +#endif + } + + + for (item_ptr = item_array; (item = item_ptr->item); item_ptr++) { + + + shared = true; + if (!device_group_index && message_type != DGR_MSGTYPE_UPDATE_COMMAND) shared = DeviceGroupItemShared(false, item); + if (shared) { + *message_ptr++ = item; + + + if (item <= DGR_ITEM_MAX_32BIT) { + value = item_ptr->value; + *message_ptr++ = value & 0xff; + if (item > DGR_ITEM_MAX_8BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + if (item > DGR_ITEM_MAX_16BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + value >>= 8; + + if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? devices_present : 1); + *message_ptr++ = value; + } + } + } + + + else { + if (item <= DGR_ITEM_MAX_STRING) { + value = strlen((const char *)item_ptr->value_ptr) + 1; + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + value = 6; + break; + } + } + + + *message_ptr++ = value; + memcpy(message_ptr, item_ptr->value_ptr, value); + message_ptr += value; + } + } + } + + + if (message_ptr != first_item_ptr) { + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + } + + + if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return 0; + } + + + if (!device_group->message_length) { + device_group->outgoing_sequence = original_sequence; + return 0; + } + + + SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); + +#ifdef USE_DEVICE_GROUPS_SEND + + if (with_local) { + struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox; + SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, true); + XdrvMailbox = save_XdrvMailbox; + } +#endif + + uint32_t now = millis(); + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { + device_group->message_length = 0; + device_group->next_ack_check_time = 0; + } + else { + device_group->ack_check_interval = 200; + device_group->next_ack_check_time = now + device_group->ack_check_interval; + if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; + device_group->member_timeout_time = now + DGR_MEMBER_TIMEOUT; + } + + device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL; + if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; + return 0; +} + +void ProcessDeviceGroupMessage(uint8_t * message, int message_length) +{ + + uint8_t device_group_index = 0; + struct device_group * device_group = device_groups; + char * message_group_name = (char *)message + sizeof(DEVICE_GROUP_MESSAGE) - 1; + for (;;) { + if (!strcmp(message_group_name, device_group->group_name)) break; + if (++device_group_index >= device_group_count) return; + device_group++; + } + + + struct device_group_member * device_group_member; + IPAddress remote_ip = device_groups_udp.remoteIP(); + struct device_group_member * * flink = &device_group->device_group_members; + for (;;) { + device_group_member = *flink; + if (!device_group_member) { + device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); + if (device_group_member == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating member block")); + return; + } + device_group_member->ip_address = remote_ip; + *flink = device_group_member; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s added"), IPAddressToString(remote_ip)); + break; + } + else if (device_group_member->ip_address == remote_ip) { + break; + } + flink = &device_group_member->flink; + } + + SendReceiveDeviceGroupMessage(device_group, device_group_member, message, message_length, true); +} + +void DeviceGroupStatus(uint8_t device_group_index) +{ + if (Settings.flag4.device_groups_enabled && device_group_index < device_group_count) { + char buffer[1024]; + int member_count = 0; + struct device_group * device_group = &device_groups[device_group_index]; + buffer[0] = buffer[1] = 0; + for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member; device_group_member = device_group_member->flink) { + snprintf_P(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence); + member_count++; + } + Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}}"), device_group_index, device_group->group_name, device_group->outgoing_sequence, member_count, &buffer[1]); + } +} + +void DeviceGroupsLoop(void) +{ + if (!device_groups_up || restart_flag) return; + + while (device_groups_udp.parsePacket()) { + uint8_t packet_buffer[512]; + int length = device_groups_udp.read(packet_buffer, sizeof(packet_buffer) - 1); + if (length > 0) { + packet_buffer[length] = 0; + if (!strncmp_P((char *)packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { + ProcessDeviceGroupMessage(packet_buffer, length); + } + } + } + + uint32_t now = millis(); + + + if ((long)(now - next_check_time) >= 0) { +#ifdef DEVICE_GROUPS_DEBUG +AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_check_time, now); +#endif + next_check_time = now + DGR_ANNOUNCEMENT_INTERVAL * 2; + + struct device_group * device_group = device_groups; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { + + + if (device_group->next_ack_check_time) { + + + if ((long)(now - device_group->next_ack_check_time) >= 0) { + + + if (device_group->initial_status_requests_remaining) { + if (--device_group->initial_status_requests_remaining) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending initial status request for group %s"), device_group->group_name); +#endif + SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); + device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; + next_check_time = device_group->next_ack_check_time = now + 200; + continue; + } + + + + else { + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } + } + + + else { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for ack's")); +#endif + bool acked = true; + struct device_group_member ** flink = &device_group->device_group_members; + struct device_group_member * device_group_member; + while ((device_group_member = *flink)) { + + + if (device_group_member->acked_sequence != device_group->outgoing_sequence) { + + + + if ((long)(now - device_group->member_timeout_time) >= 0) { + *flink = device_group_member->flink; + free(device_group_member); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s removed"), IPAddressToString(device_group_member->ip_address)); + continue; + } + + + SendReceiveDeviceGroupMessage(device_group, device_group_member, device_group->message, device_group->message_length, false); + device_group_member->unicast_count++; + acked = false; + } + flink = &device_group_member->flink; + } + + + + if (acked) { + device_group->next_ack_check_time = 0; + device_group->message_length = 0; + } + + + + + else { + device_group->ack_check_interval *= 2; + if (device_group->ack_check_interval > 5000) device_group->ack_check_interval = 5000; + device_group->next_ack_check_time = now + device_group->ack_check_interval; + } + } + } + + if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; + } + + + + + +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now); +#endif + if ((long)(now - device_group->next_announcement_time) >= 0) { + SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, false); + device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000); + } + if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; + } + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_eeprom.ino" +# 26 "/workspace/Tasmota/tasmota/support_eeprom.ino" +#ifdef USE_EEPROM + +#ifdef USE_24C256 + +#include +#define EEPROM_ADDRESS 0x50 +static Eeprom24C128_256 m_eeprom(EEPROM_ADDRESS); + +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.writeBytes(addr,len,(uint8_t*)buff); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.readBytes(addr,len,(uint8_t*)buff); +} + +uint32_t eeprom_init(uint32_t size) { + if (i2c_flg) { + if (I2cActive(EEPROM_ADDRESS) || I2cSetDevice(EEPROM_ADDRESS)) { + + I2cSetActiveFound(EEPROM_ADDRESS, "24C256"); + return 1; + } + } + return 0; +} + +#else + +#ifdef ESP32 + + +uint32_t eeprom_init(uint32_t size) { + return EEPROM.begin(size); +} +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.writeBytes(addr, buff, len); + EEPROM.commit(); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.readBytes(addr, buff, len); +} + +#else + +uint32_t eeprom_init(uint32_t size) { + EEPROM.begin(size); + return 1; +} +void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) { + for (uint32_t cnt=0; cnt 100) { free_block_size -= 100; } + return free_block_size; +} + +void ESP_Restart(void) { + + ESP.reset(); +} + +#endif + + + + + +#ifdef ESP32 + + + +#include +#include + +void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) { + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READONLY, &handle); + size_t size = nSettingsLen; + nvs_get_blob(handle, sName, pSettings, &size); + nvs_close(handle); + interrupts(); +} + +void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) { + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_set_blob(handle, sName, pSettings, nSettingsLen); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + +void NvmErase(const char *sNvsName) { + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_erase_all(handle); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + +void SettingsErase(uint8_t type) { + if (1 == type) { + } else if (2 == type) { + } else if (3 == type) { + } + + NvmErase("main"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type); +} + +void SettingsRead(void *data, size_t size) { + NvmLoad("main", "Settings", data, size); +} + +void SettingsWrite(const void *pSettings, unsigned nSettingsLen) { + NvmSave("main", "Settings", pSettings, nSettingsLen); +} + +void QPCRead(void *pSettings, unsigned nSettingsLen) { + NvmLoad("qpc", "pcreg", pSettings, nSettingsLen); +} + +void QPCWrite(const void *pSettings, unsigned nSettingsLen) { + NvmSave("qpc", "pcreg", pSettings, nSettingsLen); +} + +void ZigbeeErase(void) { + NvmErase("zb"); +} + +void ZigbeeRead(void *pSettings, unsigned nSettingsLen) { + NvmLoad("zb", "zigbee", pSettings, nSettingsLen); +} + +void ZigbeeWrite(const void *pSettings, unsigned nSettingsLen) { + NvmSave("zb", "zigbee", pSettings, nSettingsLen); +} + + + + +static bool bNetIsTimeSync = false; + +void SntpInit() { + bNetIsTimeSync = true; +} + +uint32_t SntpGetCurrentTimestamp(void) { + time_t now = 0; + if (bNetIsTimeSync || ntp_force_sync) + { + + + configTime(0, 0, SettingsText(SET_NTPSERVER1), SettingsText(SET_NTPSERVER2), SettingsText(SET_NTPSERVER3)); + bNetIsTimeSync = false; + ntp_force_sync = false; + } + time(&now); + return now; +} + + + + + +void CrashDump(void) { +} + +bool CrashFlag(void) { + return false; +} + +void CrashDumpClear(void) { +} + +void CmndCrash(void) { + + + + +} + + +void CmndWDT(void) { + + + + + + +} + +void CmndBlockedLoop(void) { + + + + + +} + + + + + +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void DisableBrownout(void) { + + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); +} + + + + + +String ESP32GetResetReason(uint32_t cpu_no) { + + switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) { + case POWERON_RESET : return F("Vbat power on reset"); + case SW_RESET : return F("Software reset digital core"); + case OWDT_RESET : return F("Legacy watch dog reset digital core"); + case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); + case SDIO_RESET : return F("Reset by SLC module, reset digital core"); + case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); + case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); + case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); + case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); + case TGWDT_CPU_RESET : return F("Time Group reset CPU"); + case SW_CPU_RESET : return F("Software reset CPU"); + case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); + case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); + case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); + case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); + default : return F("NO_MEAN"); + } +} + +String ESP_getResetReason(void) { + return ESP32GetResetReason(0); +} + +uint32_t ESP_ResetInfoReason(void) { + RESET_REASON reason = rtc_get_reset_reason(0); + if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; } + if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; } + if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; } + if (SW_RESET == reason) { return REASON_EXT_SYS_RST; } +} + +uint32_t ESP_getChipId(void) { + uint32_t id = 0; + for (uint32_t i = 0; i < 17; i = i +8) { + id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; + } + return id; +} + +uint32_t ESP_getSketchSize(void) { + static uint32_t sketchsize = 0; + + if (!sketchsize) { + sketchsize = ESP.getSketchSize(); + } + return sketchsize; +} + +uint32_t ESP_getFreeHeap(void) { + + return ESP.getMaxAllocHeap(); +} + +uint32_t ESP_getMaxAllocHeap(void) { + + uint32_t free_block_size = ESP.getMaxAllocHeap(); + if (free_block_size > 100) { free_block_size -= 100; } + return free_block_size; +} + +void ESP_Restart(void) { + ESP.restart(); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_esptool.ino" +# 20 "/workspace/Tasmota/tasmota/support_esptool.ino" +#ifdef ESP8266 +#define USE_ESPTOOL +#endif + +#ifdef USE_ESPTOOL + + + + + + + +#define READ_REG(REG) (*((volatile uint32_t *)(REG))) +#define WRITE_REG(REG,VAL) *((volatile uint32_t *)(REG)) = (VAL) +#define REG_SET_MASK(reg,mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) + +#define SPI_BASE_REG 0x60000200 + +#define SPI_CMD_REG (SPI_BASE_REG + 0x00) +#define SPI_FLASH_RDSR (1<<27) +#define SPI_FLASH_SE (1<<24) +#define SPI_FLASH_BE (1<<23) +#define SPI_FLASH_WREN (1<<30) + +#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) +#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) +#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) +#define SPI_W0_REG (SPI_BASE_REG + 0x40) +#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) + +#define SPI_ST 0x7 + + +#define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / SPI_FLASH_SEC_SIZE) + + +static const uint32_t STATUS_WIP_BIT = (1 << 0); + + +inline static void spi_wait_ready(void) +{ + while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } +} + + + +static bool spiflash_is_ready(void) +{ + spi_wait_ready(); + WRITE_REG(SPI_RD_STATUS_REG, 0); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); + while(READ_REG(SPI_CMD_REG) != 0) { } + uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); + return (status_value & STATUS_WIP_BIT) == 0; +} + +static void spi_write_enable(void) +{ + while(!spiflash_is_ready()) { } + WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); + while(READ_REG(SPI_CMD_REG) != 0) { } +} + +bool EsptoolEraseSector(uint32_t sector) +{ + spi_write_enable(); + spi_wait_ready(); + + WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); + while(READ_REG(SPI_CMD_REG) != 0) { } + while(!spiflash_is_ready()) { } + + return true; +} + +void EsptoolErase(uint32_t start_sector, uint32_t end_sector) +{ + int next_erase_sector = start_sector; + int remaining_erase_sector = end_sector - start_sector; + + while (remaining_erase_sector > 0) { + spi_write_enable(); + + uint32_t command = SPI_FLASH_SE; + uint32_t sectors_to_erase = 1; + if (remaining_erase_sector >= SECTORS_PER_BLOCK && + next_erase_sector % SECTORS_PER_BLOCK == 0) { + command = SPI_FLASH_BE; + sectors_to_erase = SECTORS_PER_BLOCK; + } + uint32_t addr = next_erase_sector * SPI_FLASH_SEC_SIZE; + + spi_wait_ready(); + WRITE_REG(SPI_ADDR_REG, addr & 0xffffff); + WRITE_REG(SPI_CMD_REG, command); + while(READ_REG(SPI_CMD_REG) != 0) { } + remaining_erase_sector -= sectors_to_erase; + next_erase_sector += sectors_to_erase; + + while (!spiflash_is_ready()) { } + yield(); + OsWatchLoop(); + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_features.ino" +# 24 "/workspace/Tasmota/tasmota/support_features.ino" +void GetFeatures(void) +{ + feature_drv1 = 0x00000000; + +#if defined(USE_ENERGY_SENSOR) && defined(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 +#if defined(USE_WEBSERVER) && defined(WEBSERVER_ADVERTISE) + feature_drv1 |= 0x00000100; +#endif +#if defined(USE_WEBSERVER) && defined(USE_EMULATION_HUE) + feature_drv1 |= 0x00000200; +#endif + + feature_drv1 |= 0x00000400; + + + + + + + +#if defined(USE_DISCOVERY) && defined(MQTT_HOST_DISCOVERY) + feature_drv1 |= 0x00002000; +#endif +#if defined(USE_LIGHT) && defined(USE_ARILUX_RF) + feature_drv1 |= 0x00004000; +#endif +#if defined(USE_LIGHT) && defined(USE_WS2812) + feature_drv1 |= 0x00008000; +#endif +#if defined(USE_LIGHT) && defined(USE_WS2812) && defined(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 +#if defined(USE_IR_REMOTE) && defined(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 +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + feature_drv1 |= 0x02000000; +#endif +#if defined(USE_TIMERS) && defined(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 +#if defined(USE_ENERGY_SENSOR) && defined(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 +#if defined(USE_DISPLAY) && defined(USE_DISPLAY_MODES1TO5) + feature_drv2 |= 0x00000020; +#endif +#if defined(USE_DISPLAY) && defined(USE_DISPLAY_GRAPH) + feature_drv2 |= 0x00000040; +#endif +#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_LCD) + feature_drv2 |= 0x00000080; +#endif +#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SSD1306) + feature_drv2 |= 0x00000100; +#endif +#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_MATRIX) + feature_drv2 |= 0x00000200; +#endif +#if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_ILI9341) + feature_drv2 |= 0x00000400; +#endif +#if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_EPAPER_29) + feature_drv2 |= 0x00000800; +#endif +#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SH1106) + feature_drv2 |= 0x00001000; +#endif +#ifdef USE_MP3_PLAYER + feature_drv2 |= 0x00002000; +#endif +#if defined(USE_I2C) && defined(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 +#if defined(USE_WEBSERVER) && defined(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 +#if defined(USE_ADC_VCC) || defined(USE_ADC) + feature_sns1 |= 0x00000002; +#endif +#ifdef USE_ENERGY_SENSOR + feature_sns1 |= 0x00000004; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(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 +#if defined(USE_I2C) && defined(USE_SHT) + feature_sns1 |= 0x00000100; +#endif +#if defined(USE_I2C) && defined(USE_HTU) + feature_sns1 |= 0x00000200; +#endif +#if defined(USE_I2C) && defined(USE_BMP) + feature_sns1 |= 0x00000400; +#endif +#if defined(USE_I2C) && defined(USE_BMP) && defined(USE_BME680) + feature_sns1 |= 0x00000800; +#endif +#if defined(USE_I2C) && defined(USE_BH1750) + feature_sns1 |= 0x00001000; +#endif +#if defined(USE_I2C) && defined(USE_VEML6070) + feature_sns1 |= 0x00002000; +#endif +#if defined(USE_I2C) && defined(USE_ADS1115_I2CDEV) + feature_sns1 |= 0x00004000; +#endif +#if defined(USE_I2C) && defined(USE_ADS1115) + feature_sns1 |= 0x00008000; +#endif +#if defined(USE_I2C) && defined(USE_INA219) + feature_sns1 |= 0x00010000; +#endif +#if defined(USE_I2C) && defined(USE_SHT3X) + feature_sns1 |= 0x00020000; +#endif +#ifdef USE_MHZ19 + feature_sns1 |= 0x00040000; +#endif +#if defined(USE_I2C) && defined(USE_TSL2561) + feature_sns1 |= 0x00080000; +#endif +#ifdef USE_SENSEAIR + feature_sns1 |= 0x00100000; +#endif +#ifdef USE_PMS5003 + feature_sns1 |= 0x00200000; +#endif +#if defined(USE_I2C) && defined(USE_MGS) + feature_sns1 |= 0x00400000; +#endif +#ifdef USE_NOVA_SDS + feature_sns1 |= 0x00800000; +#endif +#if defined(USE_I2C) && defined(USE_SGP30) + feature_sns1 |= 0x01000000; +#endif +#ifdef USE_SR04 + feature_sns1 |= 0x02000000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_SDM120) + feature_sns1 |= 0x04000000; +#endif +#if defined(USE_I2C) && defined(USE_SI1145) + feature_sns1 |= 0x08000000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_SDM630) + feature_sns1 |= 0x10000000; +#endif +#if defined(USE_I2C) && defined(USE_LM75AD) + feature_sns1 |= 0x20000000; +#endif +#if defined(USE_I2C) && defined(USE_APDS9960) + feature_sns1 |= 0x40000000; +#endif +#ifdef USE_TM1638 + feature_sns1 |= 0x80000000; +#endif + + + feature_sns2 = 0x00000000; + +#if defined(USE_I2C) && defined(USE_MCP230xx) + feature_sns2 |= 0x00000001; +#endif +#if defined(USE_I2C) && defined(USE_MPR121) + feature_sns2 |= 0x00000002; +#endif +#if defined(USE_I2C) && defined(USE_CCS811) + feature_sns2 |= 0x00000004; +#endif +#if defined(USE_I2C) && defined(USE_MPU6050) + feature_sns2 |= 0x00000008; +#endif +#if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_OUTPUT) + feature_sns2 |= 0x00000010; +#endif +#if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_DISPLAYOUTPUT) + feature_sns2 |= 0x00000020; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) + feature_sns2 |= 0x00000040; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_CSE7766) + feature_sns2 |= 0x00000080; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) + feature_sns2 |= 0x00000100; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_AC) + feature_sns2 |= 0x00000200; +#endif +#if defined(USE_I2C) && defined(USE_DS3231) + feature_sns2 |= 0x00000400; +#endif +#ifdef USE_HX711 + feature_sns2 |= 0x00000800; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_DC) + feature_sns2 |= 0x00001000; +#endif +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) + feature_sns2 |= 0x00002000; +#endif +#if defined(USE_I2C) && defined(USE_MGC3130) + feature_sns2 |= 0x00004000; +#endif +#ifdef USE_RF_SENSOR + feature_sns2 |= 0x00008000; +#endif +#if defined(USE_RF_SENSOR) && defined(USE_THEO_V2) + feature_sns2 |= 0x00010000; +#endif +#if defined(USE_RF_SENSOR) && defined(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 +#if defined(USE_I2C) && defined(USE_MAX44009) + feature_sns2 |= 0x00200000; +#endif +#if defined(USE_I2C) && defined(USE_SCD30) + feature_sns2 |= 0x00400000; +#endif +#ifdef USE_HRE + feature_sns2 |= 0x00800000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_ADE7953) + feature_sns2 |= 0x01000000; +#endif +#if defined(USE_I2C) && defined(USE_SPS30) + feature_sns2 |= 0x02000000; +#endif +#if defined(USE_I2C) && defined(USE_VL53L0X) + feature_sns2 |= 0x04000000; +#endif +#if defined(USE_I2C) && defined(USE_MLX90614) + feature_sns2 |= 0x08000000; +#endif +#ifdef USE_MAX31865 + feature_sns2 |= 0x10000000; +#endif +#if defined(USE_I2C) && defined(USE_CHIRP) + feature_sns2 |= 0x20000000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_SOLAX_X1) + feature_sns2 |= 0x40000000; +#endif +#if defined(USE_I2C) && defined(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 +#if defined(USE_I2C) && defined(USE_INA226) + feature5 |= 0x00000010; +#endif +#ifdef USE_A4988_STEPPER + feature5 |= 0x00000020; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_DDS2382) + feature5 |= 0x00000040; +#endif +#if defined(USE_LIGHT) && defined(USE_SM2135) + feature5 |= 0x00000080; +#endif +#ifdef USE_SHUTTER + feature5 |= 0x00000100; +#endif +#if defined(USE_I2C) && defined(USE_PCF8574) + feature5 |= 0x00000200; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_DDSU666) + feature5 |= 0x00000400; +#endif +#ifdef USE_DEEPSLEEP + feature5 |= 0x00000800; +#endif +#ifdef USE_SONOFF_SC + feature5 |= 0x00001000; +#endif +#ifdef USE_SONOFF_RF + feature5 |= 0x00002000; +#endif +#if defined(USE_LIGHT) && defined(USE_SONOFF_L1) + feature5 |= 0x00004000; +#endif +#if defined(USE_LIGHT) && defined(USE_EXS_DIMMER) + feature5 |= 0x00008000; +#endif +#ifdef USE_TASMOTA_CLIENT + feature5 |= 0x00010000; +#endif +#if defined(USE_I2C) && defined(USE_HIH6) + feature5 |= 0x00020000; +#endif +#ifdef USE_HPMA + feature5 |= 0x00040000; +#endif +#if defined(USE_I2C) && defined(USE_TSL2591) + feature5 |= 0x00080000; +#endif +#if defined(USE_I2C) && defined(USE_DHT12) + feature5 |= 0x00100000; +#endif +#if defined(USE_I2C) && defined(USE_DS1624) + feature5 |= 0x00200000; +#endif +#ifdef USE_GPS + feature5 |= 0x00400000; +#endif +#if defined(USE_I2C) && defined(USE_HOTPLUG) + feature5 |= 0x00800000; +#endif +#ifdef USE_NRF24 + feature5 |= 0x01000000; +#endif +#ifdef USE_MIBLE + feature5 |= 0x02000000; +#endif +#ifdef USE_HM10 + feature5 |= 0x04000000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_LE01MR) + feature5 |= 0x08000000; +#endif +#if defined(USE_I2C) && defined(USE_AHT1x) + feature5 |= 0x10000000; +#endif +#if defined(USE_I2C) && defined(USE_WEMOS_MOTOR_V1) + feature5 |= 0x20000000; +#endif +#ifdef USE_DEVICE_GROUPS + feature5 |= 0x40000000; +#endif +#ifdef USE_PWM_DIMMER + feature5 |= 0x80000000; +#endif + + + + feature6 = 0x00000000; + +#ifdef USE_KEELOQ + feature6 |= 0x00000001; +#endif +#ifdef USE_HRXL + feature6 |= 0x00000002; +#endif +#ifdef USE_SONOFF_D1 + feature6 |= 0x00000004; +#endif +#if defined(USE_I2C) && defined(USE_HDC1080) + feature6 |= 0x00000008; +#endif +#if defined(USE_I2C) && defined(USE_IAQ) + feature6 |= 0x00000010; +#endif +#if defined(USE_DISPLAY) && defined(USE_DISPLAY_SEVENSEG) + feature6 |= 0x00000020; +#endif +#if defined(USE_I2C) && defined(USE_AS3935) + feature6 |= 0x00000040; +#endif +#ifdef USE_PING + feature6 |= 0x00000080; +#endif +#ifdef USE_WINDMETER + feature6 |= 0x00000100; +#endif +#ifdef USE_OPENTHERM + feature6 |= 0x00000200; +#endif +#ifdef USE_THERMOSTAT + feature6 |= 0x00000400; +#endif +#if defined(USE_I2C) && defined(USE_VEML6075) + feature6 |= 0x00000800; +#endif +#if defined(USE_I2C) && defined(USE_VEML7700) + feature6 |= 0x00001000; +#endif +#if defined(USE_I2C) && defined(USE_MCP9808) + feature6 |= 0x00002000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_BL0940) + feature6 |= 0x00004000; +#endif +#ifdef USE_TELEGRAM + feature6 |= 0x00008000; +#endif +#if defined(USE_I2C) && defined(USE_HP303B) + feature6 |= 0x00010000; +#endif +#ifdef USE_TCP_BRIDGE + feature6 |= 0x00020000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_TELEINFO) + feature6 |= 0x00040000; +#endif +#ifdef USE_LMT01 + feature6 |= 0x00080000; +#endif +#ifdef USE_PROMETHEUS + feature6 |= 0x00100000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_IEM3000) + feature6 |= 0x00200000; +#endif +#ifdef USE_DYP + feature6 |= 0x00400000; +#endif +#ifdef USE_I2S_AUDIO + feature6 |= 0x00800000; +#endif +#ifdef USE_MLX90640 + feature6 |= 0x01000000; +#endif +#if defined(USE_I2C) && defined(USE_VL53L1X) + feature6 |= 0x02000000; +#endif +#ifdef USE_MIEL_HVAC + feature6 |= 0x04000000; +#endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_WE517) + feature6 |= 0x08000000; +#endif +#if defined(USE_I2C) && defined(USE_EZOPH) + feature6 |= 0x10000000; +#endif +#if defined(ESP32) && defined(USE_TTGO_WATCH) + feature6 |= 0x20000000; +#endif +#if defined(ESP32) && defined(USE_ETHERNET) + feature6 |= 0x40000000; +#endif +#if defined(ESP32) && defined(USE_WEBCAM) + feature6 |= 0x80000000; +#endif + + + + feature7 = 0x00000000; + +#if defined(USE_I2C) && defined(USE_EZOORP) + feature7 |= 0x00000001; +#endif +#if defined(USE_I2C) && defined(USE_EZORTD) + feature7 |= 0x00000002; +#endif +#if defined(USE_I2C) && defined(USE_EZOHUM) + feature7 |= 0x00000004; +#endif +#if defined(USE_I2C) && defined(USE_EZOEC) + feature7 |= 0x00000008; +#endif +#if defined(USE_I2C) && defined(USE_EZOCO2) + feature7 |= 0x00000010; +#endif +# 683 "/workspace/Tasmota/tasmota/support_features.ino" +} +# 1 "/workspace/Tasmota/tasmota/support_flash_log.ino" +# 39 "/workspace/Tasmota/tasmota/support_flash_log.ino" +#ifdef USE_FLOG +#ifdef ESP8266 + +class FLOG + +#define MAGIC_WORD_FL 0x464c + +{ + +struct header_t{ + uint16_t magic_word; + uint16_t padding; + uint32_t physical_start_sector:10; + uint32_t number:10; + uint32_t buf_pointer:12; + }; + +private: +void _readSector(uint8_t one_sector); +void _eraseSector(uint8_t one_sector); +void _writeSector(uint8_t one_sector); +void _clearBuffer(void); +void _searchSaves(void); +void _findFirstErasedSector(void); +void _showBuffer(void); +void _initBuffer(void); +void _saveBufferToSector(void); +header_t _saved_header; + +public: + uint32_t size; + uint32_t start; + uint32_t end; + uint16_t num_sectors; + + uint16_t first_erased_sector; + uint16_t current_sector; + + uint16_t bytes_left; + uint16_t sectors_left; + + uint8_t mode = 0; + bool found_saved_data = false; + bool ready = false; + bool running_download = false; + bool recording = false; + + union sector_t{ + uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; + uint8_t byte_buffer[FLASH_SECTOR_SIZE]; + header_t header; + } sector; + + void init(void); + void addToBuffer(uint8_t src[], uint32_t size); + void startRecording(bool append); + void stopRecording(void); + + typedef void (*CallbackNoArgs) (); + typedef void (*CallbackWithArgs) (uint8_t *_record); + + void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); +}; + +extern "C" uint32_t _SPIFFS_start; +extern "C" uint32_t _FS_start; + + + + +void FLOG::init(void) +{ +DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); +size = ESP.getSketchSize(); + +start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); +end = (uint32_t)&_FS_start - 0x40200000; +num_sectors = (end - start)/FLASH_SECTOR_SIZE; +DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); +_findFirstErasedSector(); +if(first_erased_sector == 0xffff){ + _eraseSector(0); + first_erased_sector = 0; +} +_searchSaves(); +_initBuffer(); +ready = true; +} +# 139 "/workspace/Tasmota/tasmota/support_flash_log.ino" +void FLOG::_readSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); + ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} + + + + + +void FLOG::_eraseSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); + ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); +} + + + + + +void FLOG::_writeSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); + ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} + + + + +void FLOG::_clearBuffer(){ + for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ + sector.dword_buffer[i] = 0; + } + sector.header.buf_pointer = sizeof(sector.header); + +} + + + + +void FLOG::_saveBufferToSector(){ + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); + _writeSector(current_sector); + if(current_sector == num_sectors){ + current_sector = 0; + } + else{ + current_sector++; + } + _eraseSector(current_sector); + _clearBuffer(); + sector.header.number++; + DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); +} + + + + + +void FLOG::_findFirstErasedSector(){ + for (uint32_t i = 0; i3){ + break; + } + } +} + + + + + + + +void FLOG::addToBuffer(uint8_t src[], uint32_t size){ + if(mode == 0){ + if(sector.header.number == num_sectors && !ready){ + return; + } + } + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + + + + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; + + } + else{ + DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); + DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + _saveBufferToSector(); + sectors_left++; + + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; + } + } +} + + + + + + +void FLOG::startRecording(bool append){ + if(recording){ + DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); + return; + } + recording = true; + DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); + _initBuffer(); + if(!found_saved_data) { + append = false; + } + if(append){ + sector.header.number = _saved_header.number+1; + sector.header.physical_start_sector = _saved_header.physical_start_sector; + } + else{ + sector.header.physical_start_sector = (uint16_t)first_erased_sector; + found_saved_data = false; + sectors_left = 0; + } + } + + + + + +void FLOG::stopRecording(void){ + _saveBufferToSector(); + _findFirstErasedSector(); + _searchSaves(); + _initBuffer(); + recording = false; + found_saved_data = true; + } +# 378 "/workspace/Tasmota/tasmota/support_flash_log.ino" + void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ + + _readSector(sector.header.physical_start_sector); + uint32_t next_sector = sector.header.physical_start_sector; + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); + running_download = true; + + sendHeader(); + + while(sectors_left){ + DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); + + uint32_t k = sizeof(sector.header); + while(bytes_left){ + + uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; + + sendRecord(_record_start); + if(k%128 == 0){ + + OsWatchLoop(); + delay(ssleep); + } + k+=size; + if(bytes_left>7){ + bytes_left-=size; + } + else{ + bytes_left = 0; + DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); + } + } + next_sector++; + if(next_sector>num_sectors){ + next_sector = 0; + } + sectors_left--; + _readSector(next_sector); + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + OsWatchLoop(); + delay(ssleep); + } + running_download = false; + + sendFooter(); + + _searchSaves(); + _initBuffer(); + } + + #endif + #endif +# 1 "/workspace/Tasmota/tasmota/support_float.ino" +# 20 "/workspace/Tasmota/tasmota/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; } + if (x == 1.0) { return 0; } + double z = (x + 1) / (x - 1); + double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); + double totalValue = 0; + double powe = 1; + for (uint32_t count = 0; count < 10; count++) { + z *= step; + double y = (1 / powe) * z; + totalValue = totalValue + y; + powe = powe + 2; + } + totalValue *= 2; +# 141 "/workspace/Tasmota/tasmota/support_float.ino" + return totalValue; +} +# 151 "/workspace/Tasmota/tasmota/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); +float const f_180pi = 180 / f_pi; +# 191 "/workspace/Tasmota/tasmota/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); + } + return 0.0; +} + + + + +float sin_52(float x) +{ + return cos_52((float)f_halfpi - x); +} +# 245 "/workspace/Tasmota/tasmota/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)); +} +# 265 "/workspace/Tasmota/tasmota/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); + } + return 0.0; +} +# 295 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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 (ifrom_min >= ifrom_max) { + if (ito_min > ito_max) { + return ito_max; + } else { + 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)); + + + if (to_min > to_max) { + + num = (from_max - num) + from_min; + to_min = ito_max; + to_max = ito_min; + } + + 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)); +} + + +float ModulusRangef(float f, float a, float b) { + if (b <= a) { return a; } + float range = b - a; + float x = f - a; + x = fmodf(x, range); + if (x < 0.0f) { x += range; } + return x + a; +} + + + + + + +float Polynomialf(const float *factors, uint32_t degree, float x) { + float r = 0.0f; + for (uint32_t i = degree - 1; i >= 0; i--) { + r = r * x + factors[i]; + } + return r; +} +# 1 "/workspace/Tasmota/tasmota/support_jpeg.ino" +# 21 "/workspace/Tasmota/tasmota/support_jpeg.ino" +#ifdef ESP32 +#ifdef JPEG_PICTS + +#include "img_converters.h" +#include "esp_jpg_decode.h" + +void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len) { +uint8_t red, grn, blu; +uint16_t b , g, r; + + for (uint32_t cnt=0; cnt> 3) & 0x1f; + g = ((grn >> 2) & 0x3f) << 5; + r = ((red >> 3) & 0x1f) << 11; + *out++ = (r | g | b); + } +} + +typedef struct { + uint16_t width; + uint16_t height; + uint16_t data_offset; + const uint8_t *input; + uint8_t *output; +} rgb_jpg_decoder; + + +static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len) +{ + rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; + if(buf) { + memcpy(buf, jpeg->input + index, len); + } + return len; +} + + +static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data) +{ + rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; + if(!data){ + if(x == 0 && y == 0){ + + jpeg->width = w; + jpeg->height = h; + + if(!jpeg->output){ + jpeg->output = (uint8_t *)malloc((w*h*3)+jpeg->data_offset); + if(!jpeg->output){ + return false; + } + } + } else { + + } + return true; + } + + size_t jw = jpeg->width*3; + size_t t = y * jw; + size_t b = t + (h * jw); + size_t l = x * 3; + uint8_t *out = jpeg->output+jpeg->data_offset; + uint8_t *o = out; + size_t iy, ix; + + w = w * 3; + + for(iy=t; iy= data_size) return false; + if(data[i] != 0xFF) return false; + if(data[i+1] == 0xC0) { + + *height = data[i+5]*256 + data[i+6]; + *width = data[i+7]*256 + data[i+8]; + return true; + } + else + { + i+=2; + block_length = data[i] * 256 + data[i+1]; + } + } + return false; + }else{ return false; } + + }else{ return false; } +} + + +#endif +#endif + +#ifdef USE_DISPLAY_DUMP +#define bytesPerPixel 3 +#define fileHeaderSize 14 +#define infoHeaderSize 40 + +void createBitmapFileHeader(uint32_t height, uint32_t width, uint8_t *fileHeader) { + int paddingSize = (4 - (width*bytesPerPixel) % 4) % 4; + + int fileSize = fileHeaderSize + infoHeaderSize + (bytesPerPixel*width+paddingSize) * height; + memset(fileHeader,0,fileHeaderSize); + fileHeader[ 0] = (unsigned char)('B'); + fileHeader[ 1] = (unsigned char)('M'); + fileHeader[ 2] = (unsigned char)(fileSize ); + fileHeader[ 3] = (unsigned char)(fileSize>> 8); + fileHeader[ 4] = (unsigned char)(fileSize>>16); + fileHeader[ 5] = (unsigned char)(fileSize>>24); + fileHeader[10] = (unsigned char)(fileHeaderSize + infoHeaderSize); + +} + +void createBitmapInfoHeader(uint32_t height, uint32_t width, uint8_t *infoHeader ) { + memset(infoHeader,0,infoHeaderSize); + + infoHeader[ 0] = (unsigned char)(infoHeaderSize); + infoHeader[ 4] = (unsigned char)(width ); + infoHeader[ 5] = (unsigned char)(width>> 8); + infoHeader[ 6] = (unsigned char)(width>>16); + infoHeader[ 7] = (unsigned char)(width>>24); + infoHeader[ 8] = (unsigned char)(height ); + infoHeader[ 9] = (unsigned char)(height>> 8); + infoHeader[10] = (unsigned char)(height>>16); + infoHeader[11] = (unsigned char)(height>>24); + infoHeader[12] = (unsigned char)(1); + infoHeader[14] = (unsigned char)(bytesPerPixel*8); + infoHeader[24] = (unsigned char)0x13; + infoHeader[25] = (unsigned char)0x0b; + infoHeader[28] = (unsigned char)0x13; + infoHeader[29] = (unsigned char)0x0b; + +} +#endif +# 1 "/workspace/Tasmota/tasmota/support_light_list.ino" +# 25 "/workspace/Tasmota/tasmota/support_light_list.ino" +template +class LList; + +template +class LList_elt { +public: + + LList_elt() : _next(nullptr), _val() {} + + inline T & val(void) { return _val; } + inline LList_elt * next(void) { return _next; } + inline void next(LList_elt * next) { _next = next; } + + friend class LList; + +protected: + LList_elt * _next; + T _val; +}; + + + + + + +template +class LList { +public: + LList() : _head(nullptr) {} + ~LList() { reset(); } + + + void removeHead(void); + void reset(void); + void remove(const T * val); + + + inline bool isEmpty(void) const { return (_head == nullptr) ? true : false; } + size_t length(void) const; + inline T * head(void) { return _head ? &_head->_val : nullptr; } + inline const T * head(void) const { return _head ? &_head->_val : nullptr; } + const T * at(size_t index) const ; + + + inline T * at(size_t index) { return (T*) ((const LList*)this)->at(index); } + + + T & addHead(void); + T & addHead(const T &val); + T & addToLast(void); + + + T & addHead(LList_elt * elt); + T & addToLast(LList_elt * elt); + + + + class iterator { + public: + iterator(LList_elt *_cur): cur(_cur), next(nullptr) { if (cur) { next = cur->_next; } } + iterator operator++() { cur = next; if (cur) { next = cur->_next;} return *this; } + bool operator!=(const iterator & other) const { return cur != other.cur; } + T & operator*() const { return cur->_val; } + private: + LList_elt *cur; + LList_elt *next; + }; + iterator begin() { return iterator(this->_head); } + iterator end() { return iterator(nullptr); } + + + class const_iterator { + public: + const_iterator(const LList_elt *_cur): cur(_cur), next(nullptr) { if (cur) { next = cur->_next; } } + const_iterator operator++() { cur = next; if (cur) { next = cur->_next;} return *this; } + bool operator!=(const_iterator & other) const { return cur != other.cur; } + const T & operator*() const { return cur->_val; } + private: + const LList_elt *cur; + const LList_elt *next; + }; + const_iterator begin() const { return const_iterator(this->_head); } + const_iterator end() const { return const_iterator(nullptr); } + +protected: + LList_elt * _head; +}; + +template +size_t LList::length(void) const { + size_t count = 0; + for (auto & elt : *this) {count++; } + return count; +} + + +template +const T * LList::at(size_t index) const { + size_t count = 0; + for (const auto & elt : *this) { + if (index == count++) { return &elt; } + } + return nullptr; +} + +template +void LList::reset(void) { + while (_head) { + LList_elt * next = _head->next(); + delete _head; + _head = next; + } +} + +template +void LList::removeHead(void) { + if (_head) { + LList_elt * next = _head->next(); + delete _head; + _head = next; + } +} + +template +void LList::remove(const T * val) { + if (nullptr == val) { return; } + + LList_elt **curr_ptr = &_head; + while (*curr_ptr) { + LList_elt * curr_elt = *curr_ptr; + if ( &(curr_elt->_val) == val) { + *curr_ptr = curr_elt->_next; + delete curr_elt; + break; + } + curr_ptr = &((*curr_ptr)->_next); + } +} + +template +T & LList::addHead(void) { + LList_elt * elt = new LList_elt(); + elt->next(_head); + _head = elt; + return elt->_val; +} + +template +T & LList::addHead(const T &val) { + LList_elt * elt = new LList_elt(); + elt->next(_head); + elt->_val = val; + _head = elt; + return elt->_val; +} + +template +T & LList::addHead(LList_elt * elt) { + elt->next(_head); + _head = elt; + return elt->_val; +} + +template +T & LList::addToLast(void) { + LList_elt **curr_ptr = &_head; + while (*curr_ptr) { + curr_ptr = &((*curr_ptr)->_next); + } + LList_elt * elt = new LList_elt(); + *curr_ptr = elt; + return elt->_val; +} + +template +T & LList::addToLast(LList_elt * elt) { + LList_elt **curr_ptr = &_head; + while (*curr_ptr) { + curr_ptr = &((*curr_ptr)->_next); + } + *curr_ptr = elt; + elt->_next = nullptr; + return elt->_val; +} +# 1 "/workspace/Tasmota/tasmota/support_network.ino" +# 24 "/workspace/Tasmota/tasmota/support_network.ino" +struct { + uint8_t begun = 0; +} Mdns; + +#ifdef USE_DISCOVERY +void StartMdns(void) { + if (Settings.flag3.mdns_enabled) { + if (!Mdns.begun) { + + + + + + Mdns.begun = (uint8_t)MDNS.begin(my_hostname); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED); + + } + } +} + +#ifdef MQTT_HOST_DISCOVERY +void MqttDiscoverServer(void) +{ + if (!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 + SettingsUpdateText(SET_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(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port); + } +} +#endif + +#ifdef WEBSERVER_ADVERTISE +void MdnsAddServiceHttp(void) { + if (1 == Mdns.begun) { + Mdns.begun = 2; + MDNS.addService("http", "tcp", WEB_PORT); + } +} + +void MdnsUpdate(void) { + if (2 == Mdns.begun) { + MDNS.update(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); + } +} +#endif +#endif + + + + + +char* NetworkHostname(void) { +#ifdef ESP32 +#ifdef USE_ETHERNET + if (!global_state.eth_down) { + return EthernetHostname(); + } +#endif +#endif + return my_hostname; +} + +IPAddress NetworkAddress(void) { +#ifdef ESP32 +#ifdef USE_ETHERNET + if (!global_state.eth_down) { + return EthernetLocalIP(); + } +#endif +#endif + return WiFi.localIP(); +} + +String NetworkMacAddress(void) { +#ifdef ESP32 +#ifdef USE_ETHERNET + if (!global_state.eth_down) { + return EthernetMacAddress(); + } +#endif +#endif + return WiFi.macAddress(); +} +# 1 "/workspace/Tasmota/tasmota/support_rotary.ino" +# 20 "/workspace/Tasmota/tasmota/support_rotary.ino" +#ifdef ROTARY_V1 +# 36 "/workspace/Tasmota/tasmota/support_rotary.ino" +#ifndef ROTARY_MAX_STEPS +#define ROTARY_MAX_STEPS 10 +#endif +#ifndef ROTARY_START_DIM +#define ROTARY_START_DIM 1 +#endif +#ifndef ROTARY_TIMEOUT +#define ROTARY_TIMEOUT 2 +#endif +#ifndef ROTARY_DEBOUNCE +#define ROTARY_DEBOUNCE 10 +#endif + + + +const uint8_t rotary_dimmer_increment[2] = { 100 / (ROTARY_MAX_STEPS * 3), 100 / ROTARY_MAX_STEPS }; +const uint8_t rotary_ct_increment[2] = { 350 / (ROTARY_MAX_STEPS * 3), 350 / ROTARY_MAX_STEPS }; +const uint8_t rotary_color_increment[2] = { 360 / (ROTARY_MAX_STEPS * 3), 360 / ROTARY_MAX_STEPS }; +const uint8_t rotary_offset = 128; +const int8_t rotary_state_pos[16] = { 0, 1, -1, 2, -1, 0, -2, 1, 1, -2, 0, -1, 2, -1, 1, 0 }; + +struct ROTARY { + uint8_t model; + bool present; +} Rotary; + +struct tEncoder { + volatile uint32_t debounce = 0; + volatile uint8_t state = 0; + volatile uint8_t position; + volatile int8_t direction = 0; + volatile int8_t pina; + volatile int8_t pinb; + uint8_t timeout = 0; + int8_t abs_position[2] = { 0 }; + bool changed = false; +}; +tEncoder Encoder[MAX_ROTARIES]; + + + +bool RotaryButtonPressed(uint32_t button_index) { + if (!Rotary.present) { return false; } + + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { + if (-1 == Encoder[index].pinb) { continue; } + if (index != button_index) { continue; } + + bool powered_on = (power); +#ifdef USE_LIGHT + if (!Settings.flag4.rotary_uses_rules) { + powered_on = LightPower(); + } +#endif + if (Encoder[index].changed && powered_on) { + Encoder[index].changed = false; + return true; + } + return false; + } + return false; +} + +void ICACHE_RAM_ATTR RotaryIsrArgMiDesk(void *arg) { + tEncoder* encoder = static_cast(arg); + + + uint32_t state = encoder->state & 3; + if (digitalRead(encoder->pina)) { state |= 4; } + if (digitalRead(encoder->pinb)) { state |= 8; } + encoder->position += rotary_state_pos[state]; + encoder->state = (state >> 2); +} + +void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) { + tEncoder* encoder = static_cast(arg); + + + uint32_t time = millis(); + if ((encoder->debounce < time) || (encoder->debounce > time + ROTARY_DEBOUNCE)) { + int direction = (digitalRead(encoder->pinb)) ? -1 : 1; + if ((0 == encoder->direction) || (direction == encoder->direction)) { + encoder->position += direction; + encoder->direction = direction; + } + encoder->debounce = time + ROTARY_DEBOUNCE; + } +} + +void RotaryInit(void) { + Rotary.present = false; + Rotary.model = 1; +#ifdef ESP8266 + if (MI_DESK_LAMP == my_module_type) { + Rotary.model = 0; + } +#endif + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { + Encoder[index].pinb = -1; + if (PinUsed(GPIO_ROT1A, index) && PinUsed(GPIO_ROT1B, index)) { + Encoder[index].position = rotary_offset; + Encoder[index].pina = Pin(GPIO_ROT1A, index); + Encoder[index].pinb = Pin(GPIO_ROT1B, index); + pinMode(Encoder[index].pina, INPUT_PULLUP); + pinMode(Encoder[index].pinb, INPUT_PULLUP); + if (0 == Rotary.model) { + attachInterruptArg(Encoder[index].pina, RotaryIsrArgMiDesk, &Encoder[index], CHANGE); + attachInterruptArg(Encoder[index].pinb, RotaryIsrArgMiDesk, &Encoder[index], CHANGE); + } else { + attachInterruptArg(Encoder[index].pina, RotaryIsrArg, &Encoder[index], FALLING); + } + } + Rotary.present |= (Encoder[index].pinb > -1); + } +} + + + + + +void RotaryHandler(void) { + if (!Rotary.present) { return; } + + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { + if (-1 == Encoder[index].pinb) { continue; } + + if (Encoder[index].timeout) { + Encoder[index].timeout--; + if (!Encoder[index].timeout) { +#ifdef USE_LIGHT + if (!Settings.flag4.rotary_uses_rules) { + ResponseLightState(0); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_STATE)); + } +#endif + Encoder[index].direction = 0; + } + } + if (rotary_offset == Encoder[index].position) { continue; } + + Encoder[index].timeout = ROTARY_TIMEOUT; + + noInterrupts(); + int rotary_position = Encoder[index].position - rotary_offset; + Encoder[index].position = rotary_offset; + interrupts(); + + if (Settings.save_data && (save_data_counter < 2)) { + save_data_counter = 3; + } + + bool button_pressed = (Button.hold_timer[index]); + if (button_pressed) { Encoder[index].changed = true; } + + +#ifdef USE_LIGHT + if (!Settings.flag4.rotary_uses_rules) { + bool second_rotary = (Encoder[1].pinb > -1); + if (0 == index) { + if (button_pressed) { + if (second_rotary) { + LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); + } else { + if (!LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model])) { + LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); + } + } + } else { + uint32_t dimmer_index = second_rotary ? 1 : 0; + if (!Settings.flag4.rotary_poweron_dimlow || power) { + LightDimmerOffset(dimmer_index, rotary_position * rotary_dimmer_increment[Rotary.model]); + } else { + if (rotary_position > 0) { + LightDimmerOffset(dimmer_index, -LightGetDimmer(dimmer_index) + ROTARY_START_DIM); + } + } + } + } else { + if (button_pressed) { + LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model]); + } else { + LightDimmerOffset(2, rotary_position * rotary_dimmer_increment[Rotary.model]); + } + } + } else { +#endif + Encoder[index].abs_position[button_pressed] += rotary_position; + if (Encoder[index].abs_position[button_pressed] < 0) { + Encoder[index].abs_position[button_pressed] = 0; + } + if (Encoder[index].abs_position[button_pressed] > ROTARY_MAX_STEPS) { + Encoder[index].abs_position[button_pressed] = ROTARY_MAX_STEPS; + } + Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position[0], Encoder[index].abs_position[1]); + XdrvRulesProcess(); +#ifdef USE_LIGHT + } +#endif + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_rtc.ino" +# 25 "/workspace/Tasmota/tasmota/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; + uint32_t millis = 0; + uint32_t last_sync = 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; +} + +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 GetMinuteTime(uint32_t minutes) +{ + char tm[6]; + snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); + + return String(tm); +} + +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); +} +# 177 "/workspace/Tasmota/tasmota/support_rtc.ino" +String GetDateAndTime(uint8_t time_type) +{ + + uint32_t time = Rtc.local_time; + + switch (time_type) { + case DT_UTC: + time = Rtc.utc_time; + break; + + + + case DT_DST: + time = Rtc.daylight_saving_time; + break; + case DT_STD: + time = Rtc.standard_time; + break; + case DT_RESTART: + if (Rtc.restart_time == 0) { + return ""; + } + time = Rtc.restart_time; + break; + case DT_ENERGY: + time = Settings.energy_kWhtotal_time; + break; + case DT_BOOTCOUNT: + time = Settings.bootcount_reset_time; + break; + } + String dt = GetDT(time); + + if (DT_LOCAL_MILLIS == time_type) { + char ms[10]; + snprintf_P(ms, sizeof(ms), PSTR(".%03d"), RtcMillis()); + dt += ms; + time_type = DT_LOCAL; + } + + if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { + dt += GetTimeZone(); + } + return dt; +} + +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; +} + +uint32_t RtcMillis(void) { + return (millis() - Rtc.millis) % 1000; +} + +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; + + 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; + + Rtc.millis = millis(); + + if (!Rtc.user_time_entry) { + if (!global_state.network_down) { + uint8_t uptime_minute = (uptime / 60) % 60; + if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { + Rtc.ntp_sync_minute = 1; + } + uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP_getChipId() & 0xF) * 3) + 3) ; + if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || + (Rtc.ntp_sync_minute == uptime_minute))) || + ntp_force_sync ) ) { + Rtc.ntp_time = sntp_get_current_timestamp(); + if (Rtc.ntp_time > START_VALID_TIME) { + ntp_force_sync = false; + Rtc.utc_time = Rtc.ntp_time; + Rtc.last_sync = 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); + + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } else { + Rtc.ntp_sync_minute++; + } + } + } + if ((Rtc.utc_time > (2 * 60 * 60)) && (Rtc.last_sync < Rtc.utc_time - (2 * 60 * 60))) { + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Not synced")); + Rtc.last_sync = Rtc.utc_time; + } + } + + 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; + } + if (Settings.bootcount_reset_time < START_VALID_TIME) { + Settings.bootcount_reset_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; + sntp_init(); + } else { + sntp_stop(); + Rtc.user_time_entry = true; + Rtc.utc_time = epoch -1; + } +} + +void RtcInit(void) +{ + sntp_setservername(0, SettingsText(SET_NTPSERVER1)); + sntp_setservername(1, SettingsText(SET_NTPSERVER2)); + sntp_setservername(2, SettingsText(SET_NTPSERVER3)); + sntp_stop(); + sntp_set_timezone(0); + sntp_init(); + Rtc.utc_time = 0; + BreakTime(Rtc.utc_time, RtcTime); + TickerRtc.attach(1, RtcSecond); +} +# 1 "/workspace/Tasmota/tasmota/support_static_buffer.ino" +# 20 "/workspace/Tasmota/tasmota/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 add16BigEndian(const uint16_t data) { + if (_buf->len < _buf->size - 1) { + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data; + } + 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 add32BigEndian(const uint32_t data) { + if (_buf->len < _buf->size - 3) { + _buf->buf[_buf->len++] = data >> 24; + _buf->buf[_buf->len++] = data >> 16; + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data; + } + return _buf->len; + } + size_t add64(const uint64_t data) { + if (_buf->len < _buf->size - 7) { + _buf->buf[_buf->len++] = data; + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data >> 16; + _buf->buf[_buf->len++] = data >> 24; + _buf->buf[_buf->len++] = data >> 32; + _buf->buf[_buf->len++] = data >> 40; + _buf->buf[_buf->len++] = data >> 48; + _buf->buf[_buf->len++] = data >> 56; + } + 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 uint8_t *buf2, size_t len2) { + if ((buf2) && (len() + len2 <= size())) { + for (uint32_t i = 0; i < len2; i++) { + _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); + } + } + return _buf->len; + } + + size_t addBuffer(const char *buf2, size_t len2) { + if ((buf2) && (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; + } + uint16_t get16BigEndian(const size_t offset) const { + if (offset < len() - 1) { + return _buf->buf[offset+1] | (_buf->buf[offset] << 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; + } + int32_t get32IBigEndian(const size_t offset) const { + if (offset < len() - 3) { + return _buf->buf[offset+3] | (_buf->buf[offset+2] << 8) | + (_buf->buf[offset+1] << 16) | (_buf->buf[offset] << 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; + } + + + inline size_t strlen(const size_t offset) const { + return strnlen((const char*) &_buf->buf[offset], len() - offset); + } + + size_t strlen_s(const size_t offset) const { + size_t slen = this->strlen(offset); + if (slen == len() - offset) { + return 0; + } else { + return slen; + } + } + + 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; + + +bool equalsSBuffer(const class SBuffer * buf1, const class SBuffer * buf2) { + if (buf1 == buf2) { return true; } + if (!buf1 && (buf2->len() == 0)) { return true; } + if (!buf2 && (buf1->len() == 0)) { return true; } + if (!buf1 || !buf2) { return false; } + + if (buf1->len() != buf2->len()) { return false; } + size_t len = buf1->len(); + for (uint32_t i=0; iget8(i) != buf2->get8(i)) { return false; } + } + return true; +} +# 1 "/workspace/Tasmota/tasmota/support_statistics.ino" +# 20 "/workspace/Tasmota/tasmota/support_statistics.ino" +#define USE_STATS_CODE + +#ifdef USE_STATS_CODE + + + + +String GetStatistics(void) +{ + char data[40]; + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); + return String(data); +} + +#else + +String GetStatistics(void) +{ + return String(""); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_switch.ino" +# 20 "/workspace/Tasmota/tasmota/support_switch.ino" +#define SWITCH_V3 +#ifdef SWITCH_V3 + + + + + + +const uint8_t SWITCH_PROBE_INTERVAL = 10; +const uint8_t SWITCH_FAST_PROBE_INTERVAL =2; +const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PROBE_INTERVAL; + + +#define SM_TIMER_MASK 0x3F +#define SM_NO_TIMER_MASK 0xFF +#define SM_FIRST_PRESS 0x40 +#define SM_SECOND_PRESS 0x80 + +#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 first_change = 0; + uint8_t present = 0; +} Switch; + + + +void SwitchPullupFlag(uint16 switch_bit) +{ + bitSet(Switch.no_pullup_mask, switch_bit); +} + +void SwitchSetVirtual(uint32_t index, uint8_t state) +{ + Switch.virtual_state[index] = state; +} + +uint8_t SwitchGetVirtual(uint32_t index) +{ + return Switch.virtual_state[index]; +} + +uint8_t SwitchLastState(uint32_t index) +{ + return Switch.last_state[index]; +} + +bool SwitchState(uint32_t index) +{ + uint32_t switchmode = Settings.switchmode[index]; + return ((FOLLOW_INV == switchmode) || + (PUSHBUTTON_INV == switchmode) || + (PUSHBUTTONHOLD_INV == switchmode) || + (FOLLOWMULTI_INV == switchmode) || + (PUSHHOLDMULTI_INV == switchmode) || + (PUSHON_INV == switchmode) + ) ^ Switch.last_state[index]; +} + + + +void SwitchProbe(void) +{ + if (uptime < 4) { return; } + + uint8_t state_filter; + uint8_t debounce_flags = Settings.switch_debounce % 10; + uint8_t force_high = debounce_flags &1; + uint8_t force_low = debounce_flags &2; + uint8_t ac_detect = debounce_flags == 9; + uint8_t switch_probe_interval; + uint8_t first_change = Switch.first_change; + + if (ac_detect) { + switch_probe_interval = SWITCH_FAST_PROBE_INTERVAL; + if (Settings.switch_debounce < 2 * AC_PERIOD * SWITCH_FAST_PROBE_INTERVAL + 9) { + state_filter = 2 * AC_PERIOD; + } else if (Settings.switch_debounce > (0x7f - 2 * AC_PERIOD) * SWITCH_FAST_PROBE_INTERVAL) { + state_filter = 0x7f; + } else { + state_filter = (Settings.switch_debounce - 9) / SWITCH_FAST_PROBE_INTERVAL; + } + } else { + switch_probe_interval = SWITCH_PROBE_INTERVAL; + state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; + } + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + if (PinUsed(GPIO_SWT1, i)) { + + if (1 == digitalRead(Pin(GPIO_SWT1, i))) { + + if (ac_detect) { + Switch.state[i] |= 0x80; + if (Switch.state[i] > 0x80) { + Switch.state[i]--; + if (0x80 == Switch.state[i]) { + Switch.virtual_state[i] = 0; + Switch.first_change = false; + } + } + } else { + + 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 (ac_detect) { + + + + + + + + if (Switch.state[i] & 0x80) { + Switch.state[i] &= 0x7f; + if (Switch.state[i] < state_filter - 2 * AC_PERIOD) { + Switch.state[i] += 2 * AC_PERIOD; + } else { + Switch.state[i] = state_filter; + Switch.virtual_state[i] = 1; + if (first_change) { + Switch.last_state[i] = 1; + Switch.first_change = false; + } + } + } else { + if (Switch.state[i] > 0x00) { + Switch.state[i]--; + if (0x00 == Switch.state[i]) { + Switch.virtual_state[i] = 0; + Switch.first_change = false; + } + } + } + } 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) +{ + uint8_t ac_detect = Settings.switch_debounce % 10 == 9; + + Switch.present = 0; + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + Switch.last_state[i] = 1; + if (PinUsed(GPIO_SWT1, i)) { + Switch.present++; +#ifdef ESP8266 + pinMode(Pin(GPIO_SWT1, i), bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_SWT1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); +#else + pinMode(Pin(GPIO_SWT1, i), bitRead(Switch.no_pullup_mask, i) ? INPUT : INPUT_PULLUP); +#endif + if (ac_detect) { + Switch.state[i] = 0x80 + 2 * AC_PERIOD; + Switch.last_state[i] = 0; + } else { + Switch.last_state[i] = digitalRead(Pin(GPIO_SWT1, i)); + } + } + Switch.virtual_state[i] = Switch.last_state[i]; + } + if (Switch.present) { + if (ac_detect) { + TickerSwitch.attach_ms(SWITCH_FAST_PROBE_INTERVAL, SwitchProbe); + Switch.first_change = true; + } else { + TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); + } + } +} + + + + + +void SwitchHandler(uint8_t mode) +{ + if (uptime < 4) { return; } + + uint16_t loops_per_second = 1000 / Settings.switch_debounce; + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + if (PinUsed(GPIO_SWT1, i) || (mode)) { + uint8_t button = Switch.virtual_state[i]; + uint8_t switchflag = POWER_TOGGLE +1; + + if (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) { + Switch.hold_timer[i]--; + if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings.param[P_HOLD_TIME] / 25) { + if ((Settings.switchmode[i] == PUSHHOLDMULTI) & (NOT_PRESSED == Switch.last_state[i])) { + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } + if ((Settings.switchmode[i] == PUSHHOLDMULTI_INV) & (PRESSED == Switch.last_state[i])) { + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } + } + if (0 == (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK))) { + switch (Settings.switchmode[i]) { + case TOGGLEMULTI: + switchflag = POWER_TOGGLE; + break; + case FOLLOWMULTI: + switchflag = button &1; + break; + case FOLLOWMULTI_INV: + switchflag = ~button &1; + break; + case PUSHHOLDMULTI: + if (NOT_PRESSED == button) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } else { + Switch.hold_timer[i]= 0; + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); + } + break; + case PUSHHOLDMULTI_INV: + if (PRESSED == button) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } else { + Switch.hold_timer[i]= 0; + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); + } + break; + default: + SendKey(KEY_SWITCH, i +1, POWER_HOLD); + break; + } + } + } + + if (button != Switch.last_state[i]) { + switch (Settings.switchmode[i]) { + case TOGGLE: + case PUSHBUTTON_TOGGLE: + switchflag = POWER_TOGGLE; + break; + case FOLLOW: + switchflag = button &1; + break; + case FOLLOW_INV: + switchflag = ~button &1; + break; + case PUSHBUTTON: + if (PRESSED == button) { + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTON_INV: + if (NOT_PRESSED == button) { + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTONHOLD: + if (PRESSED == button) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((NOT_PRESSED == button) && (Switch.hold_timer[i])) { + Switch.hold_timer[i] = 0; + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTONHOLD_INV: + if (NOT_PRESSED == button) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((PRESSED == button) && (Switch.hold_timer[i])) { + Switch.hold_timer[i] = 0; + switchflag = POWER_TOGGLE; + } + break; + case TOGGLEMULTI: + case FOLLOWMULTI: + case FOLLOWMULTI_INV: + if (Switch.hold_timer[i]) { + Switch.hold_timer[i] = 0; + SendKey(KEY_SWITCH, i +1, POWER_HOLD); + } else { + Switch.hold_timer[i] = loops_per_second / 2; + } + break; + case PUSHHOLDMULTI: + if (NOT_PRESSED == button) { + if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { + Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; + SendKey(KEY_SWITCH, i +1, POWER_INV); + } + } else { + if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) { + if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { + Switch.hold_timer[i]= SM_FIRST_PRESS; + switchflag = POWER_TOGGLE; + } + else{ + SendKey(KEY_SWITCH, i +1, POWER_100); + Switch.hold_timer[i]= 0; + } + } else { + Switch.hold_timer[i]= 0; + SendKey(KEY_SWITCH, i +1, POWER_RELEASE); + } + } + Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; + break; + case PUSHHOLDMULTI_INV: + if (PRESSED == button) { + if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { + Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; + SendKey(KEY_SWITCH, i +1, POWER_INV); + } + } else { + if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) { + if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { + Switch.hold_timer[i]= SM_FIRST_PRESS; + switchflag = POWER_TOGGLE; + } + else{ + SendKey(KEY_SWITCH, i +1, POWER_100); + Switch.hold_timer[i]= 0; + } + } else { + Switch.hold_timer[i]= 0; + SendKey(KEY_SWITCH, i +1, POWER_RELEASE); + } + } + Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; + break; + case PUSHON: + if (PRESSED == button) { + switchflag = POWER_ON; + } + break; + case PUSHON_INV: + if (NOT_PRESSED == button) { + switchflag = POWER_ON; + } + break; + case PUSH_IGNORE: + MqttPublishSensor(); + break; + } + Switch.last_state[i] = button; + } + if (switchflag <= POWER_TOGGLE) { + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); + } + } + } + } +} + +void SwitchLoop(void) +{ + if (Switch.present) { + if (TimeReached(Switch.debounce)) { + SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); + SwitchHandler(0); + } + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_tasmota.ino" +# 20 "/workspace/Tasmota/tasmota/support_tasmota.ino" +const char kSleepMode[] PROGMEM = "Dynamic|Normal"; +const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; + +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 { + String mac_address = WiFi.macAddress(); + mac_address.replace(":", ""); + if (digits > 12) { digits = 12; } + String mac_part = mac_address.substring(12 - digits); + snprintf_P(output, size, PSTR("%s%s"), output, mac_part.c_str()); + } + } 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(SettingsText(SET_OTAURL), "%04d") != nullptr) { + snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP_getChipId() & 0x1fff); + } + else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { + snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP_getChipId()); + } + else { + strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); + } + + return otaurl; +} + +char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) +{ +# 91 "/workspace/Tasmota/tasmota/support_tasmota.ino" + char romram[CMDSZ]; + String fulltopic; + + snprintf_P(romram, sizeof(romram), subtopic); + if (fallback_topic_flag || (prefix > 3)) { + bool fallback = (prefix < 8); + prefix &= 3; + char stemp[11]; + fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); + fulltopic += F("/"); + if (fallback) { + fulltopic += mqtt_client; + fulltopic += F("_fb"); + } else { + fulltopic += topic; + } + } else { + fulltopic = SettingsText(SET_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 < MAX_MQTT_PREFIXES; i++) { + if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { + char temp[TOPSZ]; + SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); + } + } + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + 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* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic) +{ + + + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(itopic), subtopic); +} + +char* GetFallbackTopic_P(char *stopic, const char* subtopic) +{ + return GetTopic_P(stopic, CMND +4, nullptr, subtopic); +} + +char* GetStateText(uint32_t state) +{ + if (state >= MAX_STATE_TEXT) { + state = 1; + } + return SettingsText(SET_STATE_TXT1 + 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); + DigitalWrite(GPIO_REL1, port, bitRead(rel_inverted, port) ? !state : state); + } +} + +void SetDevicePower(power_t rpower, uint32_t source) +{ + ShowSource(source); + last_source = 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); + XsnsCall(FUNC_SET_POWER); + + XdrvMailbox.index = rpower; + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_DEVICE_POWER)) { + + } +#ifdef ESP8266 + 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); + } +#endif + else + { + for (uint32_t i = 0; i < devices_present; i++) { + power_t state = rpower &1; + if (i < MAX_RELAYS) { + DigitalWrite(GPIO_REL1, i, bitRead(rel_inverted, i) ? !state : state); + } + rpower >>= 1; + } + } +} + +void RestorePower(bool publish_power, uint32_t source) +{ + if (power != last_power) { + power = last_power; + SetDevicePower(power, source); + if (publish_power) { + MqttPublishAllPowerState(); + } + } +} + +void SetAllPower(uint32_t state, uint32_t source) +{ +# 263 "/workspace/Tasmota/tasmota/support_tasmota.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 SetPowerOnState(void) +{ +#ifdef ESP8266 + if (MOTOR == my_module_type) { + Settings.poweronstate = POWER_ALL_ON; + } +#endif + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { + SetDevicePower(1, SRC_RESTART); + } else { + if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == 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) && PinUsed(GPIO_REL1, i)) { + bitWrite(power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(rel_inverted, i)); + } + } + if (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate)) { + SetPulseTimer(i % MAX_PULSETIMERS, Settings.pulse_timer[i % MAX_PULSETIMERS]); + } + } + blink_powersave = power; +} + +void UpdateLedPowerAll() +{ + for (uint32_t i = 0; i < leds_present; i++) { + SetLedPowerIdx(i, bitRead(led_power, i)); + } +} + +void SetLedPowerIdx(uint32_t led, uint32_t state) +{ + if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { + if (PinUsed(GPIO_LED1, 1)) { + led = 1; + } + } + if (PinUsed(GPIO_LED1, led)) { + uint32_t mask = 1 << led; + if (state) { + state = 1; + led_power |= mask; + } else { + led_power &= (0xFF ^ mask); + } + uint16_t pwm = 0; + if (bitRead(Settings.ledpwm_mask, led)) { +#ifdef USE_LIGHT + pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); +#else + pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); +#endif + analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); + } else { + DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + } + } +#ifdef USE_BUZZER + if (led == 0) { + BuzzerSetStateToLed(state); + } +#endif +} + +void SetLedPower(uint32_t state) +{ + if (!PinUsed(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) { + SetLedPowerIdx(0, state); + } + else if (led_pin < 99) { + if (state) { state = 1; } + digitalWrite(led_pin, (led_inv) ? !state : state); + } +#ifdef USE_BUZZER + BuzzerSetStateToLed(state); +#endif +} + +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) +{ +# 452 "/workspace/Tasmota/tasmota/support_tasmota.ino" + char stopic[TOPSZ]; + char scommand[CMDSZ]; + char key_topic[TOPSZ]; + bool result = false; + uint32_t device_save = device; + + char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_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(SettingsText(SET_MQTT_GRP_TOPIC), 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)))) { +#endif + MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain + : Settings.flag.mqtt_button_retain) && + (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); +#ifdef USE_DOMOTICZ + } +#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_PWM_DIMMER + if (PWM_DIMMER == my_module_type && !result) { +#endif + int32_t payload_save = XdrvMailbox.payload; + XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device; + XdrvCall(FUNC_ANY_KEY); + XdrvMailbox.payload = payload_save; +#ifdef USE_PWM_DIMMER + result = true; + } +#endif + return result; +} + +void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) +{ +# 520 "/workspace/Tasmota/tasmota/support_tasmota.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; + + SetPulseTimer((device -1) % MAX_PULSETIMERS, 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; + } +#ifdef USE_DEVICE_GROUPS + if (SRC_REMOTE != source && SRC_RETRY != source) { + if (Settings.flag4.multiple_device_groups) + SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (power >> (device - 1)) & 1 | 0x01000000); + else + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); + } +#endif + 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(); + } + + + SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1) % MAX_PULSETIMERS] : 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 (PinUsed(GPIO_PWM1, i)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); + first = false; + } + } + ResponseJsonEnd(); +} + +void MqttShowState(void) +{ + char stemp1[TOPSZ]; + + ResponseAppendTime(); + ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); + +#ifdef ESP8266 +#ifdef USE_ADC_VCC + dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); + ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); +#endif +#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), + ssleep, loop_load_avg, MqttConnectCount()); + + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_LIGHT + if ((LightDevice()) && (i >= LightDevice())) { + if (i == LightDevice()) { ResponseLightState(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(); + } + + if (!global_state.wifi_down) { + int32_t rssi = WiFi.RSSI(); + 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_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}"), + Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(), + WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); + } + + ResponseJsonEnd(); +} + +void MqttPublishTeleState(void) +{ + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); +#if defined(USE_RULES) || defined(USE_SCRIPT) + RulesTeleperiod(); +#endif +} + +void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperature, float f_humidity) +{ + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{"), types); + ResponseAppendTHD(f_temperature, f_humidity); + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (pass_on) { + DomoticzTempHumPressureSensor(f_temperature, f_humidity); + } +#endif +#ifdef USE_KNX + if (pass_on) { + KnxSensor(KNX_TEMPERATURE, f_temperature); + KnxSensor(KNX_HUMIDITY, f_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_THD(types, f_temperature, f_humidity); +#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 (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) { +#else + if (PinUsed(GPIO_SWT1, i)) { +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); + } + } + XsnsCall(FUNC_JSON_APPEND); + XdrvCall(FUNC_JSON_APPEND); + + 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()); + } + if ((strstr_P(mqtt_data, PSTR(D_JSON_SPEED)) != nullptr) && Settings.flag2.speed_conversion) { + ResponseAppend_P(PSTR(",\"" D_JSON_SPEED_UNIT "\":\"%s\""), SpeedUnit().c_str()); + } + ResponseJsonEnd(); + + if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } + return json_data_available; +} + +void MqttPublishSensor(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishTeleSensor(); + } +} +# 788 "/workspace/Tasmota/tasmota/support_tasmota.ino" +void PerformEverySecond(void) +{ + uptime++; + + if (POWER_CYCLE_TIME == uptime) { + UpdateQuickPowerCycle(false); + } + + if (BOOT_LOOP_TIME == uptime) { + RtcRebootReset(); + +#ifdef USE_DEEPSLEEP + if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { +#endif + Settings.bootcount++; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); +#ifdef USE_DEEPSLEEP + } +#endif + } + + if (mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked_reset--; + if (!mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked = 0; + } + } + + 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) { + if (tele_period >= 9999) { + if (!global_state.network_down) { + tele_period = 0; + } + } else { + tele_period++; + 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 + } + + XsnsCall(FUNC_AFTER_TELEPERIOD); + XdrvCall(FUNC_AFTER_TELEPERIOD); + } + } + } + + + wifiKeepAlive(); + +#ifdef ESP32 + if (11 == uptime) { + ESP_getSketchSize(); + } +#endif +} + + + + + +void Every100mSeconds(void) +{ + + power_t power_now; + + if (prepped_loglevel) { + AddLog(prepped_loglevel); + } + + 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; + for (uint32_t j = 0; j < devices_present; j = j +MAX_PULSETIMERS) { + ExecuteCommandPower(i + j +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); + } + } + } +} + + + + + +void Every250mSeconds(void) +{ + + + uint32_t blinkinterval = 1; + + state_250mS++; + state_250mS &= 0x3; + + global_state.network_down = (global_state.wifi_down && global_state.eth_down) ? 1 : 0; + + if (!Settings.flag.global_state) { + if (global_state.data &0x03) { + if (global_state.mqtt_down) { blinkinterval = 7; } + if (global_state.network_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 && (PinUsed(GPIO_LEDLNK) || !(blinks || restart_flag || ota_state_flag)) ) { + bool tstate = power & Settings.ledmask; +#ifdef ESP8266 + 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; + } +#endif + SetLedPower(tstate); + } + + + + + + switch (state_250mS) { + case 0: + if (ota_state_flag && BACKLOG_EMPTY) { + ota_state_flag--; + if (2 == ota_state_flag) { + RtcSettings.ota_loader = 0; + ota_retry_counter = OTA_ATTEMPTS; + ESPhttpUpdate.rebootOnUpdate(false); + SettingsSave(1); + } + if (ota_state_flag <= 0) { +#ifdef USE_COUNTER + CounterInterruptDisable(true); +#endif +#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) { +# 1015 "/workspace/Tasmota/tasmota/support_tasmota.ino" + char *bch = strrchr(mqtt_data, '/'); + if (bch == nullptr) { bch = mqtt_data; } + char *ech = strchr(bch, '.'); + if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } + + + + char ota_url_type[strlen(ech) +1]; + strncpy(ota_url_type, ech, sizeof(ota_url_type)); + + char *pch = strrchr(bch, '-'); + if (pch == nullptr) { pch = ech; } + *pch = '\0'; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); + } +#endif + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); + WiFiClient OTAclient; + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); + 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; + Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); + if (ota_result) { + + if (!VersionCompatible()) { + ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); + } else { + ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + restart_flag = 2; + } + } else { + ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + } + ResponseAppend_P(PSTR("\"}")); + + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); +#ifdef USE_COUNTER + CounterInterruptDisable(false); +#endif + } + } + 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 < devices_present; i++) { + if ((Settings.pulse_timer[i % MAX_PULSETIMERS] > 0) && (Settings.pulse_timer[i % MAX_PULSETIMERS] < 30)) { + mask &= ~(1 << i); + } + } + if (!((Settings.power &mask) == (power &mask))) { + Settings.power = power; + } + } else { + Settings.power = 0; + } + if (!restart_flag) { 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_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; + strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); + char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; + strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); + char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; + strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); + char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; + strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); + + char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; + strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); + char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; + strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); + char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; + strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); + char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; + strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); + uint16_t mqtt_port = Settings.mqtt_port; + + + + + if ((215 == restart_flag) || (216 == restart_flag)) { + SettingsErase(0); + } + SettingsDefault(); + + SettingsUpdateText(SET_STASSID1, storage_ssid1); + SettingsUpdateText(SET_STASSID2, storage_ssid2); + SettingsUpdateText(SET_STAPWD1, storage_pass1); + SettingsUpdateText(SET_STAPWD2, storage_pass2); + if (216 == restart_flag) { + + SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); + SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); + SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); + SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); + Settings.mqtt_port = mqtt_port; + } + 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_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (restart_halt) ? "Halted" : D_RESTARTING); + EspRestart(); + } + } + break; + case 2: + if (Settings.flag4.network_wifi) { + WifiCheck(wifi_state_flag); + wifi_state_flag = WIFI_RESTART; + } + break; + case 3: + if (!global_state.network_down) { +#ifdef FIRMWARE_MINIMAL + if (1 == RtcSettings.ota_loader) { + RtcSettings.ota_loader = 0; + ota_state_flag = 3; + } +#endif + +#ifdef USE_DISCOVERY + StartMdns(); +#endif + +#ifdef USE_WEBSERVER + if (Settings.webserver) { + +#ifdef ESP8266 + StartWebserver(Settings.webserver, WiFi.localIP()); +#else +#ifdef USE_ETHERNET + StartWebserver(Settings.webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP()); +#else + StartWebserver(Settings.webserver, WiFi.localIP()); +#endif +#endif + +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE + MdnsAddServiceHttp(); +#endif +#endif + } else { + StopWebserver(); + } +#ifdef USE_EMULATION + if (Settings.flag2.emulation) { UdpConnect(); } +#endif +#endif + +#ifdef USE_DEVICE_GROUPS + DeviceGroupsStart(); +#endif + +#ifdef USE_KNX + if (!knx_started && Settings.flag.knx_enabled) { + KNXStart(); + knx_started = true; + } +#endif + + MqttCheck(); + } else { +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + +#ifdef USE_DEVICE_GROUPS + DeviceGroupsStop(); +#endif + +#ifdef USE_KNX + knx_started = false; +#endif + } + 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(NetworkHostname()); + if (strlen(SettingsText(SET_WEBPWD))) { + ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); + } + + 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")); +} + +void ArduinoOtaLoop(void) +{ + MDNS.update(); + ArduinoOTA.handle(); + + while (arduino_ota_triggered) { ArduinoOTA.handle(); } +} +#endif + + + +void SerialInput(void) +{ + while (Serial.available()) { + + delay(0); + serial_in_byte = Serial.read(); + + if (0 == serial_in_byte_counter) { + serial_buffer_overrun = false; + } + else if ((serial_in_byte_counter == INPUT_BUFFER_SIZE) +#ifdef ESP8266 + || Serial.hasOverrun() +#endif + ) { + serial_buffer_overrun = true; + } + +#ifdef ESP8266 + + + + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + serial_in_byte = ButtonSerial(serial_in_byte); + } +#endif + + + 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_buffer_overrun = true; + } + } + } else { + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { + bool in_byte_is_delimiter = + (((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || + ((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && + !Settings.flag.mqtt_serial_raw; + + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && + !in_byte_is_delimiter) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + + if ((serial_in_byte_counter >= INPUT_BUFFER_SIZE -1) || + in_byte_is_delimiter) { + serial_polling_window = 0; + break; + } + + serial_polling_window = millis(); + } + } + +#ifdef USE_SONOFF_SC + + + + 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 +#endif + + + 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; + if (serial_buffer_overrun) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "Serial buffer overrun")); + } else { + 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; + bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); + + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":")); + if (assume_json) { + ResponseAppend_P(serial_in_buffer); + } else { + ResponseAppend_P(PSTR("\"")); + if (Settings.flag.mqtt_serial_raw) { + char hex_char[(serial_in_byte_counter * 2) + 2]; + ResponseAppend_P(ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char))); + } else { + ResponseAppend_P(EscapeJSONString(serial_in_buffer).c_str()); + } + ResponseAppend_P(PSTR("\"")); + } + ResponseJsonEnd(); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); + serial_in_byte_counter = 0; + } +} + + + +void ResetPwm(void) +{ + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (PinUsed(GPIO_PWM1, i)) { + analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); + + } + } +} + + + +void GpioInit(void) +{ + if (!ValidModule(Settings.module)) { + uint32_t module = MODULE; + if (!ValidModule(MODULE)) { +#ifdef ESP8266 + module = SONOFF_BASIC; +#endif +#ifdef ESP32 + module = WEMOS; +#endif + } + + Settings.module = module; + Settings.last_module = module; + } + SetModuleType(); + + if (Settings.module != Settings.last_module) { + Settings.baudrate = APP_BAUDRATE / 300; + Settings.serial_config = TS_SERIAL_8N1; + SetSerialBegin(); + } + + + +#ifdef ESP8266 + ConvertGpios(); +#endif + + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) { + Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); + } + } + + myio def_gp; + ModuleGpios(&def_gp); + for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + if ((Settings.my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.my_gp.io[i] < AGPIO(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] < AGPIO(GPIO_USER))) { + my_module.io[i] = def_gp.io[i]; + } + } + + for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { + uint32_t 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 >= AGPIO(GPIO_SWT1_NP)) && (mpin < (AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES))) { + SwitchPullupFlag(mpin - AGPIO(GPIO_SWT1_NP)); + mpin -= (AGPIO(GPIO_SWT1_NP) - AGPIO(GPIO_SWT1)); + } + else if ((mpin >= AGPIO(GPIO_KEY1_NP)) && (mpin < (AGPIO(GPIO_KEY1_NP) + MAX_KEYS))) { + ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_NP)); + mpin -= (AGPIO(GPIO_KEY1_NP) - AGPIO(GPIO_KEY1)); + } + else if ((mpin >= AGPIO(GPIO_KEY1_INV)) && (mpin < (AGPIO(GPIO_KEY1_INV) + MAX_KEYS))) { + ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV)); + mpin -= (AGPIO(GPIO_KEY1_INV) - AGPIO(GPIO_KEY1)); + } + else if ((mpin >= AGPIO(GPIO_KEY1_INV_NP)) && (mpin < (AGPIO(GPIO_KEY1_INV_NP) + MAX_KEYS))) { + ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); + ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); + mpin -= (AGPIO(GPIO_KEY1_INV_NP) - AGPIO(GPIO_KEY1)); + } +#ifdef ESP32 + else if ((mpin >= AGPIO(GPIO_KEY1_TC)) && (mpin < (AGPIO(GPIO_KEY1_TC) + MAX_KEYS))) { + ButtonTouchFlag(mpin - AGPIO(GPIO_KEY1_TC)); + mpin -= (AGPIO(GPIO_KEY1_TC) - AGPIO(GPIO_KEY1)); + } +#endif + else if ((mpin >= AGPIO(GPIO_REL1_INV)) && (mpin < (AGPIO(GPIO_REL1_INV) + MAX_RELAYS))) { + bitSet(rel_inverted, mpin - AGPIO(GPIO_REL1_INV)); + mpin -= (AGPIO(GPIO_REL1_INV) - AGPIO(GPIO_REL1)); + } + else if ((mpin >= AGPIO(GPIO_LED1_INV)) && (mpin < (AGPIO(GPIO_LED1_INV) + MAX_LEDS))) { + bitSet(led_inverted, mpin - AGPIO(GPIO_LED1_INV)); + mpin -= (AGPIO(GPIO_LED1_INV) - AGPIO(GPIO_LED1)); + } + else if (mpin == AGPIO(GPIO_LEDLNK_INV)) { + ledlnk_inverted = 1; + mpin -= (AGPIO(GPIO_LEDLNK_INV) - AGPIO(GPIO_LEDLNK)); + } + else if ((mpin >= AGPIO(GPIO_PWM1_INV)) && (mpin < (AGPIO(GPIO_PWM1_INV) + MAX_PWMS))) { + bitSet(pwm_inverted, mpin - AGPIO(GPIO_PWM1_INV)); + mpin -= (AGPIO(GPIO_PWM1_INV) - AGPIO(GPIO_PWM1)); + } + else if (XdrvCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + } + else if (XsnsCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + }; + } + if (mpin) { SetPin(i, mpin); } + } + + + + analogWriteRange(Settings.pwm_range); + analogWriteFreq(Settings.pwm_frequency); + +#ifdef ESP8266 + if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); } + +#ifdef USE_SPI + spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12))); + if (spi_flg) { + my_module.io[12] = GPIO_SPI_MISO; + SetPin(12, GPIO_SPI_MISO); + my_module.io[13] = GPIO_SPI_MOSI; + SetPin(13, GPIO_SPI_MOSI); + my_module.io[14] = GPIO_SPI_CLK; + SetPin(14, GPIO_SPI_CLK); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK)")); + } +#endif +#else +#ifdef USE_SPI + if (PinUsed(GPIO_SPI_CS) || PinUsed(GPIO_SPI_DC)) { + if ((15 == Pin(GPIO_SPI_CS)) && (!GetPin(12) && !GetPin(13) && !GetPin(14))) { + my_module.io[12] = AGPIO(GPIO_SPI_MISO); + SetPin(12, AGPIO(GPIO_SPI_MISO)); + my_module.io[13] = AGPIO(GPIO_SPI_MOSI); + SetPin(13, AGPIO(GPIO_SPI_MOSI)); + my_module.io[14] = AGPIO(GPIO_SPI_CLK); + SetPin(14, AGPIO(GPIO_SPI_CLK)); + } + else if ((5 == Pin(GPIO_SPI_CS)) && (!GetPin(19) && !GetPin(23) && !GetPin(18))) { + my_module.io[19] = AGPIO(GPIO_SPI_MISO); + SetPin(19, AGPIO(GPIO_SPI_MISO)); + my_module.io[23] = AGPIO(GPIO_SPI_MOSI); + SetPin(23, AGPIO(GPIO_SPI_MOSI)); + my_module.io[18] = AGPIO(GPIO_SPI_CLK); + SetPin(18, AGPIO(GPIO_SPI_CLK)); + } + else if ((12 == Pin(GPIO_SPI_MISO)) || (13 == Pin(GPIO_SPI_MOSI)) || (14 == Pin(GPIO_SPI_CLK))) { + my_module.io[12] = AGPIO(GPIO_SPI_MISO); + SetPin(12, AGPIO(GPIO_SPI_MISO)); + my_module.io[13] = AGPIO(GPIO_SPI_MOSI); + SetPin(13, AGPIO(GPIO_SPI_MOSI)); + my_module.io[14] = AGPIO(GPIO_SPI_CLK); + SetPin(14, AGPIO(GPIO_SPI_CLK)); + } + else if ((19 == Pin(GPIO_SPI_MISO)) || (23 == Pin(GPIO_SPI_MOSI)) || (18 == Pin(GPIO_SPI_CLK))) { + my_module.io[19] = AGPIO(GPIO_SPI_MISO); + SetPin(19, AGPIO(GPIO_SPI_MISO)); + my_module.io[23] = AGPIO(GPIO_SPI_MOSI); + SetPin(23, AGPIO(GPIO_SPI_MOSI)); + my_module.io[18] = AGPIO(GPIO_SPI_CLK); + SetPin(18, AGPIO(GPIO_SPI_CLK)); + } + spi_flg = (PinUsed(GPIO_SPI_CLK) && (PinUsed(GPIO_SPI_MOSI) || PinUsed(GPIO_SPI_MISO))); + if (spi_flg) { + if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MISO), GPIO%02d(MOSI) and GPIO%02d(CLK)"), + Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); + } + else if (PinUsed(GPIO_SPI_MOSI)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MOSI) and GPIO%02d(CLK)"), + Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); + } + else if (PinUsed(GPIO_SPI_MISO)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MISO) and GPIO%02d(CLK)"), + Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK)); + } + } + } +#endif +#endif + soft_spi_flg = (PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO))); + + for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { + uint32_t mpin = ValidPin(i, my_module.io[i]); + + if (AGPIO(GPIO_OUTPUT_HI) == mpin) { + pinMode(i, OUTPUT); + digitalWrite(i, 1); + } + else if (AGPIO(GPIO_OUTPUT_LO) == mpin) { + pinMode(i, OUTPUT); + digitalWrite(i, 0); + } + + + else if (((i < 6) || (i > 11)) && (GPIO_NONE == mpin)) { + if (!((1 == i) || (3 == i))) { + pinMode(i, INPUT); + } + } + } + +#ifdef USE_I2C + i2c_flg = (PinUsed(GPIO_I2C_SCL) && PinUsed(GPIO_I2C_SDA)); + if (i2c_flg) { + Wire.begin(Pin(GPIO_I2C_SDA), Pin(GPIO_I2C_SCL)); + } +#endif + + devices_present = 0; + light_type = LT_BASIC; + + XsnsCall(FUNC_MODULE_INIT); + + if (XdrvCall(FUNC_MODULE_INIT)) { + + } +#ifdef ESP8266 + else if (YTF_IR_BRIDGE == my_module_type) { + ClaimSerial(); + + } + else if (SONOFF_DUAL == my_module_type) { + devices_present = 2; + SetSerial(19200, TS_SERIAL_8N1); + } + else if (CH4 == my_module_type) { + devices_present = 4; + SetSerial(19200, TS_SERIAL_8N1); + } +#ifdef USE_SONOFF_SC + else if (SONOFF_SC == my_module_type) { + SetSerial(19200, TS_SERIAL_8N1); + } +#endif +#endif + + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (PinUsed(GPIO_PWM1, i)) { +#ifdef ESP8266 + pinMode(Pin(GPIO_PWM1, i), OUTPUT); +#else + analogAttach(Pin(GPIO_PWM1, i), i); +#endif + if (light_type) { + + analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); + } else { + pwm_present = true; + analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + } + } + } + + for (uint32_t i = 0; i < MAX_RELAYS; i++) { + if (PinUsed(GPIO_REL1, i)) { + pinMode(Pin(GPIO_REL1, i), OUTPUT); + devices_present++; +#ifdef ESP8266 + if (EXS_RELAY == my_module_type) { + digitalWrite(Pin(GPIO_REL1, i), bitRead(rel_inverted, i) ? 1 : 0); + if (i &1) { devices_present--; } + } +#endif + } + } + + for (uint32_t i = 0; i < MAX_LEDS; i++) { + if (PinUsed(GPIO_LED1, i)) { +#ifdef USE_ARILUX_RF + if ((3 == i) && (leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) { + SetPin(Pin(GPIO_LED1, i), AGPIO(GPIO_ARIRFSEL)); + } 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 (PinUsed(GPIO_LEDLNK)) { + pinMode(Pin(GPIO_LEDLNK), OUTPUT); + digitalWrite(Pin(GPIO_LEDLNK), ledlnk_inverted); + } + +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER == my_module_type && PinUsed(GPIO_REL1)) { devices_present--; } +#endif + + ButtonInit(); + SwitchInit(); +#ifdef ROTARY_V1 + RotaryInit(); +#endif + + SetLedPower(Settings.ledstate &8); + SetLedLink(Settings.ledstate &8); + + XdrvCall(FUNC_PRE_INIT); + XsnsCall(FUNC_PRE_INIT); +} +# 1 "/workspace/Tasmota/tasmota/support_udp.ino" +# 20 "/workspace/Tasmota/tasmota/support_udp.ino" +#ifdef USE_EMULATION + +#ifndef UDP_BUFFER_SIZE +#define UDP_BUFFER_SIZE 120 +#endif +#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; + +#ifdef ESP8266 +#ifndef UDP_MAX_PACKETS +#define UDP_MAX_PACKETS 3 +#endif + +#include "UdpListener.h" +UdpListener UdpCtx(UDP_MAX_PACKETS); +#endif + + + + + +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(); +#ifdef ESP8266 + UdpCtx.disconnect(); +#endif +#ifdef USE_DEVICE_GROUPS + + PortUdp.stop(); +#else + + WiFiUDP::stopAll(); +#endif + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); + udp_connected = false; + } + return udp_connected; +} + +bool UdpConnect(void) +{ + if (!udp_connected && !restart_flag) { + +#ifdef ESP8266 + UdpCtx.reset(); + if (igmp_joingroup(WiFi.localIP(), IPAddress(239,255,255,250)) == ERR_OK) { + ip_addr_t addr = IPADDR4_INIT(INADDR_ANY); + if (UdpCtx.listen(&addr, 1900)) { + + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); + udp_response_mutex = false; + udp_connected = true; + } +#else + 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; +#endif + } + if (!udp_connected) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); + } + } + return udp_connected; +} + +void PollUdp(void) +{ + if (udp_connected) { +#ifdef ESP8266 + while (UdpCtx.next()) { + UdpPacket *packet; + packet = UdpCtx.read(); + if (packet->len >= UDP_BUFFER_SIZE) { + packet->len--; + } + packet->buf[packet->len] = 0; + char * packet_buffer = (char*) &packet->buf; + int32_t len = packet->len; +#else + while (PortUdp.parsePacket()) { + char packet_buffer[UDP_BUFFER_SIZE]; + + int32_t len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); + packet_buffer[len] = 0; +#endif + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); + + + + if (Settings.flag2.emulation) { +#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) + 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; + +#ifdef ESP8266 + udp_remote_ip = packet->srcaddr; + udp_remote_port = packet->srcport; +#else + udp_remote_ip = PortUdp.remoteIP(); + udp_remote_port = PortUdp.remotePort(); +#endif + + + + + 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; + continue; + } + } + } + optimistic_yield(100); + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/support_wifi.ino" +# 29 "/workspace/Tasmota/tasmota/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 = 12; + +#include +#if LWIP_IPV6 +#include +#endif + +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 config_type = 0; + uint8_t config_counter = 0; + uint8_t scan_state; + uint8_t bssid[6]; + int8_t best_network_db; +} 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); +} + +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_WEBSERVER + if (WIFI_MANAGER == 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_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 WifiSetMode(WiFiMode_t wifi_mode) +{ + if (WiFi.getMode() == wifi_mode) { return; } + + if (wifi_mode != WIFI_OFF) { + + WiFi.forceSleepWake(); + delay(100); + } + + uint32_t retry = 2; + while (!WiFi.mode(wifi_mode) && retry--) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); + delay(100); + } + + if (wifi_mode == WIFI_OFF) { + delay(1000); + WiFi.forceSleepBegin(); + delay(1); + } else { + delay(30); + } +} + +void WiFiSetSleepMode(void) +{ +# 156 "/workspace/Tasmota/tasmota/support_wifi.ino" + if (ssleep && Settings.flag3.sleep_normal) { + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); + } else { + WiFi.setSleepMode(WIFI_MODEM_SLEEP); + } + WifiSetOutputPower(); +} + +void WifiBegin(uint8_t flag, uint8_t channel) +{ + const char kWifiPhyMode[] = " BGN"; + +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + + WiFi.persistent(false); + WiFi.disconnect(true); + delay(200); + + WifiSetMode(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 (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { + 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); + + char stemp[40] = { 0 }; + if (channel) { + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); + + char hex_char[18]; + snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); + } else { + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + +#if LWIP_IPV6 + for (bool configured = false; !configured;) { + uint16_t cfgcnt = 0; + for (auto addr : addrList) { + if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str()); + break; + } + delay(500); + cfgcnt++; + } + } +#endif +} + +void WifiBeginAfterScan(void) +{ + + if (0 == Wifi.scan_state) { return; } + + if (1 == Wifi.scan_state) { + memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); + Wifi.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)); + Wifi.best_network_db = WiFi.RSSI(); + if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { + Wifi.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 < MAX_SSIDS; j++) { + if (ssid_scan == SettingsText(SET_STASSID1 + j)) { + known = true; + if (rssi_scan > Wifi.best_network_db) { + if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { + Wifi.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(void) +{ + return Wifi.link_count; +} + +String WifiDowntime(void) +{ + 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; + if (!global_state.wifi_down) { + global_state.network_down = 0; + } +} + +#if LWIP_IPV6 +bool WifiCheckIPv6(void) +{ + bool ipv6_global=false; + + for (auto a : addrList) { + if(!a.isLocal() && a.isV6()) ipv6_global=true; + } + return ipv6_global; +} + +String WifiGetIPv6(void) +{ + for (auto a : addrList) { + if(!a.isLocal() && a.isV6()) return a.toString(); + } + return ""; +} + +bool WifiCheckIPAddrStatus(void) +{ + bool ip_global=false; + + for (auto a : addrList) { + if(!a.isLocal()) ip_global=true; + } + return ip_global; +} +#endif + +void WifiCheckIp(void) +{ +#if LWIP_IPV6 + if(WifiCheckIPAddrStatus()) { + Wifi.status = WL_CONNECTED; +#else + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { +#endif + WifiSetState(1); + Wifi.counter = WIFI_CHECK_SEC; + Wifi.retry = Wifi.retry_init; + if (Wifi.status != WL_CONNECTED) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_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(); + + + Settings.wifi_channel = WiFi.channel(); + uint8_t *bssid = WiFi.BSSID(); + memcpy((void*) &Settings.wifi_bssid, (void*) bssid, sizeof(Settings.wifi_bssid)); + } + Wifi.status = WL_CONNECTED; +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE + MdnsUpdate(); +#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)); + Settings.wifi_channel = 0; + 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)); + Settings.wifi_channel = 0; + 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)); + Settings.wifi_channel = 0; + } else { + if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { + Settings.wifi_channel = 0; + wifi_config_tool = WIFI_MANAGER; + 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, Settings.wifi_channel); + } + 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_MANAGER: + WifiConfig(param); + break; + default: + if (Wifi.config_counter) { + Wifi.config_counter--; + Wifi.counter = Wifi.config_counter +5; + if (Wifi.config_counter) { + if (!Wifi.config_counter) { + if (strlen(WiFi.SSID().c_str())) { + SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); + } + if (strlen(WiFi.psk().c_str())) { + SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); + } + Settings.sta_active = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); + } + } + if (!Wifi.config_counter) { + + 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 LWIP_IPV6 + if (WifiCheckIPAddrStatus()) { +#else + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { +#endif + WifiSetState(1); + if (Settings.flag3.use_wifi_rescan) { + if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { + Wifi.scan_state = 2; + } + } + } else { + WifiSetState(0); + Mdns.begun = 0; + } + } + } +} + +int WifiState(void) +{ + int state = -1; + + if (!global_state.wifi_down) { state = WIFI_RESTART; } + if (Wifi.config_type) { state = Wifi.config_type; } + return state; +} + +String WifiGetOutputPower(void) +{ + char stemp1[TOPSZ]; + dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); + return String(stemp1); +} + +void WifiSetOutputPower(void) +{ + WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); +} +# 563 "/workspace/Tasmota/tasmota/support_wifi.ino" +#ifdef WIFI_RF_MODE_RF_CAL +#ifndef USE_DEEPSLEEP +RF_MODE(RF_CAL); +#endif +#endif + +#ifdef WIFI_RF_PRE_INIT +bool rf_pre_init_flag = false; +RF_PRE_INIT() +{ +#ifndef USE_DEEPSLEEP + system_deep_sleep_set_option(1); + system_phy_set_rfoption(RF_CAL); +#endif + system_phy_set_powerup_option(3); + rf_pre_init_flag = true; +} +#endif + +void WifiConnect(void) +{ + if (!Settings.flag4.network_wifi) { return; } + + WifiSetState(0); + WifiSetOutputPower(); + WiFi.persistent(false); + Wifi.status = 0; + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP_getChipId() & 0xF); + Wifi.retry = Wifi.retry_init; + Wifi.counter = 1; + + memcpy((void*) &Wifi.bssid, (void*) Settings.wifi_bssid, sizeof(Wifi.bssid)); + +#ifdef WIFI_RF_PRE_INIT + if (rf_pre_init_flag) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Pre-init done")); + } +#endif +} + +void WifiShutdown(bool option = false) +{ + + + delay(100); + +#ifdef USE_EMULATION + UdpDisconnect(); + delay(100); +#endif + + if (Settings.flag.mqtt_enabled) { + MqttDisconnect(); + delay(100); + } + +#ifdef WIFI_FORCE_RF_CAL_ERASE + if (option) { + WiFi.disconnect(false); + SettingsErase(4); + } else +#endif + { + + + + + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + + } + delay(100); +} + +void EspRestart(void) +{ + ResetPwm(); + WifiShutdown(true); + CrashDumpClear(); + + if (restart_halt) { + while (1) { + OsWatchLoop(); + SetLedLink(1); + delay(200); + SetLedLink(0); + delay(800); + } + } else { + ESP_Restart(); + } +} + + + + +extern "C" { +#if LWIP_VERSION_MAJOR == 1 +#include "netif/wlan_lwip_if.h" +#include "netif/etharp.h" +#else +#include "lwip/etharp.h" +#endif +} + +unsigned long wifiTimer = 0; + +void stationKeepAliveNow(void) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI "Sending Gratuitous ARP")); + for (netif* interface = netif_list; interface != nullptr; interface = interface->next) + if ( + (interface->flags & NETIF_FLAG_LINK_UP) + && (interface->flags & NETIF_FLAG_UP) +#if LWIP_VERSION_MAJOR == 1 + && interface == eagle_lwip_getif(STATION_IF) + && (!ip_addr_isany(&interface->ip_addr)) +#else + && interface->num == STATION_IF + && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) +#endif + ) + { + etharp_gratuitous(interface); + break; + } +} + +void wifiKeepAlive(void) { + uint32_t wifiTimerSec = Settings.param[P_ARP_GRATUITOUS]; + + if ((WL_CONNECTED != Wifi.status) || (0 == wifiTimerSec)) { return; } + + if (TimeReached(wifiTimer)) { + stationKeepAliveNow(); + if (wifiTimerSec > 100) { + wifiTimerSec = (wifiTimerSec - 100) * 60; + } + SetNextTimeInterval(wifiTimer, wifiTimerSec * 1000); + } +} +# 1 "/workspace/Tasmota/tasmota/tasmota_ca.ino" +# 24 "/workspace/Tasmota/tasmota/tasmota_ca.ino" +#if defined(USE_TLS) && defined(USE_MQTT_TLS_CA_CERT) +# 37 "/workspace/Tasmota/tasmota/tasmota_ca.ino" +static const unsigned char PROGMEM LetsEncrypt_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 LetsEncrypt_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 LetsEncrypt_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { + { (unsigned char *)LetsEncrypt_DN, sizeof LetsEncrypt_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)LetsEncrypt_RSA_N, sizeof LetsEncrypt_RSA_N, + (unsigned char *)LetsEncrypt_RSA_E, sizeof LetsEncrypt_RSA_E, + } } + } +}; +# 100 "/workspace/Tasmota/tasmota/tasmota_ca.ino" +const unsigned char PROGMEM AmazonRootCA1_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 AmazonRootCA1_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 AmazonRootCA1_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { + { (unsigned char *)AmazonRootCA1_DN, sizeof AmazonRootCA1_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)AmazonRootCA1_RSA_N, sizeof AmazonRootCA1_RSA_N, + (unsigned char *)AmazonRootCA1_RSA_E, sizeof AmazonRootCA1_RSA_E, + } } + } +}; + + +const br_x509_trust_anchor PROGMEM Tasmota_TA[] = { + { + { (unsigned char *)LetsEncrypt_DN, sizeof LetsEncrypt_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)LetsEncrypt_RSA_N, sizeof LetsEncrypt_RSA_N, + (unsigned char *)LetsEncrypt_RSA_E, sizeof LetsEncrypt_RSA_E, + } } + } + } + , + { + { (unsigned char *)AmazonRootCA1_DN, sizeof AmazonRootCA1_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)AmazonRootCA1_RSA_N, sizeof AmazonRootCA1_RSA_N, + (unsigned char *)AmazonRootCA1_RSA_E, sizeof AmazonRootCA1_RSA_E, + } } + } + } +}; + +const size_t Tasmota_TA_size = ARRAY_SIZE(Tasmota_TA); +# 187 "/workspace/Tasmota/tasmota/tasmota_ca.ino" +const unsigned char GoDaddyCAG2_DN[] PROGMEM = { + 0x30, 0x3E, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x18, 0x44, 0x6F, 0x6D, 0x61, 0x69, 0x6E, 0x20, 0x43, 0x6F, 0x6E, 0x74, + 0x72, 0x6F, 0x6C, 0x20, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, + 0x61, 0x70, 0x69, 0x2E, 0x74, 0x65, 0x6C, 0x65, 0x67, 0x72, 0x61, 0x6D, + 0x2E, 0x6F, 0x72, 0x67 +}; + +const unsigned char GoDaddyCAG2_RSA_N[] PROGMEM = { + 0xB4, 0xA3, 0x16, 0x9E, 0x5C, 0x57, 0xC9, 0x89, 0x65, 0xED, 0xEA, 0x78, + 0x0B, 0xAE, 0x8A, 0x58, 0x2F, 0xAE, 0x5A, 0xC8, 0x6E, 0x49, 0x8D, 0xFC, + 0x57, 0xA5, 0x98, 0x88, 0x78, 0x2E, 0x0B, 0x3C, 0x40, 0x3C, 0x21, 0x2E, + 0x9A, 0x94, 0x98, 0x33, 0xA7, 0xE3, 0x42, 0xA7, 0x85, 0xFA, 0xD0, 0x73, + 0x84, 0x01, 0x1C, 0x72, 0x39, 0x37, 0x23, 0xB5, 0x56, 0x1D, 0x43, 0xA5, + 0x71, 0x14, 0x08, 0x24, 0xA5, 0x39, 0xCC, 0xDE, 0x58, 0x53, 0x94, 0x8E, + 0x2A, 0x42, 0xA7, 0x4E, 0x2D, 0x07, 0x32, 0x9E, 0xBA, 0x8B, 0xD3, 0x2A, + 0xA9, 0x9E, 0xC0, 0xE3, 0xCE, 0x9A, 0x10, 0x96, 0x45, 0x58, 0x7A, 0xC7, + 0x1E, 0x45, 0x14, 0x23, 0x92, 0xBB, 0x54, 0x82, 0x88, 0x94, 0x49, 0xB6, + 0xBE, 0x81, 0x21, 0x00, 0x29, 0x6D, 0xC9, 0xCE, 0x8B, 0x39, 0x3A, 0xDC, + 0x35, 0x15, 0xD9, 0xEB, 0x47, 0x9C, 0xEF, 0xBA, 0x09, 0x0E, 0x16, 0xE4, + 0xD9, 0xEB, 0x72, 0x30, 0xFA, 0x49, 0xAB, 0x98, 0x31, 0x7C, 0xB3, 0xAC, + 0x2B, 0x29, 0x91, 0x87, 0x08, 0x41, 0x72, 0x5E, 0x35, 0xC7, 0x87, 0x04, + 0x22, 0xF5, 0x48, 0x76, 0x30, 0x6D, 0x88, 0xDF, 0xF2, 0xA5, 0x29, 0x13, + 0x70, 0xB3, 0x87, 0x02, 0xD5, 0x6B, 0x58, 0xB1, 0xE8, 0x73, 0xC7, 0xE4, + 0xEF, 0x79, 0x86, 0xA4, 0x07, 0x5F, 0x67, 0xB4, 0x79, 0x8D, 0xA4, 0x25, + 0x01, 0x82, 0x8C, 0xE0, 0x30, 0x17, 0xCB, 0x4B, 0x5C, 0xFB, 0xEB, 0x4C, + 0x12, 0x51, 0xB9, 0xC9, 0x04, 0x1F, 0x7E, 0xD2, 0xF8, 0xBA, 0xF5, 0x35, + 0x8D, 0x8A, 0x1C, 0x37, 0x82, 0xF0, 0x15, 0x73, 0x00, 0x6E, 0x3D, 0x1C, + 0x76, 0x8B, 0x01, 0x74, 0x81, 0x3D, 0xE4, 0x2C, 0xA7, 0xCC, 0x2F, 0x66, + 0xDC, 0x44, 0xA8, 0x27, 0x3F, 0xEA, 0xD0, 0xA7, 0xA8, 0xF1, 0xCB, 0xEA, + 0xDA, 0x07, 0x38, 0xBD +}; + +const unsigned char GoDaddyCAG2_RSA_E[] PROGMEM = { + 0x01, 0x00, 0x01 +}; + +const br_x509_trust_anchor GoDaddyCAG2_TA PROGMEM = { + { (unsigned char *)GoDaddyCAG2_DN, sizeof GoDaddyCAG2_DN }, + 0, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)GoDaddyCAG2_RSA_N, sizeof GoDaddyCAG2_RSA_N, + (unsigned char *)GoDaddyCAG2_RSA_E, sizeof GoDaddyCAG2_RSA_E, + } } + } +}; + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_01_webserver.ino" +# 20 "/workspace/Tasmota/tasmota/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 = (MESSZ / 2) - 100; + +const uint16_t HTTP_REFRESH_TIME = 2345; +const uint16_t HTTP_RESTART_RECONNECT_TIME = 9000; +const uint16_t 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, UPL_TASMOTACLIENT, UPL_EFR32 }; + +#ifdef USE_UNISHOX_COMPRESSION +#ifdef USE_JAVASCRIPT_ES6 + +const size_t HTTP_HEADER1_SIZE = 377; +const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3F\xB2\xEC\xD7\xE6\x86\x7D\x78\xFE\xCB\xB3\x5F\x9A\x1A\x0C\x2B\xF7\x8F" + "\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6" + "\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E" + "\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1" + "\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61" + "\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3" + "\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50" + "\x54\x75\x56\x1D\x54\x30\xEA\x18\x19\xF0\xFB\x3E\xCF\x0C\x71\xF3\xC7\xC3\xF0\x4C" + "\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35\xF5\x10\xE3\x22\xD1\x0E\xEF\x8E\xF1\xE0" + "\xD5\xE0\x48\xBA\x6A\x16\xFE\x64\x5E\x61\x30\xEB\x3E\x77\x7C\x77\x8F\x1E\x18\x7C" + "\xD3\xE1\xF8\xC7\x1D\xDD\x3B\xC7\x4A\x32\x18\xCF\x87\x74\x11\xA4\x1F\x0F\x87\xDD" + "\x33\x65\x1F\x67\x68\xFB\x19\x7E\xF0\xFE\x7C\x43\xEC\xF3\x04\x19\xC7\x78\xF0\x3E" + "\x11\xF0\xC1\xF0\xFC\x1F\xDE\x13\x07\xCE\x96\x20\x84\xCC\xDF\x51\x05\xBE\xA7\xCF" + "\xE7\x74\xFB\x0B\x2C\x43\xEC\xEA\x30\x77\x8F\x06"; +#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() +#else +const size_t HTTP_HEADER1_SIZE = 431; +const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3F\xB2\xEC\xD7\xE6\x86\x7D\x78\xFE\xCB\xB3\x5F\x9A\x1A\x0C\x2B\xF7\x8F" + "\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6" + "\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E" + "\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1" + "\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61" + "\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3" + "\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50" + "\x54\x75\x56\x1D\x54\x30\xEA\x18\x19\xF0\xFB\x3E\xCF\x06\x05\xF0\x75\xB9\xC9\x8E" + "\x3B\xBE\x3B\xC7\xB7\xEE\x85\xFF\x90\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B" + "\xEA\x21\xC6\x45\xA2\x1D\xDF\x1D\xE3\xC1\xEE\x04\x4C\x38\xD5\xE0\x4F\xC3\x8D\x42" + "\xDF\xCC\x8B\xCC\x26\x1D\x67\xC1\x27\x0D\xF0\xC3\xBB\xA7\x78\xF6\xB1\xC7\x77\x4E" + "\xF1\xD2\x8C\x86\x33\xE1\xDD\x04\x69\x07\xC3\xE1\xF7\x4C\xD9\x47\xD9\xDA\x3E\xC6" + "\x5F\xBC\x3F\x9F\x10\xFB\x3C\xC1\x06\x70\x23\xE3\xE3\xE1\x1D\xD3\x07\x78\xF6\x8F" + "\xEF\x09\x83\xE7\x4B\x10\x42\x66\x6F\xA8\x82\xDF\x53\xE7\xF3\xBA\x7D\x85\x96\x21" + "\xF6\x75\x18\x3B\xC7\x83\xDC"; +#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() +#endif +#else +const char HTTP_HEADER1[] PROGMEM = + "" + "" + "" + "" + "%s - %s" + + ""; +#endif + +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_HEAD_STYLE1_SIZE = 591; +const char HTTP_HEAD_STYLE1_COMPRESSED[] PROGMEM = "\x3D\x3D\x46\x41\x33\xF0\x4D\x33\x3A\x8C\x6B\x08\x4F\x3A\x3A\xB7\x86\x0B\xA3\xAB" + "\xCC\x26\x1D\x1E\xD1\x96\x20\x9B\xC3\xC7\x99\xCD\x21\x86\xC3\xC1\x8C\xEA\x3A\xFD" + "\xA6\xD6\x79\x9C\x84\xC6\x9E\x0F\x70\x21\xE1\xA7\xB4\x75\x86\x68\x3D\xFC\x17\xC2" + "\x1E\x67\x91\xF4\x71\xF1\x1B\x0F\x07\xB8\x61\xED\x1B\x7F\x1E\xDE\x3C\xCE\x33\xA6" + "\x93\x1A\x8E\x33\xC1\xEE\x2D\xE1\x82\xE8\xF6\x8F\xE8\x94\x28\xF3\x39\x1B\x3E\x8F" + "\xA3\xC1\x0E\xC3\x61\xD7\xED\x36\xEF\x0F\x1E\x63\xB3\xE2\x3F\x9D\x63\xB0\xD8\x78" + "\x3A\xC7\xD8\xE3\x4D\xA3\xAC\x14\xAD\x0D\xC3\x68\x29\x57\x04\xCD\x84\x3C\x0B\x3E" + "\x08\x7B\x6E\xF0\xC1\x74\x7B\xD4\x64\x31\x9F\x03\x14\xC3\x34\x1D\x86\xC3\xDF\x04" + "\x1E\x11\x41\x06\x8F\xEC\x4D\xC3\xDF\x04\x3D\xF1\x8D\x3C\x02\x0F\x03\x87\x5F\xF4" + "\x78\x55\x1E\x67\x38\x86\x1B\x0F\x06\x6F\xF5\xA1\xD8\x47\x5D\x85\xA3\xDC\x79\x9D" + "\x67\x21\x0C\x04\x9C\xCF\xF7\xC3\xCC\x10\xF1\xE3\x89\x1F\x47\xD1\xE0\xF7\x10\x21" + "\x71\x3E\x09\x1C\x28\x82\xC7\x2A\x01\x54\xCD\x95\x7F\x76\x7B\x7E\xFD\xA6\xD6\x79" + "\x82\x1E\xA0\x78\x04\x2C\xC8\xE7\xCF\xA3\xE8\xF0\x42\x9E\x8F\x0A\xA3\xCC\xE5\xCF" + "\x90\xC3\x61\xE0\x11\xF8\xFA\xC3\x37\xF3\x01\x60\xF9\xE7\x62\xEB\x01\x6B\x45\x1D" + "\x82\x19\x1E\xDA\x66\xCA\x04\x2E\x0A\x83\x7D\x4F\xE0\x83\xC9\xE9\x8B\x1B\xA1\x19" + "\x1E\x66\x6F\xE2\x5F\x59\xD5\xEB\xEF\x1D\x7E\x7F\xD3\x2A\x01\x9B\x98\x1E\xEA\x10" + "\x11\x39\x7D\x38\xC8\x61\xB0\xF0\x7B\x8D"; +#define HTTP_HEAD_STYLE1 Decompress(HTTP_HEAD_STYLE1_COMPRESSED,HTTP_HEAD_STYLE1_SIZE).c_str() +#else +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_SLIDER_GRADIENT[] PROGMEM = + "
" + "" + "
"; +const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = + "
" D_CLOSE "" D_OPEN "
" + "
"; + +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_AP2_SSID " (" STA_SSID2 ")

" + "


" + "

" D_HOSTNAME " (%s)

" + "

" D_CORS_DOMAIN "

"; + +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 " " + "

" + "

" + "
" + "
" + "

" + "
" + "
" + "
" + "

" + "
"; + +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_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; + +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 + "|" D_UPLOAD_ERR_14 + ; + +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); + last_source = source; + ExecuteCommand(svalue, SRC_IGNORE); +} + + +typedef struct WebServerDispatch_t { + char uri[3]; + uint8_t method; + void (*handler)(void); +} WebServerDispatch_t; + +const WebServerDispatch_t WebServerDispatch[] PROGMEM = { + { "", HTTP_ANY, HandleRoot }, + { "up", HTTP_ANY, HandleUpgradeFirmware }, + { "u1", HTTP_ANY, HandleUpgradeFirmwareStart }, + { "u2", HTTP_OPTIONS, HandlePreflightRequest }, + { "u3", HTTP_ANY, HandleUploadDone }, + { "cs", HTTP_GET, HandleConsole }, + { "cs", HTTP_OPTIONS, HandlePreflightRequest }, + { "cm", HTTP_ANY, HandleHttpCommand }, +#ifndef FIRMWARE_MINIMAL + { "cn", HTTP_ANY, HandleConfiguration }, + { "md", HTTP_ANY, HandleModuleConfiguration }, + { "wi", HTTP_ANY, HandleWifiConfiguration }, + { "lg", HTTP_ANY, HandleLoggingConfiguration }, + { "tp", HTTP_ANY, HandleTemplateConfiguration }, + { "co", HTTP_ANY, HandleOtherConfiguration }, + { "dl", HTTP_ANY, HandleBackupConfiguration }, + { "rs", HTTP_ANY, HandleRestoreConfiguration }, + { "rt", HTTP_ANY, HandleResetConfiguration }, + { "in", HTTP_ANY, HandleInformation }, +#endif +}; + +void WebServer_on(const char * prefix, void (*func)(void), uint8_t method = HTTP_ANY) { + Webserver->on((const __FlashStringHelper *) prefix, (HTTPMethod) method, func); +} + +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); + + for (uint32_t i=0; ionNotFound(HandleNotFound); + Webserver->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); +#ifndef FIRMWARE_MINIMAL + XdrvCall(FUNC_WEB_ADD_HANDLER); + XsnsCall(FUNC_WEB_ADD_HANDLER); +#endif + } + Web.reset_web_log_flag = false; + + Webserver->begin(); + } + if (Web.state != type) { +#if LWIP_IPV6 + String ipv6_addr = WifiGetIPv6(); + if (ipv6_addr!="") { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "), + NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str(), ipv6_addr.c_str()); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), + NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); + } +#else + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), + NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); +#endif + 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) { + + WifiSetMode(WIFI_AP_STA); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION)); + } else { + + WifiSetMode(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, WIFI_AP_PASSPHRASE, channel, 0, 1); + 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 (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) { + return Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); + } 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 HttpHeaderCors(void) +{ + if (strlen(SettingsText(SET_CORS))) { + Webserver->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); + } +} + +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")); + HttpHeaderCors(); +} + + + + + +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(); + Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); + WSSend(code, ctype, ""); + Web.chunk_buffer = ""; +} + +void _WSContentSend(const String& content) +{ + size_t len = content.length(); + Webserver->sendContent(content); + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("WSContentSend")); +#endif + DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d/%d"), len, sizeof(mqtt_data)); +} + +void WSContentFlush(void) +{ + 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); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + +#ifdef DEBUG_TASMOTA_CORE + if (len > (sizeof(mqtt_data) -1)) { + mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + } +#endif + + _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); + +#ifdef DEBUG_TASMOTA_CORE + if (len > (sizeof(mqtt_data) -1)) { + mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_PD size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + } +#endif + + 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 && strlen(SettingsText(SET_WEBPWD)) && !Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) { + return Webserver->requestAuthentication(); + } + + WSContentBegin(200, CT_HTML); + + if (title != nullptr) { +#ifdef USE_UNISHOX_COMPRESSION + WSContentSend_P(HTTP_HEADER1, D_HTML_LANGUAGE, SettingsText(SET_DEVICENAME), title); +#else + WSContentSend_P(HTTP_HEADER1, SettingsText(SET_DEVICENAME), title); +#endif + } +} + +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), + WebColor(COL_BUTTON)); +#ifdef USE_ZIGBEE + WSContentSend_P(HTTP_HEAD_STYLE_ZIGBEE); +#endif + if (formatP != nullptr) { + + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + +#ifdef DEBUG_TASMOTA_CORE + if (len > (sizeof(mqtt_data) -1)) { + mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSendStyle_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + } +#endif + + _WSContentSendBuffer(); + } + WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT), +#ifdef FIRMWARE_MINIMAL + WebColor(COL_TEXT_WARNING), +#endif + WebColor(COL_TITLE), + ModuleName().c_str(), SettingsText(SET_DEVICENAME)); + 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)

"), + NetworkHostname(), + (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 WSContentSend_THD(const char *types, float f_temperature, float f_humidity) +{ + char parameter[FLOATSZ]; + dtostrfd(f_temperature, Settings.flag2.temperature_resolution, parameter); + WSContentSend_PD(HTTP_SNS_TEMP, types, parameter, TempUnit()); + dtostrfd(f_humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_PD(HTTP_SNS_HUM, types, parameter); + dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings.flag2.temperature_resolution, parameter); + WSContentSend_PD(HTTP_SNS_DEW, types, parameter, TempUnit()); +} + +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_TIME, HTTP_RESTART_RECONNECT_TIME); + 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(); +} + +#ifdef USE_LIGHT +void WebSliderColdWarm(void) +{ + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "a", + "#eff", "#f81", + 1, + 153, 500, + LightGetColorTemp(), + 't', 0); +} +#endif + +void HandleRoot(void) +{ + if (CaptivePortal()) { return; } + + if (Webserver->hasArg("rst")) { + WebRestart(0); + return; + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg("USER1")) && !(Webserver->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + HandleWifiLogin(); + } else { + if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg("USER1") == WEB_USERNAME ) && (Webserver->arg("PASS1") == SettingsText(SET_WEBPWD) )) || 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[33]; + + 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 + WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); + + WSContentSendStyle(); + + WSContentSend_P(PSTR("
")); + if (devices_present) { +#ifdef USE_LIGHT + if (light_type) { + uint8_t light_subtype = light_type &7; + if (!Settings.flag3.pwm_multi_channels) { + bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); + + if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { + WebSliderColdWarm(); + } + + if (light_subtype > 2) { + uint16_t hue; + uint8_t sat; + LightGetHSB(&hue, &sat, nullptr); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "b", + "#800", PSTR("#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800"), + 2, + 1, 359, + hue, + 'h', 0); + + uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); + char scolor[8]; + snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); + uint8_t red, green, blue; + LightHsToRgb(hue, 255, &red, &green, &blue); + snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "s", + scolor, stemp, + 3, + 0, 100, + changeUIntScale(sat, 0, 255, 0, 100), + 'n', 0); + } + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "c", + "#000", "#fff", + 4, + Settings.flag3.slider_dimmer_stay_on, 100, + Settings.light_dimmer, + 'd', 0); + + if (split_white) { + if (LST_RGBCW == light_subtype) { + WebSliderColdWarm(); + } + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "f", + "#000", "#fff", + 5, + Settings.flag3.slider_dimmer_stay_on, 100, + LightGetDimmer(2), + 'w', 0); + } + } else { + uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; + stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; + for (uint32_t i = 0; i < pwm_channels; i++) { + stemp[1]++; + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + stemp, + "#000", "#fff", + i+1, + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), + 'e', i+1); + } + } + } +#endif +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < shutters_present; i++) { + WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); + } + } +#endif + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, + (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : 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, + (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, + ""); + } + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(idx)) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), + ""); + continue; + } +#endif + snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? "" : (devices_present > 1) ? stemp : ""); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("
%s
")); + } +#ifdef USE_TUYA_MCU + if (IsModuleTuya()) { + uint8_t modeset = 0; + if (AsModuleTuyaMS()) { + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); + snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); + WSContentSend_P(HTTP_DEVICE_CONTROL, 26, devices_present + 1, + (strlen(SettingsText(SET_BUTTON1 + devices_present))) ? SettingsText(SET_BUTTON1 + devices_present) : stemp, ""); + WSContentSend_P(PSTR("")); + modeset = 1; + } + if (IsTuyaFanCtrl()) { + uint8_t device = devices_present + modeset; + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); + for (uint32_t i = device + 1; i <= (TuyaFanSpeeds() + device) + 1; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i - (device + 1)); + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i, + (strlen(SettingsText(SET_BUTTON1 + i))) ? SettingsText(SET_BUTTON1 + i) : stemp, ""); + } + WSContentSend_P(PSTR("")); + } + } +#endif +#ifdef USE_SONOFF_RF + 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++; + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); + WSContentSend_P(PSTR(""), idx, + (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); + } + } + WSContentSend_P(PSTR("")); + } +#endif + +#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]; + char webindex[5]; + + 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 +#ifdef USE_TUYA_MCU + if (IsModuleTuya()) { + uint8_t FuncIdx = 0; + if (device <= devices_present) { + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); + } else { + if (AsModuleTuyaMS() && device == devices_present + 1) { + uint8_t dpId = TuyaGetDpId(TUYA_MCU_FUNC_MODESET); + snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend4 %d,%d"), dpId, !TuyaModeSet()); + ExecuteCommand(svalue, SRC_WEBGUI); + } + if (IsTuyaFanCtrl()) { + uint8_t dpId = 0; + for (uint32_t i = 0; i <= 3; i++) { + if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { + dpId = TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i); + } + } + if ((AsModuleTuyaMS() && device != devices_present + 1) || !AsModuleTuyaMS()) { + if (AsModuleTuyaMS()) {FuncIdx = 1;} + snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend2 %d,%d"), dpId, (device - (devices_present + FuncIdx) - 1)); + ExecuteCommand(svalue, SRC_WEBGUI); + } + } + } + } else { +#endif +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(device)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_STOPOPEN) : PSTR(D_CMND_SHUTTER_STOPCLOSE)); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } else { +#endif + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SHUTTER + } +#endif +#ifdef USE_SONOFF_IFAN + } +#endif +#ifdef USE_TUYA_MCU + } +#endif + } +#ifdef USE_LIGHT + WebGetArg("d0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("w0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + uint32_t light_device = LightDevice(); + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t j = 0; j < pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j +1); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j +light_device, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } + WebGetArg("t0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("h0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("n0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#endif +#ifdef USE_SHUTTER + for (uint32_t j = 1; j <= shutters_present; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } +#endif +#ifdef USE_SONOFF_RF + WebGetArg("k", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#endif + WSContentBegin(200, CT_HTML); + WSContentSend_P(PSTR("{t}")); + XsnsCall(FUNC_WEB_SENSOR); + XdrvCall(FUNC_WEB_SENSOR); + + 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("")); + } +#ifdef USE_TUYA_MCU + if (IsModuleTuya()) { + uint32_t fanspeed = TuyaFanState(); + uint32_t modeset = TuyaModeSet(); + if (IsTuyaFanCtrl() && !AsModuleTuyaMS()) { + WSContentSend_P(PSTR("
" D_JSON_IRHVAC_FANSPEED ": %d
"), fanspeed); + } else if (!IsTuyaFanCtrl() && AsModuleTuyaMS()) { + WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d
"), modeset); + } else if (IsTuyaFanCtrl() && AsModuleTuyaMS()) { + WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d - " D_JSON_IRHVAC_FANSPEED ": %d
"), modeset, fanspeed); + } + } +#endif + WSContentEnd(); + + return true; +} + +#ifdef USE_SHUTTER +int32_t IsShutterWebButton(uint32_t idx) { + + int32_t ShutterWebButton = 0; + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { + ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); + break; + } + } + } + return ShutterWebButton; +} +#endif + + + +#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 WSContentSendNiceLists(uint32_t option) { + char stemp[30]; + for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { + if (option && (1 == i)) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); + } + uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0; + uint32_t midx = BGPIO(ridx); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); + } + WSContentSend_P(PSTR("\";")); + + WSContentSend_P(PSTR("hs=[")); + uint32_t midx; + bool first_done = false; + for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { + midx = pgm_read_word(kGpioNiceList + i); + if (midx & 0x001F) { + if (first_done) { WSContentSend_P(PSTR(",")); } + WSContentSend_P(PSTR("%d"), midx); + first_done = true; + } + } +#ifdef ESP8266 +#ifdef USE_ADC + for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { + midx = pgm_read_word(kAdcNiceList + i); + if (midx & 0x001F) { + if (first_done) { WSContentSend_P(PSTR(",")); } + WSContentSend_P(PSTR("%d"), midx); + first_done = true; + } + } +#endif +#endif + WSContentSend_P(PSTR("];")); +} + +#ifdef ESP8266 +#ifdef USE_ADC +void WSContentSendAdcNiceList(uint32_t option) { + char stemp[30]; + WSContentSend_P(PSTR("os=\"")); + for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { + if (option && (1 == i)) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); + } + uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0; + uint32_t midx = BGPIO(ridx); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); + } +} +#endif +#endif + + + +void HandleTemplateConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (Webserver->hasArg("save")) { + TemplateSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + + 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 < ARRAY_SIZE(cmodule.io); i++) { + if (!FlashPin(i)) { + 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); + + WSContentSendNiceLists(1); + + WSContentSend_P(HTTP_SCRIPT_TEMPLATE2); + +#ifdef ESP8266 +#ifdef USE_ADC + WSContentSendAdcNiceList(1); + WSContentSend_P(HTTP_SCRIPT_TEMPLATE3); +#endif +#endif + + WSContentSend_P(HTTP_SCRIPT_TEMPLATE4); + for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { + uint32_t midx = pgm_read_byte(kModuleNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), midx +1); + } + WSContentSend_P(HTTP_SCRIPT_TEMPLATE5); + + 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 < MAX_GPIO_PIN; i++) { + if (!FlashPin(i)) { + WSContentSend_P(PSTR("" D_GPIO "%d"), + ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:150px'" : "", i, i); + WSContentSend_P(PSTR(""), i); + } + } + WSContentSend_P(PSTR("")); + + gpio_flag flag = ModuleFlag(); + if (flag.data) { + WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); + } + + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +uint16_t WebGetGpioArg(uint32_t i) { + char webindex[5]; + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); + char tmp[8]; + WebGetArg(webindex, tmp, sizeof(tmp)); + uint32_t gpio = (!strlen(tmp)) ? 0 : atoi(tmp); + char webindex2[5]; + snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), i); + char tmp2[8]; + WebGetArg(webindex2, tmp2, sizeof(tmp2)); + uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1; + gpio += value2; + return gpio; +} + +void TemplateSaveSettings(void) +{ + char tmp[TOPSZ]; + char svalue[300]; + + 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 < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", WebGetGpioArg(j)); + j++; + } + + uint32_t flag = 0; + char webindex[5]; + 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; + 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; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + + char stemp[30]; + uint32_t midx; + myio cmodule; + ModuleGpios(&cmodule); + + WSContentStart_P(S_CONFIGURE_MODULE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + + WSContentSend_P(PSTR("function sl(){os=\"")); + 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_INDEX, midx, AnyModuleName(midx).c_str(), vidx); + } + WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings.module); + + WSContentSendNiceLists(0); + + for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); + } + } + +#ifdef ESP8266 +#ifdef USE_ADC + WSContentSendAdcNiceList(0); + WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_gp.io[(sizeof(myio) / 2) -1]); +#endif +#endif + + WSContentSend_P(PSTR("}wl(sl);")); + + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); + for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(stemp, 3, PINS_WEMOS +i*2); + WSContentSend_P(PSTR("%s " D_GPIO "%d"), + (WEMOS==my_module_type)?stemp:"", i, i, i); + WSContentSend_P(PSTR(""), i); + } + } + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void ModuleSaveSettings(void) +{ + char tmp[8]; + + 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 < ARRAY_SIZE(cmodule.io); i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = GPIO_NONE; + } else { + if (ValidGPIO(i, cmodule.io[i])) { + Settings.my_gp.io[i] = WebGetGpioArg(i); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } + + 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]); + uint32_t cschn = WiFi.channel(indices[i]); + for (uint32_t j = i + 1; j < n; j++) { + if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(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; } + int32_t rssi = WiFi.RSSI(indices[i]); + 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]), rssi); + int quality = WifiGetRssiAsQuality(rssi); + int auth = WiFi.encryptionType(indices[i]); + char encryption[20]; + WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), + quality, rssi + ); + delay(0); + + } + WSContentSend_P(PSTR("
")); + } + } else { + WSContentSend_P(PSTR("
")); + } + + + WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); + WSContentSend_P(HTTP_FORM_END); + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESTORE); + WSContentButton(BUTTON_RESET_CONFIGURATION); +#endif + WSContentSpaceButton(BUTTON_RESTART); + } else { + WSContentSpaceButton(BUTTON_CONFIGURATION); + } + WSContentStop(); +} + +void WifiSaveSettings(void) +{ + char tmp[TOPSZ]; + + WebGetArg("h", tmp, sizeof(tmp)); + SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + } + WebGetArg("c", tmp, sizeof(tmp)); + SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); + WebGetArg("s1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); + WebGetArg("s2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); + WebGetArg("p1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); + WebGetArg("p2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), + SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); +} + + + +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[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)

")); + } + WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void LoggingSaveSettings(void) +{ + char tmp[TOPSZ]; + + 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)); + Settings.mqttlog_level = (!strlen(tmp)) ? MQTT_LOG_LEVEL : atoi(tmp); + WebGetArg("l3", tmp, sizeof(tmp)); + SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); + WebGetArg("lh", tmp, sizeof(tmp)); + SettingsUpdateText(SET_SYSLOG_HOST, (!strlen(tmp)) ? SYS_LOG_HOST : tmp); + 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_MQTTLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), + Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, SettingsText(SET_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" : "", + SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); + + 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 : "", + SettingsText(SET_FRIENDLYNAME1 + i)); + } + +#ifdef USE_EMULATION +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) + 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 +#endif + + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void OtherSaveSettings(void) +{ + char tmp[300]; + char webindex[5]; + char friendlyname[TOPSZ]; + char message[LOGSZ]; + + WebGetArg("dn", tmp, sizeof(tmp)); + SettingsUpdateText(SET_DEVICENAME, (!strlen(tmp)) ? "" : (!strcmp(tmp,"1")) ? SettingsText(SET_FRIENDLYNAME1) : tmp); + WebGetArg("wp", tmp, sizeof(tmp)); + SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); + Settings.flag.mqtt_enabled = Webserver->hasArg("b1"); +#ifdef USE_EMULATION + UdpDisconnect(); +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) + WebGetArg("b2", tmp, sizeof(tmp)); + Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif +#endif + + snprintf_P(message, sizeof(message), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_DEVICENAME " %s, " D_CMND_FRIENDLYNAME), + GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation, SettingsText(SET_DEVICENAME)); + 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); + SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); + snprintf_P(message, sizeof(message), PSTR("%s%s %s"), message, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); + } + AddLog_P(LOG_LEVEL_INFO, message); + + WebGetArg("t1", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); + ExecuteWebCommand(message, 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[TOPSZ]; + + + + + 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); + } + } + + myClient.write((const char*)settings_buffer, sizeof(Settings)); + + 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); + if (WifiIsInManagerMode()) { + WSContentSpaceButton(BUTTON_MAIN); + } else { + 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_CORE_RELEASE "/%s"), ESP.getSdkVersion()); + WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); +#ifdef ESP8266 + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); +#else + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d"), Settings.save_flag); +#endif + 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, SettingsText(SET_FRIENDLYNAME1 +i)); + } + WSContentSend_P(PSTR("}1}2 ")); +#ifdef ESP32 +#ifdef USE_ETHERNET + if (static_cast(EthernetLocalIP()) != 0) { + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? ".local" : ""); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str()); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (eth)}2%s"), EthernetLocalIP().toString().c_str()); + WSContentSend_P(PSTR("}1
}2
")); + } +#endif +#endif + if (Settings.flag4.network_wifi) { + int32_t rssi = WiFi.RSSI(); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : ""); +#if LWIP_IPV6 + String ipv6_addr = WifiGetIPv6(); + if (ipv6_addr != "") { + WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str()); + } +#endif + if (static_cast(WiFi.localIP()) != 0) { + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (wifi)}2%s"), WiFi.localIP().toString().c_str()); + WSContentSend_P(PSTR("}1
}2
")); + } + } + if (!global_state.network_down) { + 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()); + } + if ((WiFi.getMode() >= WIFI_AP) && (static_cast(WiFi.softAPIP()) != 0)) { + WSContentSend_P(PSTR("}1
}2
")); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (AP)}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); + } + WSContentSend_P(PSTR("}1}2 ")); + if (Settings.flag.mqtt_enabled) { + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST)); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); +#ifdef USE_MQTT_TLS + WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings.flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); +#endif + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); + WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 1 +i, GetGroupTopic_P(stopic, "", real_index +i)); + } + } + 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, "")); + WSContentSend_P(PSTR("}1" D_MQTT_NO_RETAIN "}2%s"), Settings.flag4.mqtt_no_retain ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); + } 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()); +#ifdef ESP8266 + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); +#endif + 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); +#ifdef ESP32 + if (psramFound()) { + WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%dkB"), ESP.getPsramSize() / 1024); + WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%dkB"), ESP.getFreePsram() / 1024); + } +#endif + 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, SettingsText(SET_OTAURL)); + 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[TOPSZ + 10]; + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); + WifiConfigCounter(); + + char otaurl[TOPSZ]; + 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_TIME, HTTP_OTA_RESTART_RECONNECT_TIME); + 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; } + +#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) + if (!Web.upload_error) { + + if (ZigbeeUploadOtaReady()) { + HandleZigbeeXfer(); + return; + } + } +#endif + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); + + char error[100]; + + WifiConfigCounter(); + restart_flag = 0; + MqttRetryCounter(0); +#ifdef USE_COUNTER + CounterInterruptDisable(false); +#endif + + WSContentStart_P(S_INFORMATION); + if (!Web.upload_error) { + uint32_t javascript_settimeout = HTTP_OTA_RESTART_RECONNECT_TIME; +#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) + if (ZigbeeUploadFinish()) { + javascript_settimeout = 10000; + } +#endif + WSContentSend_P(HTTP_SCRIPT_RELOAD_TIME, javascript_settimeout); + } + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

"), WebColor(COL_TEXT_WARNING)); +#ifdef USE_RF_FLASH + if (Web.upload_error < 15) { +#else + if ((Web.upload_error < 10) || (14 == Web.upload_error)) { + if (14 == Web.upload_error) { 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)); + restart_flag = 2; +#ifdef USE_TASMOTA_CLIENT + if (TasmotaClient_GetFlagFlashing()) { + WSContentSend_P(PSTR("
" D_TRANSFER_STARTED " ...
")); + restart_flag = 0; + } +#endif + if (restart_flag) { + WSContentSend_P(HTTP_MSG_RSTRT); + ShowWebSource(SRC_WEBGUI); + } + } + SettingsBufferFree(); + WSContentSend_P(PSTR("

")); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); + +#ifdef USE_TASMOTA_CLIENT + if (TasmotaClient_GetFlagFlashing()) { + TasmotaClient_Flash(); + } +#endif +} + +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_COUNTER + CounterInterruptDisable(true); +#endif +#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 { +#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) +#ifdef ESP8266 + if ((SONOFF_ZB_BRIDGE == my_module_type) && (upload.buf[0] == 0xEB)) { +#else + if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX) && (upload.buf[0] == 0xEB)) { +#endif + Update.end(); + Web.upload_file_type = UPL_EFR32; + + Web.upload_error = ZigbeeUploadInit(); + if (Web.upload_error != 0) { return; } + } else +#endif +#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 +#ifdef USE_TASMOTA_CLIENT + if (TasmotaClient_Available() && (upload.buf[0] == ':')) { + Update.end(); + Web.upload_file_type = UPL_TASMOTACLIENT; + + Web.upload_error = TasmotaClient_UpdateInit(); + if (Web.upload_error != 0) { return; } + } else +#endif + { + if ((upload.buf[0] != 0xE9) && (upload.buf[0] != 0x1F)) { + Web.upload_error = 3; + return; + } + if (0xE9 == upload.buf[0]) { + uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); + if (bin_flash_size > ESP.getFlashChipRealSize()) { + Web.upload_error = 4; + return; + } + + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "File type %d"), Web.upload_file_type); + } + } + 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++; + } + } +#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) + else if (UPL_EFR32 == Web.upload_file_type) { + + if (!ZigbeeUploadWriteBuffer(upload.buf, upload.currentSize)) { + Web.upload_error = 9; + return; + } + } +#endif +#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 +#ifdef USE_TASMOTA_CLIENT + else if (UPL_TASMOTACLIENT == Web.upload_file_type) { + TasmotaClient_WriteBuffer(upload.buf, upload.currentSize); + } +#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) { +#ifdef ESP8266 + valid_settings = (0 == settings_buffer[0xF36]); +#endif +#ifdef ESP32 + valid_settings = (1 == settings_buffer[0xF36]); +#endif + } + + 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; + } + } +#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) + else if (UPL_EFR32 == Web.upload_file_type) { + + ZigbeeUploadDone(); + Web.upload_file_type = UPL_TASMOTA; + } +#endif +#ifdef USE_RF_FLASH + else if (UPL_EFM8BB1 == Web.upload_file_type) { + + Web.upload_file_type = UPL_TASMOTA; + } +#endif +#ifdef USE_TASMOTA_CLIENT + else if (UPL_TASMOTACLIENT == Web.upload_file_type) { + + TasmotaClient_SetFlagFlashing(true); + Web.upload_file_type = UPL_TASMOTA; + } +#endif + else { + if (!Update.end(true)) { + if (_serialoutput) { Update.printError(Serial); } + Web.upload_error = 6; + return; + } + if (!VersionCompatible()) { + Web.upload_error = 14; + return; + } + } + if (!Web.upload_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes"), upload.totalSize); + } + } + + + else if (UPLOAD_FILE_ABORTED == upload.status) { + restart_flag = 0; + MqttRetryCounter(0); +#ifdef USE_COUNTER + CounterInterruptDisable(false); +#endif + Web.upload_error = 7; + if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } + } + delay(0); +} + + + +void HandlePreflightRequest(void) +{ + HttpHeaderCors(); + 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)); + + if (strlen(SettingsText(SET_WEBPWD))) { + char tmp1[33]; + WebGetArg("user", tmp1, sizeof(tmp1)); + char tmp2[strlen(SettingsText(SET_WEBPWD)) +1]; + WebGetArg("password", tmp2, sizeof(tmp2)); + if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { + WSContentBegin(401, CT_JSON); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); + WSContentEnd(); + return; + } + } + + WSContentBegin(200, CT_JSON); + 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=\"}")); + } + 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++); +# 3202 "/workspace/Tasmota/tasmota/xdrv_01_webserver.ino" + if ((' ' == decodedChar) || ('+' == decodedChar)) { + encoded += '%'; + encoded += hex[decodedChar >> 4]; + encoded += hex[decodedChar & 0xF]; + } else { + encoded += decodedChar; + } + + } + return encoded; +} + +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[200]; + 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()); + + WiFiClient http_client; + HTTPClient http; + if (http.begin(http_client, UrlEncode(url))) { + 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) +{ + + + + + + JsonParser parser((char*) dataBuf); + JsonParserObject root = parser.getRootObject(); + JsonParserArray arr = root[PSTR(D_CMND_WEBCOLOR)].getArray(); + if (arr) { + uint32_t i = 0; + for (auto color : arr) { + if (i < COL_LAST) { + WebHexCode(i, color.getStr()); + } else { + break; + } + i++; + } + } + 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 "|" D_CMND_WEBBUTTON "|" D_CMND_CORS; + +void (* const WebCommand[])(void) PROGMEM = { +#ifdef USE_EMULATION + &CmndEmulation, +#endif +#ifdef USE_SENDMAIL + &CmndSendmail, +#endif + &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, + &CmndWebSensor, &CmndWebButton, &CmndCors }; + + + + + +#ifdef USE_EMULATION +void CmndEmulation(void) +{ +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) +#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; + } +#endif + 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, NetworkHostname(), NetworkAddress().toString().c_str()); + } else { + ResponseCmndStateText(0); + } +} + +void CmndWebPassword(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); + ResponseCmndChar(SettingsText(SET_WEBPWD)); + } else { + Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); + } +} + +void CmndWeblog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { + 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(); +} + +void CmndWebButton(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_BUTTON_TEXT)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_BUTTON1, MAX_BUTTON_TEXT); + } else { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_BUTTON1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } + ResponseCmndIdxChar(SettingsText(SET_BUTTON1 + XdrvMailbox.index -1)); + } + } +} + +void CmndCors(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_CORS, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_CORS)); +} + + + + + +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 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" +#define XDRV_02 2 + + + +#ifdef USE_MQTT_TLS + #include "WiFiClientSecureLightBearSSL.h" + BearSSL::WiFiClientSecure_light *tlsClient; +#endif +WiFiClient EspClient; + +const char kMqttCommands[] PROGMEM = "|" +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + D_CMND_MQTTFINGERPRINT "|" +#endif + D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" +#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_MQTTLOG "|" + 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 + &CmndMqttUser, &CmndMqttPassword, +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + &CmndTlsKey, +#endif + &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, + &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, &CmndMqttlog, + &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; + bool mqtt_tls = 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 + + + + +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; +} +#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++; + } +} +# 136 "/workspace/Tasmota/tasmota/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 1200" +#endif + +PubSubClient MqttClient; + +void MqttInit(void) +{ +#ifdef USE_MQTT_TLS + if ((8883 == Settings.mqtt_port) || (8884 == Settings.mqtt_port)) { + + Settings.flag4.mqtt_tls = true; + } + Mqtt.mqtt_tls = Settings.flag4.mqtt_tls; + + + String host = String(SettingsText(SET_MQTT_HOST)); + if (host.indexOf(".iot.") && host.endsWith(".amazonaws.com")) { + Settings.flag4.mqtt_no_retain = true; + } + + if (Mqtt.mqtt_tls) { + tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); + +#ifdef USE_MQTT_AWS_IOT + loadTlsDir(); + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF , 0); + } +#endif + +#ifdef USE_MQTT_TLS_CA_CERT + tlsClient->setTrustAnchor(Tasmota_TA, ARRAY_SIZE(Tasmota_TA)); +#endif + + MqttClient.setClient(*tlsClient); + } else { + MqttClient.setClient(EspClient); + } +#else + MqttClient.setClient(EspClient); +#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) +{ + + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); + if (str == topic) { + mqtt_cmnd_blocked_reset = 4; + mqtt_cmnd_blocked++; + } + } + + bool result = MqttClient.publish(topic, mqtt_data, retained); + yield(); + return result; +} + +void MqttDumpData(char* topic, char* data, uint32_t data_len) { + char dump_data[data_len +1]; + memcpy(dump_data, data, sizeof(dump_data)); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_DATA_SIZE " %d, \"%s %s\""), data_len, topic, RemoveControlCharacter(dump_data)); +} + +void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len) +{ +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("MqttDataHandler")); +#endif + + + if (data_len >= MQTT_MAX_PACKET_SIZE) { return; } + + + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1)); + if ((str == mqtt_topic) && mqtt_cmnd_blocked) { + mqtt_cmnd_blocked--; + return; + } + } + + + 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)); + + + + MqttDumpData(topic, data, data_len); + + + 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); + + 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 MqttPublishLogging(const char *mxtime) +{ + char saved_mqtt_data[strlen(mqtt_data) +1]; + memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); + + + Response_P(PSTR("%s%s"), mxtime, log_data); + char stopic[TOPSZ]; + GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); + MqttPublishLib(stopic, false); + + memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); +} + +void MqttPublish(const char* topic, bool retained) +{ +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("MqttPublish")); +#endif + + if (Settings.flag4.mqtt_no_retain) { + retained = false; + } + + char sretained[CMDSZ]; + sretained[0] = '\0'; + char slog_type[20]; + snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); + + if (Settings.flag.mqtt_enabled) { + 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) +{ + MqttPublish(topic, false); +} + +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) +{ + + + + + + + + char romram[64]; + 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); + +#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) + if ((prefix > 0) && (Settings.flag4.awsiot_shadow) && (Mqtt.connected)) { + + char *topic = SettingsText(SET_MQTT_TOPIC); + char topic2[strlen(topic)+1]; + strcpy(topic2, topic); + + char *s = topic2; + while (*s) { + if ('/' == *s) { + *s = '_'; + } + s++; + } + + snprintf_P(romram, sizeof(romram), PSTR("$aws/things/%s/shadow/update"), topic2); + + + char *mqtt_save = (char*) malloc(strlen(mqtt_data)+1); + if (!mqtt_save) { return; } + strcpy(mqtt_save, mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"state\":{\"reported\":%s}}"), mqtt_save); + free(mqtt_save); + + bool result = MqttClient.publish(romram, mqtt_data, false); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); + yield(); + } +#endif +} + +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) +{ + MqttPublishPrefixTopic_P(prefix, subtopic, false); +} + +void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) +{ + MqttPublishPrefixTopic_P(prefix, subtopic, retained); + XdrvRulesProcess(); +} + +void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic) +{ + MqttPublishPrefixTopicRulesProcess_P(prefix, subtopic, false); +} + +void MqttPublishTeleSensor(void) +{ + MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + +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); + + if (!Settings.flag4.only_json_message) { + 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(void) +{ + 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(void) +{ + return Mqtt.connect_count; +} + +void MqttDisconnected(int state) +{ + Mqtt.connected = false; + Mqtt.retry_counter = Settings.mqtt_retry; + + MqttClient.disconnect(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter); + 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(MQTT_LWT_ONLINE)); + MqttPublish(stopic, true); + + if (!Settings.flag4.only_json_message) { + + mqtt_data[0] = '\0'; + MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); + } + + GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); + MqttSubscribe(stopic); + if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + GetGroupTopic_P(stopic, PSTR("#"), real_index +i); + MqttSubscribe(stopic); + } + } + GetFallbackTopic_P(stopic, PSTR("#")); + MqttSubscribe(stopic); + } + + XdrvCall(FUNC_MQTT_SUBSCRIBE); + } + + if (Mqtt.initial_connection_state) { + if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) { + char stopic2[TOPSZ]; + 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, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); +#ifdef USE_WEBSERVER + if (Settings.webserver) { +#if LWIP_IPV6 + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str()); +#else + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str()); +#endif + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); + } +#endif + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); + if (CrashFlag()) { + CrashDump(); + } else { + ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); + } + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); + } + + MqttPublishAllPowerState(); + if (Settings.tele_period) { + tele_period = Settings.tele_period -5; + } + 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(SettingsText(SET_MQTT_HOST)) || !Settings.mqtt_port) { + Mqtt.allowed = false; + } +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + + if (Mqtt.mqtt_tls) { + if (0 == strlen(SettingsText(SET_MQTT_PWD))) { + 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(SettingsText(SET_MQTT_USER))) { + mqtt_user = SettingsText(SET_MQTT_USER); + } + if (strlen(SettingsText(SET_MQTT_PWD))) { + mqtt_pwd = SettingsText(SET_MQTT_PWD); + } + + GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); + Response_P(S_LWT_OFFLINE); + + if (MqttClient.connected()) { MqttClient.disconnect(); } +#ifdef USE_MQTT_TLS + if (Mqtt.mqtt_tls) { + tlsClient->stop(); + } else { + EspClient = WiFiClient(); + MqttClient.setClient(EspClient); + } +#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) + + if (Mqtt.mqtt_tls) { + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF , 0); + } + } +#endif + MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port); + + uint32_t mqtt_connect_time = millis(); +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + bool allow_all_fingerprints; + bool learn_fingerprint1; + bool learn_fingerprint2; + if (Mqtt.mqtt_tls) { + allow_all_fingerprints = false; + learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); + 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 + bool lwt_retain = Settings.flag4.mqtt_no_retain ? false : true; +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (Mqtt.mqtt_tls) { + if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { + + mqtt_user = nullptr; + mqtt_pwd = nullptr; + } + } +#endif + + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, mqtt_data, MQTT_CLEAN_SESSION)) { +#ifdef USE_MQTT_TLS + if (Mqtt.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 +# 721 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" + const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); + + char buf_fingerprint[64]; + ToHex_P(recv_fingerprint, 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); + + bool learned = false; + + + + + + if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20))) { + memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20); + learned = true; + } + + if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20))) { + memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); + learned = true; + } + + if (learned) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); + + SettingsSaveAll(); + } + +#endif + } +#endif + MqttConnected(); + } else { +#ifdef USE_MQTT_TLS + if (Mqtt.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) { + MqttReconnect(); + } else { + Mqtt.retry_counter--; + } + } else { + global_state.mqtt_down = 0; + } + } else { + global_state.mqtt_down = 0; + if (Mqtt.initial_connection_state) { + MqttReconnect(); + } + } +} + +bool KeyTopicActive(uint32_t key) +{ + + + key &= 1; + char key_topic[TOPSZ]; + Format(key_topic, SettingsText(SET_MQTT_BUTTON_TOPIC + key), sizeof(key_topic)); + return ((strlen(key_topic) != 0) && strcmp(key_topic, "0")); +} + + + + + +#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))) { + if (SC_DEFAULT == Shortcut()) { + memcpy_P(Settings.mqtt_fingerprint[XdrvMailbox.index -1], (1 == XdrvMailbox.index) ? default_fingerprint1 : default_fingerprint2, sizeof(default_fingerprint1)); + } else { + strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : 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 + +void CmndMqttUser(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndChar(SettingsText(SET_MQTT_USER)); +} + +void CmndMqttPassword(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data); + ResponseCmndChar(SettingsText(SET_MQTT_PWD)); + restart_flag = 2; + } else { + Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); + } +} + +void CmndMqttlog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { + Settings.mqttlog_level = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.mqttlog_level); +} + +void CmndMqttHost(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndChar(SettingsText(SET_MQTT_HOST)); +} + +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 <= MAX_STATE_TEXT)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_STATE_TXT1, MAX_STATE_TEXT); + } else { + if (XdrvMailbox.data_len > 0) { + for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { + if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; + } + SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data); + } + ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); + } + } +} + +void CmndMqttClient(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); +} + +void CmndFullTopic(void) +{ + if (XdrvMailbox.data_len > 0) { + 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, SettingsText(SET_MQTT_FULLTOPIC))) { + Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1); + restart_flag = 2; + } + } + ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC)); +} + +void CmndPrefix(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_MQTT_PREFIXES)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_MQTTPREFIX1, MAX_MQTT_PREFIXES); + } else { + if (XdrvMailbox.data_len > 0) { + MakeValidMqtt(0, XdrvMailbox.data); + SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, + (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); + } + } +} + +void CmndPublish(void) +{ + if (XdrvMailbox.data_len > 0) { + char *payload_part; + char *mqtt_part = strtok_r(XdrvMailbox.data, " ", &payload_part); + if (mqtt_part) { + char stemp1[TOPSZ]; + strlcpy(stemp1, mqtt_part, sizeof(stemp1)); + if ((payload_part != nullptr) && strlen(payload_part)) { + strlcpy(mqtt_data, payload_part, sizeof(mqtt_data)); + } else { + mqtt_data[0] = '\0'; + } + MqttPublish(stemp1, (XdrvMailbox.index == 2)); + + mqtt_data[0] = '\0'; + } + } +} + +void CmndGroupTopic(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_GROUP_TOPICS)) { + if (XdrvMailbox.data_len > 0) { + uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); + + + char stemp[MAX_GROUP_TOPICS][TOPSZ]; + uint32_t read_index = 0; + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + bool not_equal = true; + for (uint32_t j = 0; j < read_index; j++) { + if (!strcmp(SettingsText(real_index +i), stemp[j])) { + not_equal = false; + } + } + if (not_equal) { + strncpy(stemp[read_index], SettingsText(real_index +i), sizeof(stemp[read_index])); + read_index++; + } + } + } + if (0 == read_index) { + SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + } else { + uint32_t write_index = 0; + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (write_index < read_index) { + SettingsUpdateText(real_index +i, stemp[write_index]); + write_index++; + } else { + SettingsUpdateText(real_index +i, ""); + } + } + } + + restart_flag = 2; + } + ResponseCmndAll(SET_MQTT_GRP_TOPIC, MAX_GROUP_TOPICS); + } +} + +void CmndTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + 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, SettingsText(SET_MQTT_TOPIC))) { + Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + SettingsUpdateText(SET_MQTT_TOPIC, stemp1); + restart_flag = 2; + } + } + ResponseCmndChar(SettingsText(SET_MQTT_TOPIC)); +} + +void CmndButtonTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, ""); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, mqtt_topic); break; + case SC_USER: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); break; + default: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, XdrvMailbox.data); + } + } + ResponseCmndChar(SettingsText(SET_MQTT_BUTTON_TOPIC)); +} + +void CmndSwitchTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, mqtt_topic); break; + case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break; + default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data); + } + } + ResponseCmndChar(SettingsText(SET_MQTT_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; + if (Settings.flag.mqtt_power_retain) { + Settings.flag4.only_json_message = 0; + } + } + 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 = 0xFF; +const static uint8_t* tls_spi_start = (uint8_t*) 0x402FF000; +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); + + + RemoveSpace(XdrvMailbox.data); + + + 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); + } + + if (ESP.flashEraseSector(tls_spi_start_sector)) { + ESP.flashWrite(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + 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); + } +} + +#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) ")

" +#ifdef USE_MQTT_TLS + "


" +#endif + "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" + "


" + "

" 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[TOPSZ]; + + WSContentStart_P(S_CONFIGURE_MQTT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, + SettingsText(SET_MQTT_HOST), + Settings.mqtt_port, +#ifdef USE_MQTT_TLS + Mqtt.mqtt_tls ? " checked" : "", +#endif + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); + WSContentSend_P(HTTP_FORM_MQTT2, + (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), + MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void MqttSaveSettings(void) +{ + char tmp[TOPSZ]; + 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, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { + Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + } + SettingsUpdateText(SET_MQTT_TOPIC, stemp); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); + WebGetArg("mh", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); +#ifdef USE_MQTT_TLS + Mqtt.mqtt_tls = Webserver->hasArg("b3"); +#endif + WebGetArg("mc", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); +#if defined(USE_MQTT_TLS) && (defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT)) + 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"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); +#else + WebGetArg("mu", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("mp", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); + 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"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_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(PSTR("/" WEB_HANDLE_MQTT), HandleMqttConfiguration); + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kMqttCommands, MqttCommand); + break; + } + } + return result; +} +# 1 "/workspace/Tasmota/tasmota/xdrv_03_energy.ino" +# 20 "/workspace/Tasmota/tasmota/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 }; + +#ifdef SDM630_IMPORT + float import_active[3] = { NAN, NAN, NAN }; +#endif + float export_active[3] = { NAN, NAN, NAN }; + + float start_energy = 0; + float daily = 0; + float total = 0; + + 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 frequency_common = false; + bool kWhtoday_offset_init = false; + + bool voltage_available = true; + bool current_available = true; + + bool type_dc = false; + bool power_on = true; + +#ifdef USE_ENERGY_MARGIN_DETECTION + uint16_t power_history[3][3] = {{ 0 }, { 0 }, { 0 }}; + uint8_t power_steady_counter = 8; + 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; + + + +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); +} + + + +bool EnergyTariff1Active() +{ + uint8_t dst = 0; + if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { + 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(); + if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { + + return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); + } else { + + return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); + } + } 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[0])) { + + + + float export_active = 0.0; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (!isnan(Energy.export_active[i])) { + export_active += Energy.export_active[i]; + } + } + return_diff = (uint32_t)(export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; + RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(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)) && + Settings.flag3.hardware_energy_total) { + 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(); + + } + 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 (!Energy.kWhtoday_offset_init && (RtcTime.day_of_year == Settings.energy_kWhdoy)) { + Energy.kWhtoday_offset = Settings.energy_kWhtoday; + Energy.kWhtoday_offset_init = true; + } + + if (LocalTime() == Midnight()) { + Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; + + RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Energy.period -= RtcSettings.energy_kWhtoday; + Energy.kWhtoday = 0; + Energy.kWhtoday_offset = 0; + RtcSettings.energy_kWhtoday = 0; + Energy.start_energy = 0; + + + 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) +{ + if (Energy.power_steady_counter) { + Energy.power_steady_counter--; + return; + } + + bool jsonflg = false; + Response_P(PSTR("{\"" D_RSLT_MARGINS "\":{")); + + int16_t power_diff[3] = { 0 }; + for (uint32_t phase = 0; phase < Energy.phase_count; phase++) { + uint16_t active_power = (uint16_t)(Energy.active_power[phase]); + + if (Settings.energy_power_delta[phase]) { + power_diff[phase] = active_power - Energy.power_history[phase][0]; + uint16_t delta = abs(power_diff[phase]); + bool threshold_met = false; + if (delta > 0) { + if (Settings.energy_power_delta[phase] < 101) { + uint16_t min_power = (Energy.power_history[phase][0] > active_power) ? active_power : Energy.power_history[phase][0]; + if (0 == min_power) { min_power++; } + delta = (delta * 100) / min_power; + if (delta > Settings.energy_power_delta[phase]) { + threshold_met = true; + } + } else { + if (delta > (Settings.energy_power_delta[phase] -100)) { + threshold_met = true; + } + } + } + if (threshold_met) { + Energy.power_history[phase][1] = active_power; + Energy.power_history[phase][2] = active_power; + jsonflg = true; + } else { + power_diff[phase] = 0; + } + } + Energy.power_history[phase][0] = Energy.power_history[phase][1]; + Energy.power_history[phase][1] = Energy.power_history[phase][2]; + Energy.power_history[phase][2] = active_power; + } + if (jsonflg) { + char power_diff_chr[Energy.phase_count][FLOATSZ]; + for (uint32_t phase = 0; phase < Energy.phase_count; phase++) { + dtostrfd(power_diff[phase], 0, power_diff_chr[phase]); + } + char value_chr[FLOATSZ *3]; + ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_chr[0], 1)); + } + + uint16_t energy_power_u = (uint16_t)(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)) { + 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); + + bool flag; + 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\"" 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\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + } + if (jsonflg) { + ResponseJsonEndEnd(); + MqttPublishPrefixTopicRulesProcess_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}"), energy_power_u); + 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(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + } + } + } + } + } + + + if (Settings.energy_max_energy) { + 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)); + 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; + 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); + } + } +#endif +} + +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(); + MqttPublishTeleSensor(); +} +#endif + +void EnergyEverySecond(void) +{ + + if (global_update) { + if (power && !isnan(global_temperature_celsius) && (global_temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { + + char temperature[33]; + dtostrfd(global_temperature_celsius, 1, temperature); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: GlobTemp %s"), temperature); + + 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; } + if (!isnan(Energy.export_active[i])) { Energy.export_active[i] = 0; } + + data_valid--; + } + } + } + if (!data_valid) { + Energy.start_energy = 0; + + XnrgCall(FUNC_ENERGY_RESET); + } + +#ifdef USE_ENERGY_MARGIN_DETECTION + EnergyMarginCheck(); +#endif +} + + + + + +void EnergyCommandCalResponse(uint32_t nvalue) +{ + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); + ResponseCmndNumber(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.start_energy = 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; + + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); + break; + } + } + } + else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { + uint32_t values[2] = { 0 }; + uint32_t position = ParseParameters(2, values); + values[0] *= 100; + values[1] *= 100; + + switch (XdrvMailbox.index) + { + case 4: + + if (position > 0) { + RtcSettings.energy_usage.usage1_kWhtotal = values[0]; + } + if (position > 1) { + 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 > 0) { + RtcSettings.energy_usage.return1_kWhtotal = values[0]; + } + if (position > 1) { + 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; + } + } + + 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]; + 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)) { + uint32_t tariff = XdrvMailbox.index -1; + uint32_t time_type = 0; + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + while ((str != nullptr) && (time_type < 2)) { + char *q; + uint32_t value = strtol(str, &q, 10); + Settings.tariff[tariff][time_type] = value; + if (value < 24) { + Settings.tariff[tariff][time_type] *= 60; + char *minute = strtok_r(nullptr, ":", &q); + if (minute) { + value = strtol(minute, nullptr, 10); + if (value > 59) { + value = 59; + } + Settings.tariff[tariff][time_type] += value; + } + } + if (Settings.tariff[tariff][time_type] > 1439) { + Settings.tariff[tariff][time_type] = 1439; + } + str = strtok_r(nullptr, ", ", &p); + time_type++; + } + } + else if (XdrvMailbox.index == 9) { + Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; + } + Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), + XdrvMailbox.command, + 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)); +} + +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; + } + ResponseCmndNumber(Settings.energy_power_calibration); + } +} + +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; + } + ResponseCmndNumber(Settings.energy_voltage_calibration); + } +} + +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; + } + ResponseCmndNumber(Settings.energy_current_calibration); + } +} + +void CmndPowerSet(void) +{ + Energy.command_code = CMND_POWERSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_power_calibration); + } +} + +void CmndVoltageSet(void) +{ + Energy.command_code = CMND_VOLTAGESET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_voltage_calibration); + } +} + +void CmndCurrentSet(void) +{ + Energy.command_code = CMND_CURRENTSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_current_calibration); + } +} + +void CmndFrequencySet(void) +{ + Energy.command_code = CMND_FREQUENCYSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_frequency_calibration); + } +} + +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.index > 0) && (XdrvMailbox.index <= 3)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { + Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.energy_power_delta[XdrvMailbox.index -1]); + } +} + +void CmndPowerLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_min_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_power); +} + +void CmndPowerHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power); +} + +void CmndVoltageLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_min_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_voltage); +} + +void CmndVoltageHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_max_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_voltage); +} + +void CmndCurrentLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_min_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_current); +} + +void CmndCurrentHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_max_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_current); +} + +#ifdef USE_ENERGY_POWER_LIMIT +void CmndMaxPower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit); +} + +void CmndMaxPowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_hold); +} + +void CmndMaxPowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_window); +} + +void CmndSafePower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit); +} + +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; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); +} + +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; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); +} + +void CmndMaxEnergy(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_energy = XdrvMailbox.payload; + Energy.max_energy_state = 3; + } + ResponseCmndNumber(Settings.energy_max_energy); +} + +void CmndMaxEnergyStart(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { + Settings.energy_max_energy_start = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_energy_start); +} +#endif +#endif + +void EnergySnsInit(void) +{ + XnrgCall(FUNC_INIT); + + if (energy_flg) { + Energy.kWhtoday_offset = 0; + + if ((ResetReason() != REASON_DEFAULT_RST) && RtcSettingsValid()) { + Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; + Energy.kWhtoday_offset_init = true; + } + 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}"; + +#ifdef SDM630_IMPORT +const char HTTP_ENERGY_SNS4[] PROGMEM = + "{s}" D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif +#endif + +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]; +#ifdef SDM630_IMPORT + char import_active_chr[Energy.phase_count][FLOATSZ]; +#endif + char export_active_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]); +#ifdef SDM630_IMPORT + dtostrfd(Energy.import_active[i], Settings.flag2.energy_resolution, import_active_chr[i]); +#endif + dtostrfd(Energy.export_active[i], Settings.flag2.energy_resolution, export_active_chr[i]); + } + + 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); + + + bool energy_tariff = false; + char energy_usage_chr[2][FLOATSZ]; + char energy_return_chr[2][FLOATSZ]; + if (Settings.tariff[0][0] != Settings.tariff[1][0]) { + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[0]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[0]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[1]); + energy_tariff = true; + } + + 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"), + GetDateAndTime(DT_ENERGY).c_str(), + energy_total_chr); + + if (energy_tariff) { + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"), + EnergyFormatIndex(value_chr, energy_usage_chr[0], json, 2)); + } + + ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), + energy_yesterday_chr, + energy_daily_chr); + + #ifdef SDM630_IMPORT + if (!isnan(Energy.import_active[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"), + EnergyFormat(value_chr, import_active_chr[0], json)); + if (energy_tariff) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT D_CMND_TARIFF "\":%s"), + EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); + } + } +#endif + + if (!isnan(Energy.export_active[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), + EnergyFormat(value_chr, export_active_chr[0], json)); + if (energy_tariff) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"), + EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); + } + } + + if (show_energy_period) { + float 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, Energy.frequency_common)); + } + } + 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); + DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr); + + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_usage_chr[0]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_usage_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, energy_return_chr[0]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, energy_return_chr[1]); + DomoticzSensorP1SmartMeter(energy_usage_chr[0], energy_usage_chr[1], energy_return_chr[0], energy_return_chr[1], (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(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); + } + WSContentSend_PD(HTTP_SNS_POWER, 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, Energy.frequency_common)); + } + } + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr); + if (!isnan(Energy.export_active[0])) { + WSContentSend_PD(HTTP_ENERGY_SNS3, EnergyFormat(value_chr, export_active_chr[0], json)); + } +#ifdef SDM630_IMPORT + if (!isnan(Energy.import_active[0])) { + WSContentSend_PD(HTTP_ENERGY_SNS4, EnergyFormat(value_chr, import_active_chr[0], json)); + } +#endif + + XnrgCall(FUNC_WEB_SENSOR); +#endif + } +} + + + + + +bool Xdrv03(uint8_t function) +{ + bool result = false; + + if (FUNC_PRE_INIT == function) { + energy_flg = ENERGY_NONE; + XnrgCall(FUNC_PRE_INIT); + } + 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_EVERY_SECOND: + XnrgCall(FUNC_EVERY_SECOND); + 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 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" +#ifdef USE_LIGHT +# 124 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" +#define XDRV_04 4 + + +enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; + +const uint8_t LIGHT_COLOR_SIZE = 25; + +const char kLightCommands[] PROGMEM = "|" + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" 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 +#ifdef USE_LIGHT_PALETTE + "|" D_CMND_PALETTE +#endif +#ifdef USE_DGR_LIGHT_SEQUENCE + "|" D_CMND_SEQUENCE_OFFSET +#endif + "|UNDOCA" ; + +void (* const LightCommand[])(void) PROGMEM = { + &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, + &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, + &CmndWhite, &CmndChannel, &CmndHsbColor, +#ifdef USE_LIGHT_PALETTE + &CmndPalette, +#endif +#ifdef USE_DGR_LIGHT_SEQUENCE + &CmndSequenceOffset, +#endif + &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 }; + + +const uint16_t CT_MIN = 153; +const uint16_t CT_MAX = 500; + +const uint16_t CT_MIN_ALEXA = 200; +const uint16_t CT_MAX_ALEXA = 380; + + + + + + +typedef struct gamma_table_t { + uint16_t to_src; + uint16_t to_gamma; +} gamma_table_t; + +const gamma_table_t gamma_table[] = { + { 1, 1 }, + { 4, 1 }, + { 209, 13 }, + { 312, 41 }, + { 457, 106 }, + { 626, 261 }, + { 762, 450 }, + { 895, 703 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; + + +const gamma_table_t gamma_table_fast[] = { + { 384, 192 }, + { 768, 576 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; +# 262 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" +struct LIGHT { + uint32_t strip_timer_counter = 0; + power_t power = 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 random = 0; + uint8_t subtype = 0; + uint8_t device = 0; + uint8_t old_power = 1; + uint8_t wakeup_active = 0; + uint8_t fixed_color_index = 1; + uint8_t pwm_offset = 0; + uint8_t max_scheme = LS_MAX -1; + + uint32_t wakeup_start_time = 0; + + bool update = true; + bool pwm_multi_channels = false; + bool virtual_ct = false; + + bool fade_initialized = false; + bool fade_running = false; +#ifdef USE_DEVICE_GROUPS + uint8_t last_scheme = 0; + bool devgrp_no_channels_out = false; +#ifdef USE_DGR_LIGHT_SEQUENCE + uint8_t sequence_offset = 0; + uint8_t * channels_fifo; +#endif +#endif +#ifdef USE_LIGHT_PALETTE + uint8_t palette_count = 0; + uint8_t * palette; +#endif + uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; + uint16_t fade_cur_10[LST_MAX]; + uint16_t fade_end_10[LST_MAX]; + uint16_t fade_duration = 0; + uint32_t fade_start = 0; + + uint16_t pwm_min = 0; + uint16_t pwm_max = 1023; +} 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; +} +# 363 "/workspace/Tasmota/tasmota/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 = CT_MIN; + uint8_t _wc = 255; + uint8_t _ww = 0; + uint8_t _briCT = 255; + + uint8_t _color_mode = LCM_RGB; + + + + + + uint16_t _ct_min_range = CT_MIN; + uint16_t _ct_max_range = CT_MAX; + + public: + LightStateClass() { + + } + + void setSubType(uint8_t sub_type) { + _subtype = sub_type; + } +# 405 "/workspace/Tasmota/tasmota/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_RGBCW: + _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; } + } + + void getChannels(uint8_t *channels) { + getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); + } + + void getChannelsRaw(uint8_t *channels) { + channels[0] = _r; + channels[1] = _g; + channels[2] = _b; + channels[3] = _wc; + channels[4] = _ww; + } + + 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(uint32_t mode = 0) { + uint8_t bri; + switch (mode) { + case 1: + bri = getBriRGB(); + break; + case 2: + bri = getBriCT(); + break; + default: + bri = getBri(); + break; + } + return BriToDimmer(bri); + } + + inline uint16_t getCT() const { + return _ct; + } + + + uint16_t getCT10bits() const { + return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); + } + + inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { + _ct_min_range = ct_min_range; + _ct_max_range = ct_max_range; + } + + inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { + if (ct_min_range) { *ct_min_range = _ct_min_range; } + if (ct_max_range) { *ct_max_range = _ct_max_range; } + } + + + 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(); } +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); +#endif + return prev_bri; + } + + + uint8_t setBriCT(uint8_t bri_ct) { + uint8_t prev_bri = _briCT; + _briCT = bri_ct; + if (bri_ct > 0) { addCTMode(); } +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); +#endif + 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 < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); + _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 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 + } +# 629 "/workspace/Tasmota/tasmota/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 (sum <= 257) { free_range = false; } + + 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, CT_MIN, CT_MAX); + 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 setChannelsRaw(uint8_t *channels) { + _r = channels[0]; + _g = channels[1]; + _b = channels[2]; + _wc = channels[3]; + _ww = channels[4]; +} + + + + + 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); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels Actuals (%d %d %d %d %d)", + _r, _g, _b, _wc, _ww); +#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); + +}; +# 748 "/workspace/Tasmota/tasmota/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 mat3x3(const float *mat33, const float *vec3, float *res3) { + for (uint32_t i = 0; i < 3; i++) { + const float * v = vec3; + *res3 = 0.0f; + for (uint32_t j = 0; j < 3; j++) { + *res3 += *mat33++ * *v++; + } + res3++; + } +} + +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 rgb[3] = { (float)i_r, (float)i_g, (float)i_b }; + + + for (uint32_t i = 0; i < 3; i++) { + rgb[i] = rgb[i] / 255.0f; + rgb[i] = (rgb[i] > 0.04045f) ? POW((rgb[i] + 0.055f) / (1.0f + 0.055f), 2.4f) : (rgb[i] / 12.92f); + } + + + + float XYZ[3]; + static const float XYZ_factors[] = { 0.649926f, 0.103455f, 0.197109f, + 0.234327f, 0.743075f, 0.022598f, + 0.000000f, 0.053077f, 1.035763f }; + mat3x3(XYZ_factors, rgb, XYZ); + + float XYZ_sum = XYZ[0] + XYZ[1] + XYZ[2]; + x = XYZ[0] / XYZ_sum; + y = XYZ[1] / XYZ_sum; + + } + 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) +{ + float XYZ[3], rgb[3]; + 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; + XYZ[0] = x / y; + XYZ[1] = 1.0f; + XYZ[2] = z / y; + + static const float rgb_factors[] = { 3.2406f, -1.5372f, -0.4986f, + -0.9689f, 1.8758f, 0.0415f, + 0.0557f, -0.2040f, 1.0570f }; + mat3x3(rgb_factors, XYZ, rgb); + float max = (rgb[0] > rgb[1] && rgb[0] > rgb[2]) ? rgb[0] : (rgb[1] > rgb[2]) ? rgb[1] : rgb[2]; + + for (uint32_t i = 0; i < 3; i++) { + rgb[i] = rgb[i] / max; + rgb[i] = (rgb[i] <= 0.0031308f) ? 12.92f * rgb[i] : 1.055f * POW(rgb[i], (1.0f / 2.4f)) - 0.055f; + } + + int32_t irgb[3]; + for (uint32_t i = 0; i < 3; i++) { + irgb[i] = rgb[i] * 255.0f + 0.5f; + } + + if (rr) { *rr = (irgb[0] > 255 ? 255: (irgb[0] < 0 ? 0 : irgb[0])); } + if (rg) { *rg = (irgb[1] > 255 ? 255: (irgb[1] < 0 ? 0 : irgb[1])); } + if (rb) { *rb = (irgb[2] > 255 ? 255: (irgb[2] < 0 ? 0 : irgb[2])); } +} + +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; + } + + void setAlexaCTRange(bool alexa_ct_range) { + + if (alexa_ct_range) { + _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); + } else { + _state->setCTRange(CT_MIN, CT_MAX); + } + } + + 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 + if (_pwm_multi_channels) { + _state->setChannelsRaw(Settings.light_color); + } else { + + _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]); + + + + uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); + + + + if ((DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && + (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + _state->setCW(255, 0); + } + _state->setBriCT(bri); + _state->setBriRGB(bri); + _state->setColorMode(LCM_RGB); + } + + 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, uint32_t mode = 0) { + uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); + switch (mode) { + case 1: + changeBriRGB(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + break; + case 2: + changeBriCT(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + break; + default: + changeBri(bri); + break; + } + } + + void changeBri(uint8_t bri) { + _state->setBri(bri); + saveSettings(); + calcLevels(); + } + + void changeBriRGB(uint8_t bri) { + _state->setBriRGB(bri); + saveSettings(); + calcLevels(); + } + + void changeBriCT(uint8_t bri) { + _state->setBriCT(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 *current_color = nullptr) { + uint8_t r,g,b,c,w,briRGB,briCT; + if (current_color == nullptr) { current_color = Light.current_color; } + + if (_pwm_multi_channels) { + _state->getChannelsRaw(current_color); + return; + } + + _state->getActualRGBCW(&r,&g,&b,&c,&w); + briRGB = _state->getBriRGB(); + briCT = _state->getBriCT(); + + current_color[0] = current_color[1] = current_color[2] = 0; + current_color[3] = current_color[4] = 0; + switch (Light.subtype) { + case LST_NONE: + current_color[0] = 255; + break; + case LST_SINGLE: + current_color[0] = briRGB; + break; + case LST_COLDWARM: + current_color[0] = c; + current_color[1] = w; + break; + case LST_RGBW: + case LST_RGBCW: + if (LST_RGBCW == Light.subtype) { + current_color[3] = c; + current_color[4] = w; + } else { + current_color[3] = briCT; + } + + case LST_RGB: + current_color[0] = r; + current_color[1] = g; + 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->getChannelsRaw(Settings.light_color); + 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 (Light.pwm_multi_channels) { + _state->setChannelsRaw(channels); + } else 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 change8to10(uint8_t v) { + return changeUIntScale(v, 0, 255, 0, 1023); +} + +uint8_t change10to8(uint16_t v) { + return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); +} + + + + + +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (v <= to_src) { + return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (vg <= to_gamma) { + return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + + +uint16_t ledGamma10_10(uint16_t v) { + return ledGamma_internal(v, gamma_table); +} + +uint16_t ledGamma10(uint8_t v) { + return ledGamma10_10(change8to10(v)); +} + + +uint8_t ledGamma(uint8_t v) { + return change10to8(ledGamma10(v)); +} + + + +void LightPwmOffset(uint32_t offset) +{ + Light.pwm_offset = offset; +} + +bool LightModuleInit(void) +{ + light_type = LT_BASIC; + + if (Settings.flag.pwm_control) { + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (PinUsed(GPIO_PWM1, i)) { light_type++; } + } + } + + light_flg = 0; + if (XlgtCall(FUNC_MODULE_INIT)) { + + } +#ifdef ESP8266 + else if (SONOFF_BN == my_module_type) { + light_type = LT_PWM1; + } + else 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); + } + light_type = LT_PWM2; + } +#endif +#ifdef USE_PWM_DIMMER +#ifdef USE_DEVICE_GROUPS + else if (PWM_DIMMER == my_module_type) { + light_type = Settings.pwm_dimmer_cfg.pwm_count + 1; + } +#endif +#endif + + if (light_type > LT_BASIC) { + devices_present++; + } + + + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + if (Settings.flag3.pwm_multi_channels) { + if (0 == pwm_channels) { pwm_channels = 1; } + devices_present += pwm_channels - 1; + } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { + + devices_present++; + } else if ((Settings.flag4.virtual_ct) && (LST_RGBW == pwm_channels)) { + Light.virtual_ct = true; + light_type++; + } + + return (light_type > LT_BASIC); +} + + + +void LightCalcPWMRange(void) { + uint16_t pwm_min, pwm_max; + + pwm_min = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_min)); + pwm_max = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_max)); + if (Settings.light_correction) { + pwm_min = ledGamma10_10(pwm_min); + pwm_max = ledGamma10_10(pwm_max); + } + pwm_min = pwm_min > 0 ? changeUIntScale(pwm_min, 1, 1023, 1, Settings.pwm_range) : 0; + pwm_max = changeUIntScale(pwm_max, 1, 1023, 1, Settings.pwm_range); + + Light.pwm_min = pwm_min; + Light.pwm_max = pwm_max; + +} + +void LightInit(void) +{ + + if (0 == Settings.rgbwwTable[4]) { + Settings.flag4.white_blend_mode = true; + Settings.rgbwwTable[4] = 255; + } + + 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 (LST_RGBW <= Light.subtype) { + + + bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); + light_controller.setCTRGBLinked(ct_rgb_linked); + } + + if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { + + light_controller.setPWMMultiChannel(true); + Light.device = devices_present - Light.subtype + 1; + } else if (!light_controller.isCTRGBLinked()) { + + Light.device--; + } + LightCalcPWMRange(); +#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(); + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + light_controller.calcLevels(); + + 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 (PinUsed(GPIO_PWM1, i)) { +#ifdef ESP8266 + pinMode(Pin(GPIO_PWM1, i), OUTPUT); +#else + analogAttach(Pin(GPIO_PWM1, i), i); +#endif + } + } + if (PinUsed(GPIO_ARIRFRCV)) { + if (PinUsed(GPIO_ARIRFSEL)) { + pinMode(Pin(GPIO_ARIRFSEL), OUTPUT); + digitalWrite(Pin(GPIO_ARIRFSEL), 1); + } + } + } + + uint32_t max_scheme = Light.max_scheme; + 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; + if (0 == Settings.light_wakeup) { + Settings.light_wakeup = 60; + } + if (Settings.flag4.fade_at_startup) { + Light.fade_initialized = true; + } + + 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]; + + Light.update = true; + +} + +uint8_t LightGetDimmer(uint8_t dimmer) { + return light_state.getDimmer(dimmer); +} + +void LightSetDimmer(uint8_t dimmer) { + light_controller.changeDimmer(dimmer); +} + +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + light_state.getHSB(hue, sat, bri); +} + +void LightGetXY(float *X, float *Y) { + light_state.getXY(X, Y); +} + +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + light_state.HsToRgb(hue, sat, r_r, r_g, r_b); +} + + +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 (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + bri = light_state.getBri(); + } + } else { + if (device == Light.device) { + bri = light_state.getBriRGB(); + } else if (device == Light.device + 1) { + bri = light_state.getBriCT(); + } + } + 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 (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + light_controller.changeBri(bri); + } + } else { + if (device == Light.device) { + light_controller.changeBriRGB(bri); + } else if (device == Light.device + 1) { + light_controller.changeBriCT(bri); + } + } +} + +void LightColorOffset(int32_t offset) { + uint16_t hue; + uint8_t sat; + light_state.getHSB(&hue, &sat, nullptr); + hue += offset; + if (hue < 0) { hue += 359; } + if (hue > 359) { hue -= 359; } + if (!Light.pwm_multi_channels) { + light_state.setHS(hue, sat); + } else { + light_state.setHS(hue, 255); + light_state.setBri(255); + } + light_controller.calcLevels(Light.new_color); +} + +bool LightColorTempOffset(int32_t offset) { + int32_t ct = LightGetColorTemp(); + if (0 == ct) { return false; } + ct += offset; + if (ct < CT_MIN) { ct = CT_MIN; } + else if (ct > CT_MAX) { ct = CT_MAX; } + + LightSetColorTemp(ct); + return true; +} + +void LightSetColorTemp(uint16_t ct) +{ + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { + return; + } + light_controller.changeCTB(ct, light_state.getBriCT()); +} + +uint16_t LightGetColorTemp(void) +{ + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != 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) +{ + if ((0 == Settings.light_scheme) || (!Light.pwm_multi_channels)) { + 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 ResponseLightState(uint8_t append) +{ + char scolor[LIGHT_COLOR_SIZE]; + char scommand[33]; + bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); + + if (append) { + ResponseAppend_P(PSTR(",")); + } else { + Response_P(PSTR("{")); + } + if (!Light.pwm_multi_channels) { + if (unlinked) { + + ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "1\":%d" + ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "2\":%d"), + Light.device, GetStateText(Light.power & 1), light_state.getDimmer(1), + Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), light_state.getDimmer(2)); + } else { + GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), + light_state.getDimmer()); + } + + + if (Light.subtype > LST_SINGLE) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + if (LST_RGB <= Light.subtype) { + 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); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); + } + + 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 (append) { + if (Light.subtype >= LST_RGB) { + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); + } + if (Light.max_scheme > LS_MAX) { + 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(power_t channels = 0xFFFFFFFF) { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); +#endif + + if (Light.pwm_multi_channels) { + for (uint32_t i = 0; i < Light.subtype; i++) { + if (bitRead(channels, i)) { + + if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else { + + if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { + ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + #ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device + i); + #endif + } + } + } else { + if (light_controller.isCTRGBLinked()) { + 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); + } + } else { + + if (channels & 1) { + if (light_state.getBriRGB() && !(Light.power & 1)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriRGB() && (Light.power & 1)) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + + if (channels & 2) { + if (light_state.getBriCT() && !(Light.power & 2)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriCT() && (Light.power & 2)) { + ExecuteCommandPower(Light.device + 1, 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); + ResponseLightState(0); +} + +#ifdef USE_LIGHT_PALETTE +void LightSetPaletteEntry(void) +{ + uint8_t bri = light_state.getBri(); + uint8_t * palette_entry = &Light.palette[Light.wheel * LST_MAX]; + for (int i = 0; i < LST_MAX; i++) { + Light.new_color[i] = changeUIntScale(palette_entry[i], 0, 255, 0, bri); + } + light_state.setChannelsRaw(Light.new_color); + if (!Light.pwm_multi_channels) { + light_state.setCW(Light.new_color[3], Light.new_color[4], true); + if (Light.new_color[0] || Light.new_color[1] || Light.new_color[2]) light_state.addRGBMode(); + } +} +#endif + +void LightCycleColor(int8_t direction) +{ + + if (Settings.light_speed > 3) { + if (Light.strip_timer_counter % (Settings.light_speed - 2)) { return; } + } + +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count) { + if (!Light.fade_running) { + if (0 == direction) { + Light.wheel = random(Light.palette_count); + } + else { + Light.wheel += direction; + if (Light.wheel >= Light.palette_count) { + Light.wheel = 0; + if (direction < 0) Light.wheel = Light.palette_count - 1; + } + } + LightSetPaletteEntry(); + } + return; + } +#endif + + if (0 == direction) { + if (Light.random == Light.wheel) { + Light.random = random(255); + + uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : + (Light.random < Light.wheel ) ? 0 : + (Light.random > Light.wheel +128) ? 0 : 1; + Light.random = (Light.random & 0xFE) | my_dir; + + + } + + direction = (Light.random &0x01) ? 1 : -1; + } + + + if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } + Light.wheel += direction; + uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); + + + + if (!Light.pwm_multi_channels) { + uint8_t sat; + light_state.getHSB(nullptr, &sat, nullptr); + light_state.setHS(hue, sat); + } else { + light_state.setHS(hue, 255); + light_state.setBri(255); + } + light_controller.calcLevels(Light.new_color); +} + +void LightSetPower(void) +{ + + Light.old_power = Light.power; + + uint32_t mask = 1; + if (Light.pwm_multi_channels) { + mask = (1 << Light.subtype) - 1; + } else if (!light_controller.isCTRGBLinked()) { + mask = 3; + } + 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) +{ + uint16_t light_still_on = 0; + bool power_off = false; + + + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + Light.strip_timer_counter++; + + + + if (Light.power || Light.fade_running) { + if (Settings.sleep > PWM_MAX_SLEEP) { + ssleep = PWM_MAX_SLEEP; + } else { + ssleep = Settings.sleep; + } + } else { + ssleep = Settings.sleep; + } + + if (!Light.power) { + Light.strip_timer_counter = 0; + if (Settings.light_scheme >= LS_MAX) { + power_off = true; + } + } else { + switch (Settings.light_scheme) { + case LS_POWER: + light_controller.calcLevels(Light.new_color); + 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_start_time = millis(); + } + + uint32_t step_10 = ((millis() - Light.wakeup_start_time) * 1023) / (Settings.light_wakeup * 1000); + if (step_10 > 1023) { step_10 = 1023; } + uint8_t wakeup_bri = changeUIntScale(step_10, 0, 1023, 0, LightStateClass::DimmerToBri(Settings.light_dimmer)); + + if (wakeup_bri != light_state.getBri()) { + light_state.setBri(wakeup_bri); + light_controller.calcLevels(); + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = Light.current_color[i]; + } + } + if (1023 == step_10) { + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); + ResponseLightState(1); + ResponseJsonEnd(); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); + + Light.wakeup_active = 0; + Settings.light_scheme = LS_POWER; + } + } + break; + case LS_CYCLEUP: + case LS_CYCLEDN: + case LS_RANDOM: + if (LS_CYCLEUP == Settings.light_scheme) { + LightCycleColor(1); + } else if (LS_CYCLEDN == Settings.light_scheme) { + LightCycleColor(-1); + } else { + LightCycleColor(0); + } + if (Light.pwm_multi_channels) { + Light.new_color[0] = changeUIntScale(Light.new_color[0], 0, 255, 0, Settings.light_color[0]); + Light.new_color[1] = changeUIntScale(Light.new_color[1], 0, 255, 0, Settings.light_color[1]); + Light.new_color[2] = changeUIntScale(Light.new_color[2], 0, 255, 0, Settings.light_color[2]); + } + break; + default: + XlgtCall(FUNC_SET_SCHEME); + } + +#ifdef USE_DEVICE_GROUPS + if (Settings.light_scheme != Light.last_scheme) { + Light.last_scheme = Settings.light_scheme; + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); + Light.devgrp_no_channels_out = false; + } +#endif + } + + if ((Settings.light_scheme < LS_MAX) || power_off) { + + + LightApplyPower(Light.new_color, Light.power); + + + + + + + + if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { + Light.update = true; + } + if (Light.update) { +#ifdef USE_DEVICE_GROUPS + if (Light.power) LightSendDeviceGroupStatus(false); +#endif + + uint16_t cur_col_10[LST_MAX]; + Light.update = false; + bool rgbwwtable_applied = false; + + + for (uint32_t i = 0; i < LST_MAX; i++) { + Light.last_color[i] = Light.new_color[i]; + + cur_col_10[i] = change8to10(Light.new_color[i]); + } + + if (Light.pwm_multi_channels) { + calcGammaMultiChannels(cur_col_10); + } else { + calcGammaBulbs(cur_col_10); + + + + if ((LST_RGBW <= Light.subtype) && (Settings.flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) { + uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); + for (uint32_t i=0; i<3; i++) { + + uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); + cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); + } + + + uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); + uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); + if (LST_RGBW == Light.subtype) { + + cur_col_10[3] = white_10; + } else { + + uint32_t ct = light_state.getCT10bits(); + cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); + cur_col_10[3] = white_10 - cur_col_10[4]; + } + rgbwwtable_applied = true; + } else if ((Light.virtual_ct) && (0 == cur_col_10[0]+cur_col_10[1]+cur_col_10[2])) { + + uint16_t sw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[4] : cur_col_10[3]; + uint16_t hw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[3] : cur_col_10[4]; + uint32_t adjust_sw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[4] : Settings.rgbwwTable[3]); + uint32_t adjust_hw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[3] : Settings.rgbwwTable[4]); + + cur_col_10[3] = changeUIntScale(hw_white, 0, 1023, 0, adjust_hw); + cur_col_10[4] = 0; + sw_white = changeUIntScale(sw_white, 0, 1023, 0, adjust_sw); + for (uint32_t i=0; i<3; i++) { + uint32_t adjust = change8to10(Settings.rgbwwTable[i]); + cur_col_10[i] = changeUIntScale(sw_white, 0, 1023, 0, adjust); + } + rgbwwtable_applied = true; + } + } + + + if (!rgbwwtable_applied) { + for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; + } + + + uint16_t orig_col_10bits[LST_MAX]; + memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; + } + + if (!Settings.light_fade || skip_light_fade || power_off || (!Light.fade_initialized)) { + + memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); + + LightSetOutputs(cur_col_10); + Light.fade_initialized = true; + } else { + if (Light.fade_running) { + + memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); + } + memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); + Light.fade_running = true; + Light.fade_duration = 0; + Light.fade_start = 0; + + } + } + if (Light.fade_running) { + if (LightApplyFade()) { + + + + LightSetOutputs(Light.fade_cur_10); + } + } +#ifdef USE_PWM_DIMMER + + if (PWM_DIMMER == my_module_type && !Light.power && !Light.fade_running) PWMDimmerSetPower(); +#endif + } +} + +bool isChannelGammaCorrected(uint32_t channel) { + if (!Settings.light_correction) { return false; } + if (channel >= Light.subtype) { return false; } +#ifdef ESP8266 + if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { + if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } + if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } + } +#endif + return true; +} + + +bool isChannelCT(uint32_t channel) { +#ifdef ESP8266 + if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { + if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } + if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } + } +#endif + return false; +} + + +uint16_t fadeGamma(uint32_t channel, uint16_t v) { + if (isChannelGammaCorrected(channel)) { + return ledGamma_internal(v, gamma_table_fast); + } else { + return v; + } +} +uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { + if (isChannelGammaCorrected(channel)) { + return ledGammaReverse_internal(vg, gamma_table_fast); + } else { + return vg; + } +} + +bool LightApplyFade(void) { + static uint32_t last_millis = 0; + uint32_t now = millis(); + + if ((now - last_millis) <= 5) { + return false; + } + last_millis = now; + + + if (0 == Light.fade_duration) { + Light.fade_start = now; + + uint32_t distance = 0; + for (uint32_t i = 0; i < Light.subtype; i++) { + int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); + if (channel_distance < 0) { channel_distance = - channel_distance; } + if (channel_distance > distance) { distance = channel_distance; } + } + if (distance > 0) { + + + + Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; + if (Settings.save_data) { + + uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; + + if (save_data_counter < delay_seconds) { + save_data_counter = delay_seconds; + } + } + } else { + + Light.fade_running = false; + } + } + + uint16_t fade_current = now - Light.fade_start; + if (fade_current <= Light.fade_duration) { + + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.fade_cur_10[i] = fadeGamma(i, + changeUIntScale(fadeGammaReverse(i, fade_current), + 0, Light.fade_duration, + fadeGammaReverse(i, Light.fade_start_10[i]), + fadeGammaReverse(i, Light.fade_end_10[i]))); + + + + } + } else { + + + Light.fade_running = false; + Light.fade_start = 0; + Light.fade_duration = 0; + + memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); + + memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); + } + return true; +} + + + +void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { + + if (Light.pwm_multi_channels) { + + for (uint32_t i = 0; i < LST_MAX; i++) { + if (0 == bitRead(power,i)) { + new_color[i] = 0; + } + } + + + + + + } else { + if (!light_controller.isCTRGBLinked()) { + + if (0 == (power & 1)) { + new_color[0] = new_color[1] = new_color[2] = 0; + } + if (0 == (power & 2)) { + new_color[3] = new_color[4] = 0; + } + } else if (!power) { + for (uint32_t i = 0; i < LST_MAX; i++) { + new_color[i] = 0; + } + } + } +} + +void LightSetOutputs(const uint16_t *cur_col_10) { + + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { + if (PinUsed(GPIO_PWM1, i)) { + + uint16_t cur_col = cur_col_10[i + Light.pwm_offset]; + if (!isChannelCT(i)) { + cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; + } + if (!Settings.flag4.zerocross_dimmer) { + analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col); + } + } + } + } + + + + + uint8_t cur_col[LST_MAX]; + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = change10to8(cur_col_10[i]); + } + + + 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]; + 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]; + } + + char *tmp_data = XdrvMailbox.data; + char *tmp_topic = XdrvMailbox.topic; + XdrvMailbox.data = (char*)cur_col; + XdrvMailbox.topic = (char*)scale_col; + if (XlgtCall(FUNC_SET_CHANNELS)) { } + else if (XdrvCall(FUNC_SET_CHANNELS)) { } + XdrvMailbox.data = tmp_data; + XdrvMailbox.topic = tmp_topic; +} + + +void calcGammaMultiChannels(uint16_t cur_col_10[5]) { + + if (Settings.light_correction) { + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } +} + +void calcGammaBulbs(uint16_t cur_col_10[5]) { + + + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + + uint32_t cw1 = Light.subtype - 1; + uint32_t cw0 = Light.subtype - 2; + uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; + uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; + +#ifdef ESP8266 + if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { + + cur_col_10[cw1] = light_state.getCT10bits(); + + if (Settings.light_correction) { + cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); + } else { + cur_col_10[cw0] = white_bri10_1023; + } + } else +#endif + if (Settings.light_correction) { + + if (white_bri10 <= 1031) { + + uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); + + cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); + cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); + } else { + cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); + cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); + } + } + } + + if (Settings.light_correction) { + + if (LST_RGB <= Light.subtype) { + for (uint32_t i = 0; i < 3; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } + + if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { + cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); + } + } +} + +#ifdef USE_DEVICE_GROUPS +void LightSendDeviceGroupStatus(bool status) +{ + static uint8_t last_bri; + uint8_t bri = light_state.getBri(); + bool send_bri_update = (status || bri != last_bri); + if (Light.subtype > LST_SINGLE && !Light.devgrp_no_channels_out) { + static uint8_t channels[LST_MAX + 1] = { 0, 0, 0, 0, 0, 0 }; + if (status) { + light_state.getChannels(channels); + } + else { + memcpy(channels, Light.new_color, LST_MAX); + channels[LST_MAX]++; + } + SendLocalDeviceGroupMessage((send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels); + } + if (send_bri_update) { + last_bri = bri; + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, light_state.getBri()); + } +} + +void LightHandleDevGroupItem(void) +{ + static bool send_state = false; + static bool restore_power = false; + +#ifdef USE_PWM_DIMMER_REMOTE + if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return; +#endif + bool more_to_come; + uint32_t value = XdrvMailbox.payload; + switch (XdrvMailbox.command_code) { + case DGR_ITEM_EOL: + more_to_come = (XdrvMailbox.index & DGR_FLAG_MORE_TO_COME); + if (restore_power && !more_to_come) { + restore_power = false; + Light.power = Light.old_power; + } + + LightAnimate(); + + if (send_state && !more_to_come) { + light_controller.saveSettings(); + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + send_state = false; + } + break; + case DGR_ITEM_LIGHT_BRI: + if (light_state.getBri() != value) { + light_state.setBri(value); + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SCHEME: + if (Settings.light_scheme != value) { + Light.last_scheme = Settings.light_scheme = value; + Light.devgrp_no_channels_out = (value != 0); + send_state = true; + } + break; + case DGR_ITEM_LIGHT_CHANNELS: +#ifdef USE_DGR_LIGHT_SEQUENCE + { + static uint8_t last_sequence = 0; + + + + if (Light.sequence_offset) { + light_controller.changeChannels(Light.channels_fifo); + + + + int last_entry = (Light.sequence_offset - 1) * LST_MAX; + for (uint8_t sequence = (uint8_t)XdrvMailbox.data[LST_MAX]; (uint8_t)(sequence - last_sequence) > 0; last_sequence++) { + memmove(Light.channels_fifo, &Light.channels_fifo[LST_MAX], last_entry); + memcpy(&Light.channels_fifo[last_entry], XdrvMailbox.data, LST_MAX); + } + } + else { +#endif + light_controller.changeChannels((uint8_t *)XdrvMailbox.data); +#ifdef USE_DGR_LIGHT_SEQUENCE + } + } +#endif + send_state = true; + break; + case DGR_ITEM_LIGHT_FIXED_COLOR: + if (Light.subtype >= LST_COLDWARM) { + send_state = true; +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count) { + Light.wheel = value % Light.palette_count; + LightSetPaletteEntry(); + break; + } +#endif + if (Light.subtype <= LST_COLDWARM) { + value = value % (MAX_FIXED_COLD_WARM - 1) + 201; + } + else { + uint32_t max = MAX_FIXED_COLOR; + if (Light.subtype >= LST_RGB) { + max++; + if (Light.subtype >= LST_RGBCW) max += (MAX_FIXED_COLD_WARM - 2); + } + value = value % max + 1; + if (value > MAX_FIXED_COLOR) value += 200 - MAX_FIXED_COLOR; + } + Light.fixed_color_index = value; + bool save_decimal_text = Settings.flag.decimal_text; + char str[16]; + LightColorEntry(str, sprintf_P(str, PSTR("%u"), value)); + Settings.flag.decimal_text = save_decimal_text; + uint32_t old_bri = light_state.getBri(); + light_controller.changeChannels(Light.entry_color); + light_controller.changeBri(old_bri); + Settings.light_scheme = 0; + Light.devgrp_no_channels_out = false; + if (!restore_power && !Light.power) { + Light.old_power = Light.power; + Light.power = 0xff; + restore_power = true; + } + } + break; + case DGR_ITEM_LIGHT_FADE: + if (Settings.light_fade != value) { + Settings.light_fade = value; + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SPEED: + if (Settings.light_speed != value && value > 0 && value <= 40) { + Settings.light_speed = value; + send_state = true; + } + break; + case DGR_ITEM_STATUS: + SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); + LightSendDeviceGroupStatus(true); + break; + } +} +#endif + + + + + +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; +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count) value = Light.wheel; +#endif + + if (buffer[0] == '#') { + buffer++; + buffer_length--; + } + + if (Light.subtype >= LST_RGB) { + char option = (1 == buffer_length) ? buffer[0] : '\0'; + if ('+' == option) { +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count || Light.fixed_color_index < MAX_FIXED_COLOR) { +#else + if (Light.fixed_color_index < MAX_FIXED_COLOR) { +#endif + value++; + } + } + else if ('-' == option) { +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count || Light.fixed_color_index > 1) { +#else + if (Light.fixed_color_index > 1) { +#endif + value--; + } + } else { + value = atoi(buffer); + } +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count) value = value % Light.palette_count; +#endif + } + + memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); + + while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { + buffer_length--; + memcpy(&Light.entry_color, &Light.current_color, 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; + } +#ifdef USE_LIGHT_PALETTE + else if (Light.palette_count) { + value--; + Light.wheel = value; + memcpy_P(&Light.entry_color, &Light.palette[value * LST_MAX], LST_MAX); + entry_type = 1; + } +#endif + 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_RGBCW == 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) { +#ifdef USE_LIGHT_PALETTE + if (Light.palette_count && XdrvMailbox.index == 2) { + LightSetPaletteEntry(); + } + else { +#endif + uint32_t old_bri = light_state.getBri(); + + light_controller.changeChannels(Light.entry_color); + if (2 == XdrvMailbox.index) { + + light_controller.changeBri(old_bri); + } +#ifdef USE_LIGHT_PALETTE + } +#endif + 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.pwm_multi_channels) { return; } + if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(2); + } else { + ResponseCmndNumber(light_state.getDimmer(2)); + } + } +} + +void CmndChannel(void) +{ + + + + + if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { + uint32_t light_index = XdrvMailbox.index - Light.device; + power_t coldim = 0; + + + if (1 == XdrvMailbox.data_len) { + uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; + } + } + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + if (Light.pwm_multi_channels) { + coldim = 1 << light_index; + } else { + if (light_controller.isCTRGBLinked()) { + + if ((light_index < 3) && (light_controller.isCTRGBLinked())) { + Light.current_color[3] = Light.current_color[4] = 0; + } else { + Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; + } + coldim = 1; + } else { + if (light_index < 3) { coldim = 1; } + else { coldim = 2; } + } + } + light_controller.changeChannels(Light.current_color); + } + ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); + if (coldim) { + LightPreparePower(coldim); + } + } +} + +void CmndHsbColor(void) +{ + + + + + + + + if (Light.subtype >= LST_RGB) { + if (XdrvMailbox.data_len > 0) { + uint16_t c_hue; + uint8_t c_sat; + light_state.getHSB(&c_hue, &c_sat, nullptr); + uint32_t HSB[3]; + HSB[0] = c_hue; + HSB[1] = c_sat; + HSB[2] = light_state.getBriRGB(); + if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { + if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } + HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); + } else { + uint32_t paramcount = ParseParameters(3, HSB); + if (HSB[0] > 360) { HSB[0] = 360; } + for (uint32_t i = 1; i < paramcount; i++) { + if (HSB[i] > 100) { HSB[i] == 100; } + HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); + } + } + light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); + LightPreparePower(1); + } else { + ResponseLightState(0); + } + } +} + +void CmndScheme(void) +{ + + + + + + if (Light.subtype >= LST_RGB) { + uint32_t max_scheme = Light.max_scheme; + + 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)) { + uint32_t parm[2]; + if (ParseParameters(2, parm) > 1) { + Light.wheel = parm[1]; +#ifdef USE_LIGHT_PALETTE + Light.wheel--; +#endif + } + 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)) { + light_controller.changeDimmer(XdrvMailbox.payload); + } + Light.wakeup_active = 3; + Settings.light_scheme = LS_WAKEUP; + LightPowerOn(); + ResponseCmndChar(D_JSON_STARTED); +} + +void CmndColorTemperature(void) +{ + + + + + if (Light.pwm_multi_channels) { return; } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + uint32_t ct = light_state.getCT(); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; + } + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; + } + } + if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { + light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); + LightPreparePower(2); + } else { + ResponseCmndNumber(ct); + } + } +} + +void LightDimmerOffset(uint32_t index, int32_t offset) { + int32_t dimmer = light_state.getDimmer(index) + offset; + if (dimmer < 1) { dimmer = Settings.flag3.slider_dimmer_stay_on; } + if (dimmer > 100) { dimmer = 100; } + + XdrvMailbox.index = index; + XdrvMailbox.payload = dimmer; + CmndDimmer(); +} + +void CmndDimmer(void) +{ + + + + + + + + uint32_t dimmer; + if (XdrvMailbox.index == 3) { + skip_light_fade = true; + XdrvMailbox.index = 0; + } + else if (XdrvMailbox.index > 2) { + XdrvMailbox.index = 1; + } + + if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { + dimmer = light_state.getDimmer(); + } else { + dimmer = light_state.getDimmer(XdrvMailbox.index); + } + + 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)) { + if (light_controller.isCTRGBLinked()) { + + light_controller.changeDimmer(XdrvMailbox.payload); + LightPreparePower(); + } else { + if (0 != XdrvMailbox.index) { + light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + LightPreparePower(1 << (XdrvMailbox.index - 1)); + } else { + + light_controller.changeDimmer(XdrvMailbox.payload, 1); + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(); + } + } +#if defined(USE_PWM_DIMMER) && defined(USE_DEVICE_GROUPS) + uint8_t bri = light_state.getBri(); + if (bri != Settings.bri_power_on) { + Settings.bri_power_on = bri; + SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); + } +#endif + Light.update = true; + if (skip_light_fade) LightAnimate(); + } else { + ResponseCmndNumber(dimmer); + } + skip_light_fade = false; +} + +void CmndDimmerRange(void) +{ + + + if (XdrvMailbox.data_len > 0) { + uint32_t parm[2]; + parm[0] = Settings.dimmer_hw_min; + parm[1] = Settings.dimmer_hw_max; + ParseParameters(2, parm); + if (parm[0] < parm[1]) { + Settings.dimmer_hw_min = parm[0]; + Settings.dimmer_hw_max = parm[1]; + } else { + Settings.dimmer_hw_min = parm[1]; + Settings.dimmer_hw_max = parm[0]; + } + LightCalcPWMRange(); + Light.update = true; + } + Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); +} + +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; + } + LightCalcPWMRange(); + Light.update = true; + } + ResponseCmndStateText(Settings.light_correction); +} + +void CmndRgbwwTable(void) +{ + + + if ((XdrvMailbox.data_len > 0)) { + uint32_t parm[LST_RGBCW -1]; + uint32_t parmcount = ParseParameters(LST_RGBCW, parm); + for (uint32_t i = 0; i < parmcount; i++) { + Settings.rgbwwTable[i] = parm[i]; + } + Light.update = true; + } + char scolor[LIGHT_COLOR_SIZE]; + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGBCW; i++) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); + } + ResponseCmndChar(scolor); +} + +void CmndFade(void) +{ + + + + + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_fade = XdrvMailbox.payload; + break; + case 2: + Settings.light_fade ^= 1; + break; + } +#ifdef USE_DEVICE_GROUPS + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); +#endif +#ifdef USE_LIGHT + if (!Settings.light_fade) { Light.fade_running = false; } +#endif + 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 < 40)) { + XdrvMailbox.payload = Settings.light_speed + 1; + } + } + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { + Settings.light_speed = XdrvMailbox.payload; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed); +#endif + } + 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); +} + +#ifdef USE_LIGHT_PALETTE +void CmndPalette(void) +{ + uint8_t * palette_entry; + char * p; + + + if (XdrvMailbox.data_len) { + Light.wheel = 0; + Light.palette_count = 0; + if (Light.palette) { + free(Light.palette); + Light.palette = nullptr; + } + if (XdrvMailbox.data_len > 1 || XdrvMailbox.data[0] != '0') { + uint8_t palette_count = 0; + char * color = XdrvMailbox.data; + if (!(Light.palette = (uint8_t *)malloc(255 * Light.subtype))) return; + palette_entry = Light.palette; + for (;;) { + p = strchr(color, ' '); + if (p) *p = 0; + color = Trim(color); + if (*color && LightColorEntry(color, strlen(color))) { + memcpy(palette_entry, Light.entry_color, Light.subtype); + palette_entry += Light.subtype; + palette_count++; + } + if (!p) break; + color = p + 1; + } + if (!(Light.palette = (uint8_t *)realloc(Light.palette, palette_count * Light.subtype))) return; + Light.palette_count = palette_count; + } + } + + char palette_str[5 * Light.subtype * Light.palette_count + 3]; + p = palette_str; + *p++ = '['; + if (Light.palette_count) { + palette_entry = Light.palette; + for (int entry = 0; entry < Light.palette_count; entry++) { + if (Settings.flag.decimal_text) { + *p++ = '"'; + for (uint32_t i = 0; i < Light.subtype; i++) { + p += sprintf_P(p, PSTR("%d,"), *palette_entry++); + } + *(p - 1) = '"'; + } + else { + for (uint32_t i = 0; i < Light.subtype; i++) { + p += sprintf_P(p, PSTR("%02X"), *palette_entry++); + } + } + *p++ = ','; + } + p--; + } + *p++ = ']'; + *p = 0; + ResponseCmndChar(palette_str); +} +#endif + +#ifdef USE_DGR_LIGHT_SEQUENCE +void CmndSequenceOffset(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { + if (XdrvMailbox.payload != Light.sequence_offset) { + if (Light.sequence_offset) free(Light.channels_fifo); + Light.sequence_offset = XdrvMailbox.payload; + if (Light.sequence_offset) Light.channels_fifo = (uint8_t *)calloc(Light.sequence_offset, LST_MAX); + } + } + ResponseCmndNumber(Light.sequence_offset); +} +#endif + +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 (FUNC_MODULE_INIT == function) { + return LightModuleInit(); + } + else if (light_type) { + switch (function) { + case FUNC_SERIAL: + result = XlgtCall(FUNC_SERIAL); + break; + case FUNC_LOOP: + if (Light.fade_running) { + if (LightApplyFade()) { + LightSetOutputs(Light.fade_cur_10); + } + } + break; + case FUNC_EVERY_50_MSECOND: + LightAnimate(); + break; +#ifdef USE_DEVICE_GROUPS + case FUNC_DEVICE_GROUP_ITEM: + LightHandleDevGroupItem(); + break; +#endif + case FUNC_SET_POWER: + LightSetPower(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kLightCommands, LightCommand); + if (!result) { + result = XlgtCall(FUNC_COMMAND); + } + break; + case FUNC_PRE_INIT: + LightInit(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" +# 55 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" +#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) + + + + +#define XDRV_05 5 + +#include +#include + +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; + +const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; + + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrSend }; +# 81 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" +class IRRawTable { +public: + IRRawTable() : timings() {} + + int32_t getTimingForLetter(uint8_t l) const { + l = toupper(l); + if ((l < 'A') || (l > 'Z')) { return -1; } + return timings[l - 'A']; + } + uint8_t findOrAdd(uint16_t t) { + if (0 == t) { return 0; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == t) { return i + 'A'; } + if (timings[i] == 0) { timings[i] = t; break; } + } + return 0; + } + void add(uint16_t t) { + if (0 == t) { return; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == 0) { timings[i] = t; break; } + } + } + +protected: + uint16_t timings[26]; +}; + + +static const uint8_t MAX_STANDARD_IR = NEC; +const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; + + + + + +#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(void) +{ + 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[8]; + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + char hvalue[65]; + + iridx = results.decode_type; + if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { 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); + } + + IRRawTable raw_table; + bool prev_number = false; + bool ir_high = true; + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); + size_t rawlen = results.rawlen; + uint32_t i; + + for (i = 1; i < rawlen; i++) { + + uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; + uint16_t raw_dms = (raw_val_millis*2 + 5) / 10; + + uint8_t letter = raw_table.findOrAdd(raw_dms); + if (letter) { + if (!ir_high) { letter = tolower(letter); } + ResponseAppend_P(PSTR("%c"), letter); + prev_number = false; + } else { + + ResponseAppend_P(PSTR("%c%d"), ir_high ? '+' : '-', (uint32_t)raw_dms * 5); + prev_number = true; + } + ir_high = !ir_high; + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = getCorrectedRawLength(&results); + ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + +#ifdef USE_DOMOTICZ + if (iridx) { + unsigned long value = results.value | (iridx << 28); + DomoticzSensor(DZ_COUNT, value); + } +#endif + } + + irrecv->resume(); + } +} +#endif + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + + + + RemoveSpace(XdrvMailbox.data); + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { return IE_INVALID_JSON; } + + + + const char *protocol = root.getStr(PSTR(D_JSON_IR_PROTOCOL), ""); + uint16_t bits = root.getUInt(PSTR(D_JSON_IR_BITS), 0); + uint64_t data = root.getULong(PSTR(D_JSON_IR_DATA), 0); + uint16_t repeat = root.getUInt(PSTR(D_JSON_IR_REPEAT), 0); + + + 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 + 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 = IE_INVALID_JSON; + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar_P(PSTR(D_JSON_INVALID_RAWDATA)); + break; + case IE_INVALID_JSON: + ResponseCmndChar_P(PSTR(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; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) { + switch (function) { + case FUNC_PRE_INIT: + if (PinUsed(GPIO_IRSEND)) { + IrSendInit(); + } +#ifdef USE_IR_RECEIVE + if (PinUsed(GPIO_IRRECV)) { + IrReceiveInit(); + } +#endif + break; + case FUNC_EVERY_50_MSECOND: +#ifdef USE_IR_RECEIVE + if (PinUsed(GPIO_IRRECV)) { + IrReceiveCheck(); + } +#endif + irsend_active = false; + break; + case FUNC_COMMAND: + if (PinUsed(GPIO_IRSEND)) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" +# 55 "/workspace/Tasmota/tasmota/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, IE_MEMORY }; + +const char kIrRemoteCommands[] PROGMEM = "|" + D_CMND_IRHVAC "|" D_CMND_IRSEND ; + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrHvac, &CmndIrSend }; +# 85 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" +class IRRawTable { +public: + IRRawTable() : timings() {} + + int32_t getTimingForLetter(uint8_t l) const { + l = toupper(l); + if ((l < 'A') || (l > 'Z')) { return -1; } + return timings[l - 'A']; + } + uint8_t findOrAdd(uint16_t t) { + if (0 == t) { return 0; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == t) { return i + 'A'; } + if (timings[i] == 0) { timings[i] = t; break; } + } + return 0; + } + void add(uint16_t t) { + if (0 == t) { return; } + + for (uint32_t i=0; i<26; i++) { + if (timings[i] == 0) { timings[i] = t; break; } + } + } + +protected: + uint16_t timings[26]; +}; + + + + + +IRsend *irsend = nullptr; +bool irsend_active = false; + + +bool irhvac_stateful = true; +stdAc::state_t irac_prev_state; + + +enum class StateModes { SEND_ONLY, + STORE_ONLY, + SEND_STORE }; +StateModes strToStateMode(class JsonParserToken token, StateModes def); + +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(void) +{ + 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) { + JsonGeneratorObject json; + json.add(PSTR(D_JSON_IRHVAC_VENDOR), typeToString(state.protocol)); + json.add(PSTR(D_JSON_IRHVAC_MODEL), state.model); + + + if (state.mode == stdAc::opmode_t::kOff || !state.power) { + json.add(PSTR(D_JSON_IRHVAC_MODE), IRac::opmodeToString(stdAc::opmode_t::kOff)); + json.add(PSTR(D_JSON_IRHVAC_POWER), IRac::boolToString(false)); + } else { + json.add(PSTR(D_JSON_IRHVAC_MODE), IRac::opmodeToString(state.mode)); + json.add(PSTR(D_JSON_IRHVAC_POWER), IRac::boolToString(state.power)); + } + json.add(PSTR(D_JSON_IRHVAC_CELSIUS), IRac::boolToString(state.celsius)); + if (floorf(state.degrees) == state.degrees) { + json.add(PSTR(D_JSON_IRHVAC_TEMP), (int32_t) floorf(state.degrees)); + } else { + + json.addStrRaw(PSTR(D_JSON_IRHVAC_TEMP), String(state.degrees, 1).c_str()); + } + + json.add(PSTR(D_JSON_IRHVAC_FANSPEED), IRac::fanspeedToString(state.fanspeed)); + json.add(PSTR(D_JSON_IRHVAC_SWINGV), IRac::swingvToString(state.swingv)); + json.add(PSTR(D_JSON_IRHVAC_SWINGH), IRac::swinghToString(state.swingh)); + json.add(PSTR(D_JSON_IRHVAC_QUIET), IRac::boolToString(state.quiet)); + json.add(PSTR(D_JSON_IRHVAC_TURBO), IRac::boolToString(state.turbo)); + json.add(PSTR(D_JSON_IRHVAC_ECONO), IRac::boolToString(state.econo)); + json.add(PSTR(D_JSON_IRHVAC_LIGHT), IRac::boolToString(state.light)); + json.add(PSTR(D_JSON_IRHVAC_FILTER), IRac::boolToString(state.filter)); + json.add(PSTR(D_JSON_IRHVAC_CLEAN), IRac::boolToString(state.clean)); + json.add(PSTR(D_JSON_IRHVAC_BEEP), IRac::boolToString(state.beep)); + json.add(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); + + String payload = json.toString(); + 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 += "\"0x"; + json += hvalue; + json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; + Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); + json += hvalue; + json += "\""; + } else { + Uint64toHex(results.value, hvalue, 32); + json += "\"0x"; + json += hvalue; + json += "\""; + } + } + } + json += ",\"" D_JSON_IR_REPEAT "\":"; + json += results.repeat; + + stdAc::state_t new_state; + if (IRAcUtils::decodeToState(&results, &new_state, irhvac_stateful && irac_prev_state.protocol == results.decode_type ? &irac_prev_state : nullptr)) { + + json += ",\"" D_CMND_IRHVAC "\":"; + json += sendACJsonState(new_state); + irac_prev_state = new_state; + } + + return json; +} + +void IrReceiveCheck(void) +{ + decode_results results; + + if (irrecv->decode(&results)) { + uint32_t now = millis(); + + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + + IRRawTable raw_table; + bool prev_number = false; + bool ir_high = true; + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); + size_t rawlen = results.rawlen; + uint32_t i; + + for (i = 1; i < rawlen; i++) { + + uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; + uint16_t raw_dms = (raw_val_millis*2 + 5) / 10; + + uint8_t letter = raw_table.findOrAdd(raw_dms); + if (letter) { + if (!ir_high) { letter = tolower(letter); } + ResponseAppend_P(PSTR("%c"), letter); + prev_number = false; + } else { + + ResponseAppend_P(PSTR("%c%d"), ir_high ? '+' : '-', (uint32_t)raw_dms * 5); + prev_number = true; + } + ir_high = !ir_high; + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = getCorrectedRawLength(&results); + ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + } + + 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; +} + +bool strToBool(class JsonParserToken token, bool def) { + if (token.isBool() || token.isNum()) { + return token.getBool(); + } else if (token.isStr()) { + return IRac::strToBool(token.getStr()); + } else { + return def; + } +} + +StateModes strToStateMode(class JsonParserToken token, StateModes def) { + if (token.isStr()) { + const char * str = token.getStr(); + if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_SEND_ONLY))) + return StateModes::SEND_ONLY; + else if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_STORE_ONLY))) + return StateModes::STORE_ONLY; + else if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_SEND_STORE))) + return StateModes::SEND_STORE; + } + return def; +} + + +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; + + + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { 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; + + JsonParserToken val; + if (val = root[PSTR(D_JSON_IRHVAC_VENDOR)]) { state.protocol = strToDecodeType(val.getStr()); } + if (val = root[PSTR(D_JSON_IRHVAC_PROTOCOL)]) { state.protocol = strToDecodeType(val.getStr()); } + if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } + if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } + + + JsonParserToken tok_fan_speed = root[PSTR(D_JSON_IRHVAC_FANSPEED)]; + if (tok_fan_speed) { + uint32_t fan_speed = tok_fan_speed.getUInt(); + if ((fan_speed >= 1) && (fan_speed <= 5)) { + state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); + } else { + state.fanspeed = IRac::strToFanspeed(tok_fan_speed.getStr()); + } + } + + if (val = root[PSTR(D_JSON_IRHVAC_MODEL)]) { state.model = IRac::strToModel(val.getStr()); } + if (val = root[PSTR(D_JSON_IRHVAC_MODE)]) { state.mode = IRac::strToOpmode(val.getStr()); } + if (val = root[PSTR(D_JSON_IRHVAC_SWINGV)]) { state.swingv = IRac::strToSwingV(val.getStr()); } + if (val = root[PSTR(D_JSON_IRHVAC_SWINGH)]) { state.swingh = IRac::strToSwingH(val.getStr()); } + state.degrees = root.getFloat(PSTR(D_JSON_IRHVAC_TEMP), state.degrees); + + + + + StateModes stateMode = StateModes::SEND_ONLY; + if (irhvac_stateful && (val = root[PSTR(D_JSON_IRHVAC_STATE_MODE)])) { stateMode = strToStateMode(val, stateMode); } + + + state.power = strToBool(root[PSTR(D_JSON_IRHVAC_POWER)], state.power); + state.celsius = strToBool(root[PSTR(D_JSON_IRHVAC_CELSIUS)], state.celsius); + state.light = strToBool(root[PSTR(D_JSON_IRHVAC_LIGHT)], state.light); + state.beep = strToBool(root[PSTR(D_JSON_IRHVAC_BEEP)], state.beep); + state.econo = strToBool(root[PSTR(D_JSON_IRHVAC_ECONO)], state.econo); + state.filter = strToBool(root[PSTR(D_JSON_IRHVAC_FILTER)], state.filter); + state.turbo = strToBool(root[PSTR(D_JSON_IRHVAC_TURBO)], state.turbo); + state.quiet = strToBool(root[PSTR(D_JSON_IRHVAC_QUIET)], state.quiet); + state.clean = strToBool(root[PSTR(D_JSON_IRHVAC_CLEAN)], state.clean); + + + state.sleep = root.getInt(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); + + + if (stateMode == StateModes::SEND_ONLY || stateMode == StateModes::SEND_STORE) { + IRac ac(Pin(GPIO_IRSEND)); + bool success = ac.sendAc(state, irhvac_stateful && irac_prev_state.protocol == state.protocol ? &irac_prev_state : nullptr); + if (!success) { return IE_SYNTAX_IRHVAC; } + } + if (stateMode == StateModes::STORE_ONLY || stateMode == StateModes::SEND_STORE) { + irac_prev_state = state; + } + + 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) +{ + + + RemoveSpace(XdrvMailbox.data); + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { return IE_INVALID_JSON; } + + + + JsonParserToken value; + + decode_type_t protocol = decode_type_t::UNKNOWN; + value = root[PSTR(D_JSON_IRHVAC_VENDOR)]; + if (root) { protocol = strToDecodeType(value.getStr()); } + value = root[PSTR(D_JSON_IRHVAC_PROTOCOL)]; + if (root) { protocol = strToDecodeType(value.getStr()); } + if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } + + uint16_t bits = root.getUInt(PSTR(D_JSON_IR_BITS), 0); + uint16_t repeat = root.getUInt(PSTR(D_JSON_IR_REPEAT), 0); + + uint64_t data; + value = root[PSTR(D_JSON_IR_DATALSB)]; + if (root) { data = reverseBitsInBytes64(value.getULong()); } + value = root[PSTR(D_JSON_IR_DATA)]; + if (value) { data = value.getULong(); } + if (0 == bits) { return IE_SYNTAX_IRSEND; } + + + if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } + + char dvalue[32]; + char hvalue[32]; + + + + 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; +} +# 549 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" +uint32_t IrRemoteSendGC(char ** pp, uint32_t count, uint32_t repeat) { + + uint16_t GC[count+1]; + for (uint32_t i = 0; i <= count; i++) { + GC[i] = strtol(strtok_r(nullptr, ",", pp), nullptr, 0); + if (!GC[i]) { return IE_INVALID_RAWDATA; } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendGC(GC, count+1); + } + return IE_NO_ERROR; +} + + + + +uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { + if (count < 2) { return IE_INVALID_RAWDATA; } + + + char * str = strtok_r(nullptr, ",", pp); + uint16_t freq = parsqeFreq(str); + + + + uint16_t parm[count-1]; + for (uint32_t i = 0; i < count-1; i++) { + parm[i] = strtol(strtok_r(nullptr, ",", pp), nullptr, 0); + if (0 == parm[i]) { return IE_INVALID_RAWDATA; } + } + + uint16_t i = 0; + if (count < 4) { + + + + + uint16_t mark, space; + space = parm[0]; + mark = space * 2; + if (3 == count) { + if (parm[1] <= 10) { + + mark = parm[0] * parm[1]; + } else { + + mark = parm[1]; + } + } + + + uint16_t raw_array[strlen(*pp)]; + for (; **pp; *(*pp)++) { + if (**pp == '0') { + raw_array[i++] = space; + } + else if (**pp == '1') { + raw_array[i++] = mark; + } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + + irsend->sendRaw(raw_array, i, freq); + if (r < repeat) { + irsend->space(40000); + } + } + } else if (6 == count) { + + uint16_t raw_array[strlen(*pp)*2+3]; + raw_array[i++] = parm[0]; + raw_array[i++] = parm[1]; + uint32_t inter_message_32 = (parm[0] + parm[1]) * 3; + uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; + for (; **pp; *(*pp)++) { + if (**pp == '0') { + raw_array[i++] = parm[2]; + raw_array[i++] = parm[3]; + } + else if (**pp == '1') { + raw_array[i++] = parm[2]; + raw_array[i++] = parm[4]; + } + } + raw_array[i++] = parm[2]; + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + + irsend->sendRaw(raw_array, i, freq); + if (r < repeat) { + irsend->space(inter_message); + } + } + } + else { return IE_INVALID_RAWDATA; } + return IE_NO_ERROR; +} +# 656 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" +uint32_t IrRemoteParseRawCompact(char * str, uint16_t * arr, size_t arr_len) { + char *p = str; + size_t i = 0; + IRRawTable raw_table; + + for (char *p = str; *p; ) { + int32_t value = -1; + if ((arr_len > 0) && (i >= arr_len)) { return 0; } + + while ((*p == ',') || (*p == '+') || (*p == '-')) { p++; } + if ((*p >= '0') && (*p <= '9')) { + + value = strtoul(p, &p, 10); + raw_table.add(value); + } else { + value = raw_table.getTimingForLetter(*p); + p++; + } + if (value < 0) { return 0; } + if (nullptr != arr) { + arr[i] = value; + } + i++; + } + return i; +} +# 691 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" +uint32_t IrRemoteSendRawStandard(char ** pp, uint32_t count, uint32_t repeat) { + uint16_t freq = parsqeFreq(*pp); + + + + uint16_t * arr = nullptr; + if (count == 0) { + + count = IrRemoteParseRawCompact(*pp, nullptr, 0); + if (0 == count) { return IE_INVALID_RAWDATA; } + } else { + count++; + } + + arr = (uint16_t*) malloc(count * sizeof(uint16_t)); + if (nullptr == arr) { return IE_MEMORY; } + + count = IrRemoteParseRawCompact(*pp, arr, count); + + + if (0 == count) { return IE_INVALID_RAWDATA; } + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(arr, count, freq); + } + + if (nullptr != arr) { + free(arr); + } + return IE_NO_ERROR; + + + + count++; + if (count < 200) { + uint16_t raw_array[count]; + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", pp), 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, ", ", pp), nullptr, 0); + } + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + free(raw_array); + } +} + + +uint16_t parsqeFreq(char * str) { + uint16_t freq = atoi(str); + if (0 == freq) { freq = 38000; } + return freq; +} + +uint32_t IrRemoteCmndIrSendRaw(void) +{ +# 772 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" + 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 count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + + + if (strcasecmp(str, "gc") == 0) { + + + return IrRemoteSendGC(&p, count, repeat); + } else if (strcasecmp(str, "raw") == 0) { + + + + + return IrRemoteSendRawFormatted(&p, count, repeat); + } else { + + + + return IrRemoteSendRawStandard(&p, count, repeat); + } +} + +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_P(PSTR(D_JSON_INVALID_RAWDATA)); + break; + case IE_INVALID_JSON: + ResponseCmndChar_P(PSTR(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; + case IE_MEMORY: + ResponseCmndChar_P(PSTR(D_JSON_MEMORY_ERROR)); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) { + switch (function) { + case FUNC_PRE_INIT: + if (PinUsed(GPIO_IRSEND)) { + IrSendInit(); + } + if (PinUsed(GPIO_IRRECV)) { + IrReceiveInit(); + } + break; + case FUNC_EVERY_50_MSECOND: + if (PinUsed(GPIO_IRRECV)) { + IrReceiveCheck(); + } + irsend_active = false; + break; + case FUNC_COMMAND: + if (PinUsed(GPIO_IRSEND)) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_06_snfbridge.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_06_snfbridge.ino" +#ifdef USE_SONOFF_RF + + + + +#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(C2_DEVID_EFM8BB1); + 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(C2_DEVID_EFM8BB1); + 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("\"}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); +} + + + +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); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + #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("\"#%06X\""), 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(PSTR(D_JSON_START_LEARNING)); + } + else if (3 == XdrvMailbox.payload) { + Settings.rf_code[XdrvMailbox.index][0] = 0; + ResponseCmndIdxChar(PSTR(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(PSTR(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(PSTR(D_JSON_DEFAULT_SENT)); + } else { + SonoffBridgeSend(XdrvMailbox.index, 0); + ResponseCmndIdxChar(PSTR(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; + +#ifdef ESP8266 + 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: + SetSerial(19200, TS_SERIAL_8N1); + break; + } + } +#endif + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" +#ifdef USE_DOMOTICZ + +#define XDRV_07 7 + + +#define D_PRFX_DOMOTICZ "Dz" +#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" +#define D_CMND_DZSEND "Send" + +const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" + D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER "|" D_CMND_DZSEND ; + +void (* const DomoticzCommand[])(void) PROGMEM = { + &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer, &CmndDomoticzSend }; + +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 "|" D_DOMOTICZ_SHUTTER ; + +const char kDomoticzCommand[] PROGMEM = "switchlight|switchscene"; + +char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; + +int domoticz_update_timer = 0; +uint32_t domoticz_fan_debounce = 0; +bool domoticz_subscribe = false; +bool domoticz_update_flag = true; + +#ifdef USE_SHUTTER +bool domoticz_is_shutter = false; +#endif + +int DomoticzBatteryQuality(void) { + + + + + int quality = 100; + +#ifdef ESP8266 +#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 +#endif + return quality; +} + +int DomoticzRssiQuality(void) { + + + return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; +} + +#ifdef USE_SONOFF_IFAN +void MqttPublishDomoticzFanState(void) { + 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(void) { + if (domoticz_update_flag) { + MqttPublishDomoticzFanState(); + } + domoticz_update_flag = true; +} +#endif + +void MqttPublishDomoticzPowerState(uint8_t device) { + if (Settings.flag.mqtt_enabled) { + if (device < 1) { device = 1; } + if ((device > devices_present) || (device > MAX_DOMOTICZ_IDX)) { return; } + if (Settings.domoticz_relay_idx[device -1]) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) { + + } else { +#endif +#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 +#ifdef USE_SHUTTER + } +#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_SHUTTER + if (domoticz_is_shutter) + { + + break; + } +#endif +#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(DOMOTICZ_OUT_TOPIC "/#")); + MqttSubscribe(stopic); + } +} + +bool DomoticzMqttData(void) { + + + + + + + domoticz_update_flag = true; + + if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { + return false; + } + + + if (XdrvMailbox.data_len < 20) { + return true; + } + + String domoticz_data = XdrvMailbox.data; + JsonParser parser((char*)domoticz_data.c_str()); + JsonParserObject domoticz = parser.getRootObject(); + if (!domoticz) { + return true; + } + + + + uint32_t idx = domoticz.getUInt(PSTR("idx"), 0); + int16_t nvalue = domoticz.getInt(PSTR("nvalue"), -1); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); + + 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.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0; + bool isShutter = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0 & strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0; + + char stemp1[10]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == i)) { + JsonParserToken svalue_tok = domoticz[PSTR("svalue1")]; + if (!svalue_tok) { + return true; + } + uint8_t svalue = svalue_tok.getUInt(); + svalue = (2 == nvalue) ? 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 +#ifdef USE_SHUTTER + if (isShutter) { + uint8_t position = domoticz.getUInt(PSTR("svalue1"), 0); + if (nvalue != 2) { + position = (0 == nvalue) ? 0 : 100; + } + + snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); + XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); + + found = true; + } else +#endif +#ifdef USE_LIGHT + if (iscolordimmer && 10 == nvalue) { + + JsonParserObject color = domoticz[PSTR("Color")].getObject(); + + uint16_t level = nvalue = domoticz.getUInt(PSTR("svalue1"), 0); + uint16_t r = color.getUInt(PSTR("r"), 0) * level / 100; + uint16_t g = color.getUInt(PSTR("g"), 0) * level / 100; + uint16_t b = color.getUInt(PSTR("b"), 0) * level / 100; + uint16_t cw = color.getUInt(PSTR("cw"), 0) * level / 100; + uint16_t ww = color.getUInt(PSTR("ww"), 0) * level / 100; + uint16_t m = color.getUInt(PSTR("m"), 0); + uint16_t t = color.getUInt(PSTR("t"), 0); + if (2 == m) { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); + } else { + 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[PSTR("svalue1")]) { + nvalue = domoticz.getUInt(PSTR("svalue1"), 0); + } 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 +#endif + 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; +} + + + +void DomoticzSendSwitch(uint32_t type, uint32_t index, uint32_t state) { + char stemp[16]; + Response_P(PSTR("{\"command\":\"%s\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + GetTextIndexed(stemp, sizeof(stemp), type, kDomoticzCommand), index, (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); +} + +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)) { + DomoticzSendSwitch(0, (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], state); + result = true; + } + } + return result; +} +# 362 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" +void DomoticzSendData(uint32_t sensor_idx, uint32_t idx, char *data) { + if (DZ_AIRQUALITY == sensor_idx) { + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + idx, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } else { + uint8_t nvalue = 0; +#ifdef USE_SHUTTER + if (DZ_SHUTTER == sensor_idx) { + uint8_t position = atoi(data); + nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); + } +#endif + Response_P(DOMOTICZ_MESSAGE, + idx, nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } + MqttPublish(domoticz_in_topic); +} + +void DomoticzSensor(uint8_t idx, char *data) { + if (Settings.domoticz_sensor_idx[idx]) { + char dmess[128]; + + memcpy(dmess, mqtt_data, sizeof(dmess)); + DomoticzSendData(idx, Settings.domoticz_sensor_idx[idx], data); + memcpy(mqtt_data, dmess, sizeof(dmess)); + } +} + +uint8_t DomoticzHumidityState(float h) { + return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; +} + +void DomoticzSensor(uint8_t idx, uint32_t value) { + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d"), value); + DomoticzSensor(idx, data); +} + + +void DomoticzTempHumPressureSensor(float temp, float hum, float baro) { + char temperature[FLOATSZ]; + dtostrfd(temp, 2, temperature); + char humidity[FLOATSZ]; + dtostrfd(hum, 2, humidity); + + char data[32]; + if (baro > -1) { + char pressure[FLOATSZ]; + dtostrfd(baro, 2, pressure); + + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temperature, humidity, DomoticzHumidityState(hum), pressure); + DomoticzSensor(DZ_TEMP_HUM_BARO, data); + } else { + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temperature, humidity, DomoticzHumidityState(hum)); + DomoticzSensor(DZ_TEMP_HUM, 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); +} + +void CmndDomoticzSend(void) { + + + + + + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { + if (XdrvMailbox.data_len > 0) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char *data; + uint32_t index = strtoul(strtok_r(XdrvMailbox.data, ",", &data), nullptr, 10); + if ((index > 0) && (data != nullptr)) { + if (XdrvMailbox.index > 3) { + uint32_t state = strtoul(data, nullptr, 10); + DomoticzSendSwitch(XdrvMailbox.index -4, index, state); + } else { + uint32_t type = DZ_TEMP; + if (2 == XdrvMailbox.index) { type = DZ_SHUTTER; } + else if (3 == XdrvMailbox.index) { type = DZ_AIRQUALITY; } + DomoticzSendData(type, index, data); + } + } + } + } + } +} + + + + + +#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 (PinUsed(GPIO_SWT1, i)) { + 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(PSTR("/" WEB_HANDLE_DOMOTICZ), HandleDomoticzConfiguration); + break; +#endif + case FUNC_MQTT_SUBSCRIBE: + DomoticzMqttSubscribe(); +#ifdef USE_SHUTTER + if (Settings.domoticz_sensor_idx[DZ_SHUTTER]) { domoticz_is_shutter = true; } +#endif + 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 "/workspace/Tasmota/tasmota/xdrv_08_serial_bridge.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_08_serial_bridge.ino" +#ifdef USE_SERIAL_BRIDGE + + + + +#define XDRV_08 8 +#define HARDWARE_FALLBACK 2 + +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) { + bool in_byte_is_delimiter = + (((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || + ((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && + !serial_bridge_raw; + + if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && + !in_byte_is_delimiter) { + serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; + } + + if ((serial_bridge_in_byte_counter >= SERIAL_BRIDGE_BUFFER_SIZE -1) || + in_byte_is_delimiter) { + serial_bridge_polling_window = 0; + break; + } + + serial_bridge_polling_window = millis(); + } + } + + if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { + serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; + bool assume_json = (!serial_bridge_raw && (serial_bridge_buffer[0] == '{')); + + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":")); + if (assume_json) { + ResponseAppend_P(serial_bridge_buffer); + } else { + ResponseAppend_P(PSTR("\"")); + if (serial_bridge_raw) { + char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; + ResponseAppend_P(ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char))); + } else { + ResponseAppend_P(EscapeJSONString(serial_bridge_buffer).c_str()); + } + ResponseAppend_P(PSTR("\"")); + } + ResponseJsonEnd(); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); + serial_bridge_in_byte_counter = 0; + } +} + + + +void SerialBridgeInit(void) +{ + serial_bridge_active = false; + if (PinUsed(GPIO_SBR_RX) && PinUsed(GPIO_SBR_TX)) { + SerialBridgeSerial = new TasmotaSerial(Pin(GPIO_SBR_RX), Pin(GPIO_SBR_TX), HARDWARE_FALLBACK); + 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 <= 6)) { + 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 > 1) { + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, &p, 16); + SerialBridgeSerial->write(code); + size -= 2; + codes += 2; + } + } + else if (6 == XdrvMailbox.index) { + char *p; + uint8_t code; + char *values = XdrvMailbox.data; + for (char* str = strtok_r(values, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { + code = (uint8_t)atoi(str); + SerialBridgeSerial->write(code); + } + } + 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 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" +#ifdef USE_TIMERS +# 39 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" +const float pi2 = TWO_PI; +const float pi = PI; +const float RAD = DEG_TO_RAD; + + + +uint32_t JulianDate(const struct TIME_T &now) { + + + uint32_t Year = now.year; + uint32_t Month = now.month; + uint32_t Day = now.day_of_month; + uint32_t Julian; + + if (Month <= 2) { + Month += 12; + Year -= 1; + } + + + Julian = (1461 * Year + 6884416) / 4 + (153 * Month - 457) / 5 + Day; + return Julian; +} + + +float InPi(float x) +{ + return ModulusRangef(x, 0.0f, pi2); +} + + + +float TimeFormula(float *DK, uint32_t Tdays) { + float RA_Mean = 18.71506921f + (2400.0513369f / 36525.0f) * Tdays; + float M = InPi( (pi2 * 0.993133f) + (pi2 * 99.997361f / 36525.0f) * Tdays); + float L = InPi( (pi2 * 0.7859453f) + M + (6893.0f * sinf(M) + 72.0f * sinf(M+M) + (6191.2f / 36525.0f) * Tdays) * (pi2 / 1296.0e3f)); + + float eps = 0.40904f; + float cos_eps = 0.91750f; + float sin_eps = 0.39773f; + + float RA = atanf(tanf(L) * cos_eps); + if (RA < 0.0f) RA += pi; + if (L > pi) RA += pi; + RA = RA * (24.0f/pi2); + *DK = asinf(sin_eps * sinf(L)); + RA_Mean = ModulusRangef(RA_Mean, 0.0f, 24.0f); + float dRA = ModulusRangef(RA_Mean - RA, -12.0f, 12.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) +{ + const uint32_t JD2000 = 2451545; + uint32_t JD = JulianDate(RtcTime); + uint32_t Tdays = JD - JD2000; + + + float DK; + + + + + + + const float h = SUNRISE_DAWN_ANGLE * RAD; + const float sin_h = sinf(h); + + float B = Settings.latitude / (1000000.0f / RAD); + + float GeographischeLaenge = ((float)Settings.longitude)/1000000; + + + + float Zeitzone = ((float)Rtc.time_timezone) / 60; + float Zeitgleichung = TimeFormula(&DK, Tdays); + float Zeitdifferenz = acosf((sin_h - sinf(B)*sinf(DK)) / (cosf(B)*cosf(DK))) * (12.0f / 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 + (1/120.0f); + + Aufgang = ModulusRangef(Aufgang, 0.0f, 24.0f); + int AufgangStunden = (int)Aufgang; + int AufgangMinuten = (int)(60.0f * fmodf(Aufgang, 1.0f)); + float Untergang = UntergangWeltzeit + Zeitzone; + + Untergang = ModulusRangef(Untergang, 0.0f, 24.0f); + int UntergangStunden = (int)Untergang; + int UntergangMinuten = (int)(60.0f * fmodf(Untergang, 1.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]; + + if (hour[mode]==255) { + + if ((Settings.latitude > 0) != (RtcTime.month>=4 && RtcTime.month<=9)) { + duskdawn->time=2046; + } else { + duskdawn->time=2047; + } + + return; + } + + + 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]; + if (xtimer.arm) { +#ifdef USE_SUNRISE + if ((1 == xtimer.mode) || (2 == xtimer.mode)) { + ApplyTimerOffsets(&xtimer); + if (xtimer.time>=2046) { continue; } + } +#endif + 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 + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); + error = 1; + } + else { + char parm_uc[10]; + index--; + JsonParserToken val = root[PSTR(D_JSON_TIMER_ARM)]; + if (val) { + Settings.timer[index].arm = (val.getInt() != 0); + } +#ifdef USE_SUNRISE + val = root[PSTR(D_JSON_TIMER_MODE)]; + if (val) { + Settings.timer[index].mode = val.getUInt() & 0x03; + } +#endif + val = root[PSTR(D_JSON_TIMER_TIME)]; + if (val) { + uint16_t itime = 0; + int8_t value = 0; + uint8_t sign = 0; + char time_str[10]; + + strlcpy(time_str, val.getStr(), 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; + } + val = root[PSTR(D_JSON_TIMER_WINDOW)]; + if (val) { + Settings.timer[index].window = val.getUInt() & 0x0F; + TimerSetRandomWindow(index); + } + val = root[PSTR(D_JSON_TIMER_DAYS)]; + if (val) { + + Settings.timer[index].days = 0; + const char *tday = val.getStr(); + 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++; + } + } + val = root[PSTR(D_JSON_TIMER_REPEAT)]; + if (val) { + Settings.timer[index].repeat = (val.getUInt() != 0); + } + val = root[PSTR(D_JSON_TIMER_OUTPUT)]; + if (val) { + uint8_t device = (val.getUInt() -1) & 0x0F; + Settings.timer[index].device = (device < devices_present) ? device : 0; + } + val = root[PSTR(D_JSON_TIMER_ACTION)]; + if (val) { + uint8_t action = val.getUInt() & 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); + } + ResponseCmndFloat((float)(Settings.longitude) /1000000, 6); +} + +void CmndLatitude(void) +{ + if (XdrvMailbox.data_len) { + Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); + } + ResponseCmndFloat((float)(Settings.latitude) /1000000, 6); +} +#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 = + "

"; + +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_TIMER_SCRIPT1_SIZE = 106; +const char HTTP_TIMER_SCRIPT1_COMPRESSED[] PROGMEM = "\x33\xBF\xA1\x94\x7C\x3D\xE3\xDF\x3A\x83\xA3\xE1\xC4\x8F\x04\x60\x5F\x07\x5B\x9C" + "\x83\x67\x77\x4E\xA3\x51\xDE\x3D\xA6\x77\xF5\x87\xC1\x30\x31\x63\x5F\x51\xD0\x3F" + "\xBB\xA6\x4C\x26\x35\xF5\x1D\xD3\xEF\x06\x56\xE7\x1F\x67\x78\xF1\x87\x4A\x66\xCA" + "\x20\xF3\xA9\xF5\x1F\x34\xF0\x6A\x3A\x58\xC1\x8F\x84\x20\xC5\x68\x42\x1D\xDC\x3B" + "\xC7\x83\xDC"; +#define HTTP_TIMER_SCRIPT1 Decompress(HTTP_TIMER_SCRIPT1_COMPRESSED,HTTP_TIMER_SCRIPT1_SIZE).c_str() +#else +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);" + "}"; +#endif + +#ifdef USE_SUNRISE +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_TIMER_SCRIPT2_SIZE = 630; +const char HTTP_TIMER_SCRIPT2_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x43\xD4\x77\x4E\xF1\xED\x33\xBF\xA1\xA7\x50\xC3\xA8\xD4\x78" + "\x1A\x7C\x35\x78\xEE\x9F\x7B\xC3\x05\xD1\xEF\x75\x8D\x67\xC3\xD9\xF1\x0F\x61\xEF" + "\x9E\x61\x8A\x61\x9A\x31\x0F\xB3\xBC\x74\x33\xB0\x85\xB3\xC0\xC3\xE0\xCA\x3D\xE0" + "\xE8\xF7\xCF\xD1\xC6\x46\xC3\x9E\x22\x30\x46\x0F\x1A\x60\xEE\x8D\x3E\x1F\x0E\x33" + "\xBC\x7B\x4B\xD8\x77\x4E\x33\xBC\x78\x23\x51\xF0\x86\xDD\x0A\x3A\x18\x0B\x33\xE7" + "\x74\x61\xD8\x73\x99\xDE\x3C\x16\x98\x3B\xA6\xA3\xD0\xE4\x67\x78\xF6\x91\xA8\xF8" + "\x7D\x9C\x67\xD9\xDB\x23\x51\xE0\xF7\x1A\xBC\x77\x4F\xB3\xC8\x56\x02\x1E\x5E\x7C" + "\x35\x1E\x0D\x47\xC1\x87\xD1\xF4\x73\x99\x02\x9E\x10\x37\x41\x1B\x08\x3D\xDA\x60" + "\xEE\x9D\xD1\xA7\xC3\xE1\xC8\x77\x8F\xF1\xFE\x3B\xA4\x34\xF8\x7C\x39\x47\x78\xEF" + "\x1E\xD2\xF6\x1D\xD3\x90\x81\x53\x59\x3F\x0F\x87\x25\x1D\xE3\xDA\x46\xA3\xAC\xF8" + "\x72\x51\xE0\x8D\x5E\x3B\xA7\xD9\xE4\x27\xCF\xB3\xBC\x74\xF3\x09\x87\x4C\x42\xDE" + "\x11\x9B\x0F\x87\x21\xE0\xF7\x13\x0B\xCC\xF6\x82\x9D\xC3\x8C\xF0\x7B\x88\x19\x67" + "\x04\x87\xB8\x11\x38\xE6\xF6\x1D\xD1\xC7\x78\xF6\xE1\xF0\x11\x32\xD3\xC3\x3E\x61" + "\xD0\x31\x5A\x10\x84\xC2\x63\x5F\x51\x07\x82\xFA\x8F\x1A\x60\xEE\x8E\x3E\x1F\x0E" + "\x43\xBC\x40\x8F\xC0\x1D\x19\x04\xCE\x86\x7B\xED\x1D\xA1\x6D\x19\x1F\x0F\xB3\xEC" + "\xF1\xA6\x0E\xEB\x3F\x0E\x4A\x3B\xC7\xB4\x8C\x67\xCE\xEE\x9F\x0E\x4A\x3C\x16\x9E" + "\x87\xC3\x95\x67\x82\xD3\xB6\x76\xCE\xF1\xED\xC3\xA7\xD8\xDC\x33\x64\x18\xAD\x08" + "\x43\xBB\x87\x40\xAF\xD4\x08\x7A\x08\xAD\x08\x43\xBC\x78\x3D\xC7\xB8\x13\x38\x68" + "\x04\xCD\x04\x56\x88\x23\xE0\x41\xD1\xCF\x43\x95\x64\x0A\x3A\x38\x6C\xEE\xE9\xD5" + "\x87\x78\xF0\x7B\x8F\x71\xEE\x3D\xC6"; +#define HTTP_TIMER_SCRIPT2 Decompress(HTTP_TIMER_SCRIPT2_COMPRESSED,HTTP_TIMER_SCRIPT2_SIZE).c_str() +#else +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').style.visibility='';" + "if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" + "}else{" + "qs('#dr').style.visibility='hidden';" + "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" + "}" + "}"; +#endif +#endif + +#ifdef USE_UNISHOX_COMPRESSION +#ifdef USE_SUNRISE +const size_t HTTP_TIMER_SCRIPT3_SIZE = 587; +const char HTTP_TIMER_SCRIPT3_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x5E\xA3\xBA\x77\x8F\x69\x9D\xFD\x69\xD4\x11\xD4\x34\xEA\xE3" + "\xA8\x61\xD5\xE3\xC0\xD3\xE1\xC6\x78\x2F\x1F\x0E\x33\xC1\x71\xF0\xE4\x3D\x0F\x4B" + "\x87\x82\xD3\x07\x75\x8E\x3B\xA7\xDD\x9C\x67\xD9\xDE\x3A\x10\x62\x98\x66\x8C\x43" + "\xBC\x7B\x7C\x7F\x8F\x9C\x78\x3D\xDC\x7C\x39\x0F\x43\xD2\x69\x02\x1D\xFF\x82\x75" + "\xF3\x19\xF3\xBB\xA7\xC3\x8C\xF0\x5A\x7A\x1C\xF1\xE0\xB4\xED\x9D\xB3\xBC\x7B\x78" + "\xF8\x72\x1E\x87\xA1\xDD\x9C\x76\xCB\x4E\xF0\x21\xE2\x83\xE7\xD9\xDB\xD0\x4C\xC5" + "\x4F\x70\xD3\xE1\xAB\xC7\x74\xFB\xDE\x18\x2E\x8F\x7B\xAC\x6B\x3E\x1E\xCF\x88\x7B" + "\x0F\x7C\xF3\x04\x2C\x0C\xFB\x3B\xC7\x43\x3B\x08\x5B\x3C\x78\xFF\x1F\x0E\xE8\x2F" + "\xE0\xA7\xA1\xE8\x72\x91\xDE\x3C\x16\x98\x3B\xA7\xD0\x87\xE1\xC6\x77\x8F\x69\x69" + "\xF0\xD5\xE3\xBA\x7D\x9E\x42\x1C\x87\xD9\xDE\x3A\x17\x98\x4C\x3A\x62\x16\xF0\x8C" + "\xD8\x78\xD3\x07\x77\x4F\xC3\xE1\xC6\x77\x8F\x69\x78\xFF\x1F\x0E\xEE\x9E\x87\xA1" + "\xCA\xB3\xBC\x78\x3D\xC4\x08\x7A\x11\xE4\x30\x13\x30\xD3\xD0\xF4\x39\x5E\x3B\xC7" + "\x83\xDC\x4C\x2F\x33\xDB\xE3\xFC\x7C\x39\x67\xA1\xE9\x5E\x3C\x1E\xE2\x08\xF8\x77" + "\x41\x07\x0D\x15\x80\x97\x86\x9E\xB3\x9C\xCE\xF1\xDB\x23\x57\x8E\xE9\xF6\x79\x0D" + "\xD0\x4B\xB0\x77\x8F\xD1\xC6\x46\xC3\x9E\x22\x30\x46\x0F\x1A\x60\xEE\x8D\x3E\x02" + "\x16\xC2\x11\xE0\xF7\x69\x83\xBA\x77\x46\x9F\x0F\x87\x21\xDE\x3F\xC7\xF8\xEE\x90" + "\xD3\xE1\xF0\xE5\x1D\xE3\xBC\x7B\x4B\x4C\x02\x0E\x78\x27\xC1\x2F\x20\x3F\x0E\x33" + "\xBC\x7B\x4B\x4C\x1D\xD0\x8F\xC3\x8C\xEF\x1E\xD2\x08\xED\x9F\x0E\x7A\x99\xE0\xF7" + "\x1E\xE2\xF1\xFE\x3E\x04\x08\x59\xC1\xEE\xF1\xFE\x04\x3D\xE4\x68\xF8\x27\xEB\xA7" + "\x19\x11\x83\xBC\x7A\x1E\x87\x24\x3C\x10\xCA\x3D\xE0\xE8\xF7\xCF\x9E\x3C\x31\xC7" + "\x74\xFB\xA3\x8C\x81\x0F\x8A\x63\xE0\xCA\x3A\x1A\xF3\x78\xEE\x9D\xE3\xC1\xEE"; +#define HTTP_TIMER_SCRIPT3 Decompress(HTTP_TIMER_SCRIPT3_COMPRESSED,HTTP_TIMER_SCRIPT3_SIZE).c_str() +#else +const size_t HTTP_TIMER_SCRIPT3_SIZE = 424; +const char HTTP_TIMER_SCRIPT3_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x5E\xA3\xBA\x77\x8F\x69\x9D\xFD\x69\xD4\x11\xD4\x34\xEA\xE3" + "\xA8\x61\xD5\xE3\xC0\xD3\xE1\xC6\x78\x2F\x1F\x0E\x33\xC1\x71\xF0\xE4\x3D\x0F\x4B" + "\x87\x82\xD3\x07\x75\x8E\x3B\xA7\xDD\x9C\x67\xD9\xDE\x3A\x10\x62\x98\x66\x8C\x43" + "\xBC\x7B\x7C\x7F\x8F\x9C\x78\x3D\xDC\x7C\x39\x0F\x43\xD2\x69\x02\x1D\xFF\x82\x75" + "\xF3\x19\xF3\xBB\xA7\xC3\x8C\xF0\x5A\x7A\x1C\xF1\xE0\xB4\xED\x9D\xB3\xBC\x7B\x78" + "\xF8\x72\x1E\x87\xA1\xDD\x9C\x76\xCB\x4E\xF0\x21\xE2\x83\xE7\xD9\xDB\xD0\x4C\xC5" + "\x4F\x76\x98\x3B\xA7\xD0\x87\xE1\xC6\x77\x8F\x69\x69\xF0\xD5\xE3\xBA\x7D\x9E\x42" + "\x1C\x87\xD9\xDE\x3A\x17\x98\x4C\x3A\x62\x16\xF0\x8C\xD8\x78\xD3\x07\x77\x4F\xC3" + "\xE1\xC6\x77\x8F\x69\x78\xFF\x1F\x0E\xEE\x9E\x87\xA1\xCA\xB3\xBC\x78\x3D\xC5\xE3" + "\xFC\x7C\x3B\xA6\xAF\x1D\xD3\xEC\xF2\x18\x09\x98\x69\xE8\x7A\x1C\xAF\x1D\xE3\xC1" + "\xEE\x26\x17\x99\xED\xF1\xFE\x3E\x1C\xB3\xD0\xF4\xAF\x1E\x0F\x71\x04\x7C\x3B\xA0" + "\x83\x86\x8A\xC0\x4B\xC3\x4F\x59\xCE\x67\x78\xED\x91\xAB\xC7\x74\xFB\x3C\x86\xE8" + "\x25\xD8\x3B\xC7\xE8\xE3\x23\x61\xCF\x11\x18\x23\x07\x8D\x30\x77\x46\x9F\x01\x0B" + "\x61\x08\x10\x75\xB0\x41\xCA\xC6\x8F\x82\x7E\x1E\x71\x91\x18\x3B\xC7\xA1\xE8\x72" + "\x43\xC1\x0C\xA3\xDE\x0E\x8F\x7C\xF9\xE3\xC3\x1C\x77\x4F\xBA\x38\xCF\xB3\xBC\x74" + "\x23\x3B\x08\x5B\x3E\x0C\xA3\xA1\xAF\x37\x8E\xE9\xDE\x3C\x1E\xE3"; +#define HTTP_TIMER_SCRIPT3 Decompress(HTTP_TIMER_SCRIPT3_COMPRESSED,HTTP_TIMER_SCRIPT3_SIZE).c_str() +#endif +#else +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){if(l>0){l+=720;}}" + "s|=l&0x7FF;" + "}" +#endif + "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" + "pt[ct]=s;" + "eb('t0').value=pt.join();" + "}"; +#endif + +#ifdef USE_UNISHOX_COMPRESSION +#ifdef USE_SUNRISE +const size_t HTTP_TIMER_SCRIPT4_SIZE = 548; +const char HTTP_TIMER_SCRIPT4_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x59\x47\x76\x8E\xA6\x77\x8F\x69\x9D\xFD\x69\xD5\xC7\x56\x1D" + "\x43\x0E\xA3\x51\xD5\xE3\xC6\x98\x3B\xA1\xD1\xE8\x71\x23\xBC\x7B\x4B\xD4\x77\x4E" + "\xF1\xE0\xF7\x07\x47\xCA\x3C\x61\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35" + "\xF5\x78\x87\x19\x10\x61\x5F\xBC\x5D\x63\x59\xDD\x3E\xE8\x23\xEC\xEF\x1E\x0C\x67" + "\xCE\xEE\x9F\x0E\x33\xC1\x69\xE9\x87\x40\x9F\x0F\x50\xA3\xC6\x9D\xB3\xB6\x77\x8F" + "\x6E\x1E\xF6\x9E\xF9\xD3\xD4\x64\x13\x3A\x07\xEF\x15\x33\x65\x1F\x0F\x60\xEB\x0C" + "\xD0\x7B\xF8\x2F\x84\x3C\xCF\x23\xE8\xE3\xE2\x36\x1E\x03\xC0\xB3\xE0\x85\x20\xC6" + "\x75\x1D\x63\xEF\x47\x85\x51\xE7\xD9\xF1\xB6\x11\xE0\xF6\x1E\xE6\x0C\x53\x1F\x1D" + "\x81\x08\x78\x3D\x87\x8F\x1F\x06\x51\xEF\x07\x47\xBE\x78\x18\x7C\x3B\xBE\x3F\x0F" + "\xC3\x94\x8E\xF1\xFA\xB3\xC1\x31\xC7\x74\xFB\x1C\x7D\x9D\xB1\x87\x78\xE8\x18\xA6" + "\x19\xA3\x10\xF8\x72\x1E\x08\x7A\x8E\xE9\xDE\x3C\x1A\x8F\x87\x77\xC7\xE1\xF8\x72" + "\x43\xBC\x7E\x99\x1B\x08\xC1\xE3\x4C\x1D\xD3\x51\xE8\x72\x33\xBC\x7B\x48\xD4\x7C" + "\x3E\xCE\x33\xEC\xED\x91\xA8\xF0\x7B\x8D\x5E\x3B\xA7\xD9\xE4\x34\x7C\xFB\x3B\xC7" + "\x43\x3B\x08\x5B\x3E\x1A\x81\x1B\x85\xB3\x9E\x20\x41\xE1\x50\x10\x74\x43\xBA\x72" + "\x71\xDB\x2D\x3B\xC7\x78\xFD\x1C\x87\x82\x63\x8E\xE9\xF6\x3E\x7D\x9D\xBD\x04\x5D" + "\x20\x61\xE0\xF7\x69\x83\xBA\x7D\x08\x7E\x1C\x64\x08\x78\x51\xCA\xB2\x04\x1D\x34" + "\xD5\xE3\xBA\x7D\x9E\x42\x1C\x84\x08\x99\xD8\xC3\xB6\x72\x10\x21\xF0\x28\x73\xC7" + "\x78\xFD\x59\x02\x0D\xC1\x87\x21\xF6\x77\x8E\x85\xE6\x13\x0E\x98\x85\xBC\x23\x36" + "\x1F\x06\x1E\x0F\x70\x20\xE0\x67\x26\x90\x21\xE9\xFF\x38\xCF\xB2\x04\x7D\x38\x10" + "\x6D\x9C\xB8\x40\x87\x6E\xC1\x26\xD9\xEE"; +#define HTTP_TIMER_SCRIPT4 Decompress(HTTP_TIMER_SCRIPT4_COMPRESSED,HTTP_TIMER_SCRIPT4_SIZE).c_str() +#else +const size_t HTTP_TIMER_SCRIPT4_SIZE = 620; +const char HTTP_TIMER_SCRIPT4_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x59\x47\x76\x8E\xA6\x77\x8F\x69\x9D\xFD\x69\xD5\xC7\x56\x1D" + "\x43\x0E\xA3\x51\xD5\xE3\xC6\x98\x3B\xA1\xD1\xE8\x71\x23\xBC\x7B\x4B\xD4\x77\x4E" + "\xF1\xE0\xF7\x07\x47\xCA\x3C\x61\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35" + "\xF5\x78\x87\x19\x10\x61\x5F\xBC\x5D\x63\x59\xDD\x3E\xE8\x23\xEC\xEF\x1E\x0C\x67" + "\xCE\xEE\x9F\x0E\x33\xC1\x69\xE9\x87\x40\x9F\x0F\x50\xA3\xC6\x9D\xB3\xB6\x77\x8F" + "\x6E\x1E\xF6\x9E\xF9\xD3\xD4\x64\x13\x3A\x07\xEF\x15\x33\x65\x1F\x0F\x60\xEB\x0C" + "\xD0\x7B\xF8\x2F\x84\x3C\xCF\x23\xE8\xE3\xE2\x36\x1E\x03\xC0\xB3\xE0\x85\x20\xC6" + "\x75\x1D\x63\xEF\x47\x85\x51\xE7\xD9\xF1\xB6\x11\xE0\xF6\x1E\xE6\x0C\x53\x1F\x1D" + "\x81\x08\x78\x3D\x87\x8F\x1F\x06\x51\xEF\x07\x47\xBE\x78\x18\x7C\xF1\xFA\x38\xC8" + "\xD8\x73\xC4\x46\x08\xC1\xE0\xD4\x7C\x21\xB7\x42\x8E\x86\x02\xCC\xF9\xDD\x18\x76" + "\x1C\xE6\x77\x8F\x05\xA6\x0E\xE9\xA8\xF4\x39\x19\xDE\x3D\xA4\x6A\x3E\x1F\x67\x19" + "\xF6\x76\xC8\xD4\x78\x3D\xC6\xAF\x1D\xD3\xEC\xF2\x15\x87\xD9\xDE\x3A\x19\xD8\x42" + "\xD9\xF0\xD4\x78\x35\x1F\x06\x1F\x47\xD1\xCE\x64\x0A\x78\x40\xDD\x04\x8C\x20\xEE" + "\xF8\xFC\x3F\x0E\x48\x77\x8F\xD3\x23\x61\x18\x05\x4C\x38\x7C\x11\xB0\xE0\x45\xE2" + "\x8C\xE7\x88\x10\x78\x9C\x18\x7C\x3B\xBE\x3F\x0F\xC3\xBA\x72\x71\xDB\x2D\x3B\xC7" + "\x78\xFD\x1C\x87\x82\x63\x8E\xE9\xF6\x3E\x7D\x9D\xBD\x3B\xC7\x40\xC5\x30\xCD\x18" + "\x87\xC1\x87\x83\xDD\xA6\x0E\xE9\xF4\x21\xF8\x71\x90\x21\xE1\x47\x2A\x2B\xC8\x10" + "\x74\xD3\x57\x8E\xE9\xF6\x79\x08\x72\x10\x22\x67\x63\x0E\xD9\xC8\x78\x20\x42\xBC" + "\x73\xC7\x78\xFD\x59\x02\x0D\xC1\x87\x21\xF6\x77\x8E\x85\xE6\x13\x0E\x98\x85\xBC" + "\x23\x36\x1F\x06\x1E\x0F\x70\x20\xE0\x67\x26\x90\x21\xE9\xFF\x38\xCF\xB2\x04\x7D" + "\x38\x10\x6D\x9C\xB8\x40\x87\x6E\xC1\x26\xD9\xEE"; +#define HTTP_TIMER_SCRIPT4 Decompress(HTTP_TIMER_SCRIPT4_COMPRESSED,HTTP_TIMER_SCRIPT4_SIZE).c_str() +#endif +#else +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;" + "}"; +#endif + +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+=\" \"}" + + "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 " " + "
" + "



" + "



" + "

" + "
" + " " + "" + "

" + "
"; +#ifdef USE_SUNRISE +const char HTTP_FORM_TIMER3[] PROGMEM = + "
" + "
" + "
" + "
" + "
" + "

" + "" + " "; +#else +const char HTTP_FORM_TIMER3[] PROGMEM = + "" D_TIMER_TIME " "; +#endif + +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_FORM_TIMER4_SIZE = 249; +const char HTTP_FORM_TIMER4_COMPRESSED[] PROGMEM = "\x3D\x3C\x32\xF8\xFC\x3D\x3C\xC2\x61\xD2\xF5\x19\x04\xCF\x87\xD8\xFE\x89\x42\x8F" + "\x33\x9C\xC8\x61\xB0\xF0\x7D\xAD\x10\xF8\x7D\x8A\xC3\xEC\xFC\x3D\x0E\xC0\x41\xC0" + "\x4F\xC3\xD0\xEC\xF0\xCB\xE3\xF0\xFD\x70\xEF\x0C\x3C\x1F\x5E\x04\x18\x80\xC0\x72" + "\x41\xBA\x09\xD9\x23\x1B\xE1\x87\x83\xD0\x71\xF8\x76\xCE\xC3\xAC\xF4\x3B\x07\x02" + "\x16\x68\x0C\x0B\x2C\x1F\x04\xDC\xB0\xF4\x3B\x04\xD3\x33\xF0\xF4\x1D\xF3\xF0\xF4" + "\x13\x4C\xD6\x88\x7C\x3E\xC4\xF1\xF6\xBA\xC6\xB3\xE1\xF6\x27\x8F\xB0\x42\xBA"; +#define HTTP_FORM_TIMER4 Decompress(HTTP_FORM_TIMER4_COMPRESSED,HTTP_FORM_TIMER4_SIZE).c_str() +#else +const char HTTP_FORM_TIMER4[] PROGMEM = + "" + " " D_HOUR_MINUTE_SEPARATOR " " + "" + " +/- " + "" + "

" + "
"; +#endif + +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 +#ifdef USE_UNISHOX_COMPRESSION + WSContentSend_P(HTTP_FORM_TIMER4,D_HOUR_MINUTE_SEPARATOR); +#else + WSContentSend_P(HTTP_FORM_TIMER4); +#endif + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void TimerSaveSettings(void) +{ + char tmp[MAX_TIMERS *12]; + char message[LOGSZ]; + Timer timer; + + Settings.flag3.timers_enable = Webserver->hasArg("e0"); + WebGetArg("t0", tmp, sizeof(tmp)); + char *p = tmp; + snprintf_P(message, sizeof(message), 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(message, sizeof(message), PSTR("%s,0x%08X"), message, Settings.timer[i].data); + } + AddLog_P(LOG_LEVEL_DEBUG, message); +} +#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(PSTR("/" 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 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +#ifdef USE_RULES +#ifndef USE_SCRIPT +# 68 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +#define XDRV_10 10 + +#include + +#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 = "+-*/%^\0"; + #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; + uint16_t mems_event = 0; + bool teleperiod = false; + bool busy = 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>16) +#error MAX_RULE_MEMS is bigger than 16 +#endif +# 214 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +#ifdef USE_UNISHOX_COMPRESSION + +String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; + +#endif + + +inline bool IsRuleUncompressed(uint32_t idx) { +#ifdef USE_UNISHOX_COMPRESSION + return Settings.rules[idx][0] ? true : false; +#else + return true; +#endif +} + + +inline bool IsRuleEmpty(uint32_t idx) { +#ifdef USE_UNISHOX_COMPRESSION + return (Settings.rules[idx][0] == 0) && (Settings.rules[idx][1] == 0) ? true : false; +#else + return (Settings.rules[idx][0] == 0) ? true : false; +#endif +} + + +size_t GetRuleLen(uint32_t idx) { + + if (IsRuleUncompressed(idx)) { + return strlen(Settings.rules[idx]); + } else { + return Settings.rules[idx][1] * 8; + } +} + + +size_t GetRuleLenStorage(uint32_t idx) { +#ifdef USE_UNISHOX_COMPRESSION + if (Settings.rules[idx][0] || !Settings.rules[idx][1]) { + return 1 + strlen(Settings.rules[idx]); + } else { + return 2 + strlen(&Settings.rules[idx][1]); + } +#else + return 1 + strlen(Settings.rules[idx]); +#endif +} + +#ifdef USE_UNISHOX_COMPRESSION + +void GetRule_decompress(String &rule, const char *rule_head) { + size_t buf_len = 1 + *rule_head * 8; + rule_head++; + + rule = Decompress(rule_head, buf_len); +} +#endif + + + + + +String GetRule(uint32_t idx) { + if (IsRuleUncompressed(idx)) { + return String(Settings.rules[idx]); + } else { +#ifdef USE_UNISHOX_COMPRESSION + + String rule(""); + if (Settings.rules[idx][1] == 0) { return rule; } + + + if (0 == k_rules[idx].length() ) { + GetRule_decompress(rule, &Settings.rules[idx][1]); + if (!Settings.flag4.compress_rules_cpu) { + k_rules[idx] = rule; + } + } else { + + rule = k_rules[idx]; + } + return rule; +#endif + } + return ""; +} + +#ifdef USE_UNISHOX_COMPRESSION + + +int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, size_t out_len) { + int32_t len_compressed; + len_compressed = compressor.unishox_compress(in, in_len, out, out_len); + + if (len_compressed >= 0) { + + k_rules[idx] = (const char*) nullptr; + if ((!Settings.flag4.compress_rules_cpu) && out) { + + k_rules[idx] = in; + } + } + return len_compressed; +} +#endif + + + + +int32_t SetRule(uint32_t idx, const char *content, bool append = false) { + if (nullptr == content) { content = ""; } + size_t len_in = strlen(content); + bool needsCompress = false; + size_t offset = 0; + + if (len_in >= MAX_RULE_SIZE) { + needsCompress = true; + } + if (append) { + if (IsRuleUncompressed(idx) || IsRuleEmpty(idx)) { + offset = strlen(Settings.rules[idx]); + if (len_in + offset >= MAX_RULE_SIZE) { + needsCompress = true; + } + } else { + needsCompress = true; + } + } + + if (!needsCompress) { + strlcpy(Settings.rules[idx] + offset, content, sizeof(Settings.rules[idx])); + if (0 == Settings.rules[idx][0]) { + Settings.rules[idx][1] = 0; + } + +#ifdef USE_UNISHOX_COMPRESSION + if (0 != len_in + offset) { + + int32_t len_compressed, len_uncompressed; + + len_uncompressed = strlen(Settings.rules[idx]); + len_compressed = compressor.unishox_compress(Settings.rules[idx], len_uncompressed, nullptr , MAX_RULE_SIZE + 8); + AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Stored uncompressed, would compress from %d to %d (-%d%%)"), len_uncompressed, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_uncompressed, 0, 100)); + } + +#endif + + return len_in + offset; + } else { +#ifdef USE_UNISHOX_COMPRESSION + int32_t len_compressed; + + char *buf_out = (char*) malloc(MAX_RULE_SIZE + 8); + if (!buf_out) { return -1; } + + + if (append) { + String content_append = GetRule(idx); + content_append += content; + len_in = content_append.length(); + len_compressed = SetRule_compress(idx, content_append.c_str(), len_in, buf_out, MAX_RULE_SIZE + 8); + } else { + len_compressed = SetRule_compress(idx, content, len_in, buf_out, MAX_RULE_SIZE + 8); + } + + if ((len_compressed >= 0) && (len_compressed < MAX_RULE_SIZE - 2)) { + + Settings.rules[idx][0] = 0; + Settings.rules[idx][1] = (len_in + 7) / 8; + memcpy(&Settings.rules[idx][2], buf_out, len_compressed); + Settings.rules[idx][len_compressed + 2] = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Compressed from %d to %d (-%d%%)"), len_in, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_in, 0, 100)); + + + } else { + len_compressed = -1; + + k_rules[idx] = (const char *) nullptr; + } + free(buf_out); + return len_compressed; + +#else + return -1; +#endif + } + +} + + + +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all_rules) +{ + + + + + bool match = false; + char stemp[10]; + + + String rule_expr = rule; + if (Rules.teleperiod) { + int ppos = rule_expr.indexOf("TELE-"); + if (ppos == -1) { return false; } + rule_expr = rule.substring(5); + } + + String rule_name, rule_param; + int8_t compareOperator = parseCompareExpression(rule_expr, rule_name, rule_param); + + + + + + + char rule_svalue[80] = { 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 = SettingsText(SET_MEM1 + i); + break; + } + } + if (rule_param.startsWith(F("%TIME%"))) { + rule_param = String(MinutesPastMidnight()); + } + if (rule_param.startsWith(F("%UPTIME%"))) { + rule_param = String(MinutesUptime()); + } + if (rule_param.startsWith(F("%TIMESTAMP%"))) { + rule_param = GetDateAndTime(DT_LOCAL).c_str(); + } +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + if (rule_param.startsWith(F("%SUNRISE%"))) { + rule_param = String(SunMinutes(0)); + } + if (rule_param.startsWith(F("%SUNSET%"))) { + rule_param = String(SunMinutes(1)); + } +#endif +# 478 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" + 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); + } + } + + + int pos; + int rule_name_idx = 0; + if ((pos = rule_name.indexOf("[")) > 0) { + 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); + } + + String buf = event; + + + + JsonParser parser((char*)buf.c_str()); + JsonParserObject obj = parser.getRootObject(); + if (!obj) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: No valid JSON (%s)"), buf.c_str()); + return false; + } + String subtype; + uint32_t i = 0; + while ((pos = rule_name.indexOf("#")) > 0) { + subtype = rule_name.substring(0, pos); + obj = obj[subtype.c_str()].getObject(); + if (!obj) { return false; } + + rule_name = rule_name.substring(pos +1); + if (i++ > 10) { return false; } + + yield(); + } + + JsonParserToken val = obj[rule_name.c_str()]; + if (!val) { return false; } + const char* str_value; + if (rule_name_idx) { + if (val.isArray()) { + str_value = (val.getArray())[rule_name_idx -1].getStr(); + } else { + str_value = val.getStr(); + } + } else { + str_value = val.getStr(); + } + + + + + 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 (stop_all_rules) { match = false; } + + + + 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; +} +# 614 "/workspace/Tasmota/tasmota/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; +} + +void RulesVarReplace(String &commands, const String &sfind, const String &replace) +{ + + + + char *find = (char*)sfind.c_str(); + uint32_t flen = strlen(find); + + String ucommand = commands; + ucommand.toUpperCase(); + char *read_from = (char*)ucommand.c_str(); + char *write_to = (char*)commands.c_str(); + char *found_at; + while ((found_at = strstr(read_from, find)) != nullptr) { + write_to += (found_at - read_from); + memmove_P(write_to, find, flen); + write_to += flen; + read_from = found_at + flen; + } + + commands.replace(find, replace); +} + + + +bool RuleSetProcess(uint8_t rule_set, String &event_saved) +{ + bool serviced = false; + char stemp[10]; + + delay(0); + + + + String rules = GetRule(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); + + String commands = rules.substring(pevt +4, plen); + Rules.event_value = ""; + String event = event_saved; + + + + if (RulesRuleMatch(rule_set, event, event_trigger, stop_all_rules)) { + if (plen == plen2) { stop_all_rules = true; } + commands.trim(); + String ucommand = commands; + ucommand.toUpperCase(); + + + + if ((ucommand.indexOf("IF ") == -1) && + (ucommand.indexOf("EVENT ") != -1) && + (ucommand.indexOf("BACKLOG ") == -1)) { + commands = "backlog " + commands; + } + + RulesVarReplace(commands, 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); + RulesVarReplace(commands, stemp, rules_vars[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); + RulesVarReplace(commands, stemp, SettingsText(SET_MEM1 +i)); + } + RulesVarReplace(commands, F("%TIME%"), String(MinutesPastMidnight())); + RulesVarReplace(commands, F("%UTCTIME%"), String(UtcTime())); + RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime())); + RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL)); + RulesVarReplace(commands, F("%TOPIC%"), mqtt_topic); + snprintf_P(stemp, sizeof(stemp), PSTR("%06X"), ESP_getChipId()); + RulesVarReplace(commands, F("%DEVICEID%"), stemp); + String mac_address = WiFi.macAddress(); + mac_address.replace(":", ""); + RulesVarReplace(commands, F("%MACADDR%"), mac_address); +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0))); + RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1))); +#endif +#ifdef USE_ZIGBEE + snprintf_P(stemp, sizeof(stemp), PSTR("0x%04X"), Z_GetLastDevice()); + RulesVarReplace(commands, F("%ZBDEVICE%"), String(stemp)); + RulesVarReplace(commands, F("%ZBGROUP%"), String(Z_GetLastGroup())); + RulesVarReplace(commands, F("%ZBCLUSTER%"), String(Z_GetLastCluster())); + RulesVarReplace(commands, F("%ZBENDPOINT%"), String(Z_GetLastEndpoint())); +#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; + } + plen += 6; + Rules.trigger_count[rule_set]++; + } + return serviced; +} + + + +bool RulesProcessEvent(char *json_event) +{ + if (Rules.busy) { return false; } + + Rules.busy = true; + 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 (GetRuleLen(i) && bitRead(Settings.rule_enabled, i)) { + if (RuleSetProcess(i, event_saved)) { serviced = true; } + } + } + + Rules.busy = false; + + return serviced; +} + +bool RulesProcess(void) +{ + return RulesProcessEvent(mqtt_data); +} + +void RulesInit(void) +{ + + bitWrite(Settings.rule_once, 7, 0); + + bitWrite(Settings.rule_once, 6, 0); + + rules_flag.data = 0; + for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { + if (0 == GetRuleLen(i)) { + bitWrite(Settings.rule_enabled, i, 0); + bitWrite(Settings.rule_once, i, 0); + } + } + Rules.teleperiod = false; +} + +void RulesEvery50ms(void) +{ + if (Settings.rule_enabled && !Rules.busy) { + 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 (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) { +#else + if (PinUsed(GPIO_SWT1, i)) { +#endif + snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (SwitchState(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, SettingsText(SET_MEM1 +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\":{\"Init\":1}}"), sizeof(json_event)); break; + case 1: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; + case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; + case 3: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; + case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; + case 5: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; + case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; + case 7: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; + case 8: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break; +#ifdef USE_SHUTTER + case 9: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event)); break; + case 10: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event)); break; +#endif + } + if (json_event[0]) { + RulesProcessEvent(json_event); + break; + } + } + mask <<= 1; + } + } + } +} + +uint8_t rules_xsns_index = 0; + +void RulesEvery100ms(void) +{ + if (Settings.rule_enabled && !Rules.busy && (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(); + RulesProcessEvent(mqtt_data); + } + } +} + +void RulesEverySecond(void) +{ + if (Settings.rule_enabled && !Rules.busy) { + 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 && !Rules.busy) { + 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 +# 1021 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +bool RulesMqttData(void) +{ + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { + return false; + } + bool serviced = 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 { + JsonParser parser((char*)sData.c_str()); + JsonParserObject jsonData = parser.getRootObject(); + + String key1 = event_item.Key; + String key2; + if (!jsonData) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + JsonParserToken value_tok = jsonData[key1.c_str()].getObject()[key2.c_str()]; + if (!value_tok) break; + value = value_tok.getStr(); + + + } else { + JsonParserToken value_tok = jsonData[key1.c_str()]; + if (!value_tok) break; + value = value_tok.getStr(); + + + } + } + value.trim(); + + snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); + } + } + return serviced; +} +# 1090 "/workspace/Tasmota/tasmota/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()); +} +# 1170 "/workspace/Tasmota/tasmota/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 +# 1212 "/workspace/Tasmota/tasmota/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; + } +} +# 1251 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +bool findNextNumber(char * &pNumber, float &value) +{ + bool bSucceed = false; + String sNumber = ""; + if (*pNumber == '-') { + sNumber = "-"; + pNumber++; + } + while (*pNumber) { + if (isdigit(*pNumber) || (*pNumber == '.')) { + sNumber += *pNumber; + pNumber++; + } else { + break; + } + } + if (sNumber.length() > 0) { + value = CharToFloat(sNumber.c_str()); + bSucceed = true; + } + return bSucceed; +} +# 1287 "/workspace/Tasmota/tasmota/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(SettingsText(SET_MEM1 + 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 +# 1335 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" + } else { + succeed = false; + } + + return succeed; +} +# 1359 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +bool findNextObjectValue(char * &pointer, float &value) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { + pointer++; + continue; + } + if (isdigit(*pointer) || (*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 - 1); + pointer = closureBracket + 1; + bSucceed = true; + } + break; + } else { + break; + } + } + return bSucceed; +} +# 1403 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" +bool findNextOperator(char * &pointer, int8_t &op) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { + pointer++; + continue; + } + 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; + } + return bSucceed; +} +# 1440 "/workspace/Tasmota/tasmota/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; +} +# 1493 "/workspace/Tasmota/tasmota/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 == pgm_read_byte(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(void) +{ + 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(); +} +# 1567 "/workspace/Tasmota/tasmota/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; +} +# 1623 "/workspace/Tasmota/tasmota/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; +} +# 1660 "/workspace/Tasmota/tasmota/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 - 1); + pointer = closureBracket + 1; + bSucceed = true; + } + break; + } + pointer++; + } + if (!bSucceed && pointer > pExpr) { + + value = evaluateComparisonExpression(pExpr, pointer - pExpr); + bSucceed = true; + } + return bSucceed; +} +# 1709 "/workspace/Tasmota/tasmota/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); +} +# 1780 "/workspace/Tasmota/tasmota/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; +} +# 1837 "/workspace/Tasmota/tasmota/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; +} +# 1907 "/workspace/Tasmota/tasmota/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; + } + } + } +} +# 1971 "/workspace/Tasmota/tasmota/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) +{ + if (0 == XdrvMailbox.index) { + char data = '\0'; + if (XdrvMailbox.data_len > 0) { + if (!((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10))) { + if ('"' == XdrvMailbox.data[0]) { + data = '"'; + } else { + XdrvMailbox.data_len = 0; + } + } + } + for (uint32_t i = 1; i <= MAX_RULE_SETS; i++) { + XdrvMailbox.index = i; + XdrvMailbox.data[0] = data; + CmndRule(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); + } + mqtt_data[0] = '\0'; + return; + } + uint8_t index = XdrvMailbox.index; + if ((index > 0) && (index <= MAX_RULE_SETS)) { + + if (XdrvMailbox.data_len > 0) { + 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 { + bool append = false; + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.data[0] = ' '; + append = true; + } + int32_t res = SetRule(index - 1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, append); + if (res < 0) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("RUL: Not enough space")); + } + } + Rules.triggers[index -1] = 0; + } + String rule = GetRule(index - 1); + size_t rule_len = rule.length(); + if (rule_len > MAX_RULE_SIZE - 3) { + + size_t start_index = 0; + while (start_index < rule_len) { + size_t last_index = start_index + MAX_RULE_SIZE - 3; + if (last_index < rule_len) { + int32_t next_index = rule.lastIndexOf(" ", last_index); + if (next_index > 0) { + last_index = next_index; + } + } else { + last_index = rule_len; + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Rule%d %s%s"), + index, 0 == start_index ? PSTR("") : PSTR("+"), + rule.substring(start_index, last_index).c_str()); + start_index = last_index + 1; + } + + + rule = rule.substring(0, MAX_RULE_SIZE); + rule += F("..."); + } + + + + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"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)), + rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1), + EscapeJSONString(rule.c_str()).c_str()); + } +} + +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)); +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_EVENT, XdrvMailbox.data); +#endif + } + if (XdrvMailbox.command) 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) { + ResponseCmndAll(SET_MEM1, MAX_RULE_MEMS); + } 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, SettingsText(SET_MEM1 + XdrvMailbox.index -1)); + } else { + SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } +#else + SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); +#endif + bitSet(Rules.mems_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(SettingsText(SET_MEM1 + 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_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 + case FUNC_PRE_INIT: + RulesInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +# 21 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#ifdef USE_SCRIPT +#ifndef USE_RULES +# 41 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#define XDRV_10 10 +#define XI2C_37 37 + +#define SCRIPT_DEBUG 0 + +#define FORMAT_SPIFFS_IF_FAILED true + + +#ifndef MAXVARS +#define MAXVARS 50 +#endif +#ifndef MAXSVARS +#define MAXSVARS 5 +#endif +#define MAXNVARS MAXVARS-MAXSVARS + +#ifndef MAXFILT +#define MAXFILT 5 +#endif +#define SCRIPT_SVARSIZE 20 +#define SCRIPT_MAXSSIZE 48 +#define SCRIPT_EOL '\n' +#define SCRIPT_FLOAT_PRECISION 2 +#define PMEM_SIZE sizeof(Settings.script_pram) +#define SCRIPT_MAXPERM (PMEM_SIZE)-4/sizeof(float) +#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS + +#define MAX_SARRAY_NUM 32 + +uint32_t EncodeLightId(uint8_t relay_id); +uint32_t DecodeLightId(uint32_t hue_id); + +#ifdef USE_UNISHOX_COMPRESSION +#define USE_SCRIPT_COMPRESSION +#endif + + + +#ifdef USE_SCRIPT_FATFS +#undef LITTLEFS_SCRIPT_SIZE +#undef EEP_SCRIPT_SIZE +#undef USE_SCRIPT_COMPRESSION + +#if USE_SCRIPT_FATFS==-1 + +#ifdef ESP32 + +# 87 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script fat file option -1 used" +# 87 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#else + +# 89 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script fat file option -1 used" +# 89 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#endif + +#else + +# 93 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script fat file SDC option used" +# 93 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#endif +#endif + + +#ifdef LITTLEFS_SCRIPT_SIZE +#undef EEP_SCRIPT_SIZE +#undef USE_SCRIPT_COMPRESSION + +# 101 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script little file system option used" +# 101 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#endif + + +#ifdef EEP_SCRIPT_SIZE +#undef USE_SCRIPT_COMPRESSION +#ifdef USE_24C256 + +# 108 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script 24c256 file option used" +# 108 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#else + + +# 111 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "internal eeprom script buffer used" +# 111 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + + +#endif +#endif + + +#ifdef USE_SCRIPT_COMPRESSION + +# 118 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +#pragma message "script compression option used" +# 118 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + +#endif + + +#ifdef USE_SCRIPT_COMPRESSION +#include + +#define SCRIPT_COMPRESS compressor.unishox_compress +#define SCRIPT_DECOMPRESS compressor.unishox_decompress +#ifndef UNISHOXRSIZE +#define UNISHOXRSIZE 2560 +#endif +#endif + +#ifndef STASK_PRIO +#define STASK_PRIO 1 +#endif + +#ifdef USE_SCRIPT_TIMER +#include +Ticker Script_ticker1; +Ticker Script_ticker2; +Ticker Script_ticker3; +Ticker Script_ticker4; + +void Script_ticker1_end(void) { + Script_ticker1.detach(); + Run_Scripter(">ti1", 4, 0); +} +void Script_ticker2_end(void) { + Script_ticker2.detach(); + Run_Scripter(">ti2", 4, 0); +} +void Script_ticker3_end(void) { + Script_ticker3.detach(); + Run_Scripter(">ti3", 4, 0); +} +void Script_ticker4_end(void) { + Script_ticker4.detach(); + Run_Scripter(">ti4", 4, 0); +} +#endif + + +#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) +#ifdef ESP32 +#include "FS.h" +#ifdef LITTLEFS_SCRIPT_SIZE +#include "SPIFFS.h" +#else +#include "FFat.h" +#endif +#else +#include +#endif +FS *fsp; +#endif + + +#ifdef LITTLEFS_SCRIPT_SIZE +void SaveFile(const char *name, const uint8_t *buf, uint32_t len) { + File file = fsp->open(name, "w"); + if (!file) return; + file.write(buf, len); + file.close(); +} + + +uint8_t fs_mounted=0; + +void LoadFile(const char *name, uint8_t *buf, uint32_t len) { + if (!fs_mounted) { +#ifdef ESP32 + if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) { +#else + if (!fsp->begin()) { +#endif + + return; + } + fs_mounted=1; + } + File file = fsp->open(name, "r"); + if (!file) return; + file.read(buf, len); + file.close(); +} +#endif + + +#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,SCRIPT_EVENT_HANDLED}; + +#ifdef USE_SCRIPT_FATFS + +#if USE_SCRIPT_FATFS>=0 +#include +#include +#ifdef ESP32 +FS *fsp; +#else +SDClass *fsp; +#endif +#endif + +#ifndef ESP32 + + +#if USE_SCRIPT_FATFS>=0 + +#undef FILE_WRITE +#define FILE_WRITE (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT) +#define FILE_APPEND (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT | sdfat::O_APPEND) + +#else + +#undef FILE_WRITE +#define FILE_WRITE "w" +#undef FILE_READ +#define FILE_READ "r" +#undef FILE_APPEND +#define FILE_APPEND "a" +#endif + +#endif + + +#ifndef FAT_SCRIPT_SIZE +#define FAT_SCRIPT_SIZE 4096 +#endif + +#ifdef ESP32 +#undef FAT_SCRIPT_NAME +#define FAT_SCRIPT_NAME "/script.txt" +#else +#undef FAT_SCRIPT_NAME +#define FAT_SCRIPT_NAME "script.txt" +#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 { +#ifdef USE_SCRIPT_GLOBVARS + uint16_t data; +#else + uint8_t data; +#endif + 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; +#ifdef USE_SCRIPT_GLOBVARS + uint8_t global : 1; +#endif + }; +} SCRIPT_TYPE; + +struct T_INDEX { + uint8_t index; + SCRIPT_TYPE bits; +}; + +struct M_FILT { +#ifdef LARGE_ARRAYS + uint16_t numvals; + uint16_t index; +#else + uint8_t numvals; + uint8_t index; +#endif + float maccu; + float rbuff[1]; +}; + + +#ifdef LARGE_ARRAYS +#undef AND_FILT_MASK +#undef OR_FILT_MASK +#define AND_FILT_MASK 0x7fff +#define OR_FILT_MASK 0x8000 +#undef MAX_ARRAY_SIZE +#define MAX_ARRAY_SIZE 1000 +#else +#undef AND_FILT_MASK +#undef OR_FILT_MASK +#define AND_FILT_MASK 0x7f +#define OR_FILT_MASK 0x80 +#undef MAX_ARRAY_SIZE +#define MAX_ARRAY_SIZE 127 +#endif + + +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; + +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 udp_connected : 1; + uint8_t udp_used : 1; + }; +} UDP_FLAGS; + + +#define NUM_RES 0xfe +#define STR_RES 0xfd +#define VAR_NV 0xff + +#define NTYPE 0 +#define STYPE 0x80 + +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif + +#define SFS_MAX 4 + +struct SCRIPT_MEM { + float *fvars; + float *s_fvars; + struct T_INDEX *type; + struct M_FILT *mfilt; + char *glob_vnp; +#ifdef SCRIPT_LARGE_VNBUFF + uint16_t *vnp_offset; +#else + uint8_t *vnp_offset; +#endif + 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 script_lzero; + uint8_t var_not_found; + uint8_t glob_error; + uint8_t max_ssize; + uint8_t script_loglevel; + uint8_t flags; + uint8_t si_num[3]; + uint8_t siro_num[3]; + uint8_t sind_num; + char *last_index_string[3]; + +#ifdef USE_SCRIPT_FATFS + File files[SFS_MAX]; + FILE_FLAGS file_flags[SFS_MAX]; + uint8_t script_sd_found; + char flink[2][14]; +#endif +#ifdef USE_SCRIPT_GLOBVARS + UDP_FLAGS udp_flags; +#endif + char web_mode; +} glob_script_mem; + + + +bool event_handeled = false; + + +#ifdef USE_SCRIPT_GLOBVARS +IPAddress last_udp_ip; +WiFiUDP Script_PortUdp; + +#ifndef USE_DEVICE_GROUPS +char * IPAddressToString(const IPAddress& ip_address) { + static char ipbuffer[16]; + sprintf_P(ipbuffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); + return ipbuffer; +} +#endif +#endif + +int16_t last_findex; +int16_t last_sindex; +uint8_t tasm_cmd_activ=0; +uint8_t fast_script=0; +uint8_t glob_script=0; +uint32_t script_lastmillis; + +void flt2char(float num, char *nbuff) { + dtostrfd(num, glob_script_mem.script_dprec, nbuff); +} + +void f2char(float num, uint32_t dprec, uint32_t lzeros, char *nbuff) { + dtostrfd(num, dprec, nbuff); + if (lzeros>1) { + + uint32_t nd = num; + nd/=10; + nd+=1; + if (lzeros>nd) { + + char cpbuf[24]; + char *cp = cpbuf; + for (uint32_t cnt = 0; cnt < lzeros - nd; cnt++) { + *cp++='0'; + } + *cp=0; + strcat(cpbuf,nbuff); + strcpy(nbuff,cpbuf); + } + } +} + +#ifdef USE_BUTTON_EVENT +int8_t script_button[MAX_KEYS]; +#endif + +char *GetNumericArgument(char *lp,uint8_t lastop,float *fp, JsonParserObject *jo); +char *GetStringArgument(char *lp,uint8_t lastop,char *cp, JsonParserObject *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.0; + 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); +} + + + +#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); + + +#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; +#define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; + +float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos); + + +int16_t Init_Scripter(void) { +char *script; + + script = glob_script_mem.script_ram; + + + uint16_t lines = 0; + uint16_t nvars = 0; + uint16_t svars = 0; + uint16_t 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; + uint8_t numflt = 0; + uint16_t 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=='>' || !*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)) { + + uint16_t flen = atoi(op); + if (flen>MAX_ARRAY_SIZE) { + + flen = MAX_ARRAY_SIZE; + } + mfilt[numflt-1].numvals &= OR_FILT_MASK; + mfilt[numflt-1].numvals |= flen&AND_FILT_MASK; + } + } + + } 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; count MAXVNSIZ) { + free(glob_script_mem.script_mem); + return -5; + } + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR("Script: nv=%d, tv=%d, vns=%d, ram=%d"), nvars, svars, index, glob_script_mem.script_mem_size); + + + char *cp1 = glob_script_mem.glob_snp; + char *sp = strings; + for (count = 0; countnumvals = mfilt[count].numvals; + mp += sizeof(struct M_FILT) + ((mfilt[count].numvals & AND_FILT_MASK) - 1) * sizeof(float); + } + + glob_script_mem.numvars = vars; + glob_script_mem.script_dprec = SCRIPT_FLOAT_PRECISION; + glob_script_mem.script_lzero = 0; + 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; count=0 + + fsp = &SD; + if (SD.begin(USE_SCRIPT_FATFS)) { +#else + +#ifdef ESP32 + + if (FFat.begin(true)) { +#else + if (fsp->begin()) { +#endif + +#endif + + glob_script_mem.script_sd_found = 1; + } else { + glob_script_mem.script_sd_found = 0; + } + } + for (uint8_t cnt = 0; cnt0 + ClaimSerial(); + SetSerialBaudrate(9600); +#endif + + + glob_script_mem.scriptptr = lp - 1; + glob_script_mem.scriptptr_bu = glob_script_mem.scriptptr; + +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.udp_flags.udp_used) { + Script_Init_UDP(); + glob_script = Run_Scripter(">G", -2, 0); + } +#endif + + return 0; + +} + +#ifdef USE_SCRIPT_FATFS +uint32_t get_fsinfo(uint32_t sel) { +uint32_t result = 0; +#ifdef ESP32 +#if USE_SCRIPT_FATFS >=0 + if (sel == 0) { + result = SD.totalBytes()/1000; + } else if (sel == 1) { + result = (SD.totalBytes() - SD.usedBytes())/1000; + } +#else + if (sel == 0) { + result = FFat.totalBytes()/1000; + } else if (sel == 1) { + result = FFat.freeBytes()/1000; + } +#endif +#else + + FSInfo64 fsinfo; + fsp->info64(fsinfo); + if (sel == 0) { + result = fsinfo.totalBytes/1000; + } else if (sel == 1) { + result = (fsinfo.totalBytes - fsinfo.usedBytes)/1000; + } +#endif + return result; +} + + +void form1000(uint32_t number, char *dp, char sc) { + char str[32]; + sprintf(str, "%d", number); + char *sp = str; + uint32_t inum = strlen(sp)/3; + uint32_t fnum = strlen(sp)%3; + if (!fnum) inum--; + for (uint32_t count=0; count<=inum; count++) { + if (fnum){ + memcpy(dp,sp,fnum); + dp+=fnum; + sp+=fnum; + fnum=0; + } else { + memcpy(dp,sp,3); + dp+=3; + sp+=3; + } + if (count!=inum) { + *dp++=sc; + } + } + *dp=0; +} + +#endif + +#ifdef USE_SCRIPT_GLOBVARS +#define SCRIPT_UDP_BUFFER_SIZE 128 +#define SCRIPT_UDP_PORT 1999 +IPAddress script_udp_remote_ip; + +void Restart_globvars(void) { + Script_Stop_UDP(); + Script_Init_UDP(); +} + +void Script_Stop_UDP(void) { + if (!glob_script_mem.udp_flags.udp_used) return; + if (glob_script_mem.udp_flags.udp_connected) { + Script_PortUdp.flush(); + Script_PortUdp.stop(); + glob_script_mem.udp_flags.udp_connected = 0; + } +} + +void Script_Init_UDP() { + if (global_state.network_down) return; + if (!glob_script_mem.udp_flags.udp_used) return; + if (glob_script_mem.udp_flags.udp_connected) return; + + if (Script_PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP started")); + glob_script_mem.udp_flags.udp_connected = 1; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP failed")); + glob_script_mem.udp_flags.udp_connected = 0; + } +} + +void Script_PollUdp(void) { + if (global_state.network_down) return; + if (!glob_script_mem.udp_flags.udp_used) return; + if (glob_script_mem.udp_flags.udp_connected ) { + while (Script_PortUdp.parsePacket()) { + char packet_buffer[SCRIPT_UDP_BUFFER_SIZE]; + int32_t len = Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE - 1); + packet_buffer[len] = 0; + script_udp_remote_ip = Script_PortUdp.remoteIP(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); + char *lp=packet_buffer; + if (!strncmp(lp,"=>", 2)) { + lp += 2; + char *cp=strchr(lp, '='); + if (cp) { + char vnam[32]; + for (uint32_t count = 0; countG", 2, 0); + } + } + } + } + optimistic_yield(100); + } + } else { + Script_Init_UDP(); + } +} + +void script_udp_sendvar(char *vname,float *fp,char *sp) { + if (!glob_script_mem.udp_flags.udp_used) return; + if (!glob_script_mem.udp_flags.udp_connected) return; + + char sbuf[SCRIPT_MAXSSIZE + 4]; + strcpy(sbuf, "=>"); + strcat(sbuf, vname); + strcat(sbuf, "="); + if (fp) { + char flstr[16]; + dtostrfd(*fp, 8, flstr); + strcat(sbuf, flstr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"), sbuf); + } else { + strcat(sbuf, sp); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"), sbuf); + } + Script_PortUdp.beginPacket(IPAddress(239, 255, 255, 250), SCRIPT_UDP_PORT); + + Script_PortUdp.write((const uint8_t*)sbuf, strlen(sbuf)); + Script_PortUdp.endPacket(); +} + +#endif + +#ifdef USE_LIGHT +#ifdef USE_WS2812 +void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) { + + Ws2812ForceSuspend(); + for (uint32_t cnt = 0; cntSettings.light_pixels) break; + uint32_t col = array[cnt]; + Ws2812SetColor(index + 1, col>>16, col>>8, col, 0); + } + Ws2812ForceUpdate(); +} +#endif +#endif + + + +float median_array(float *array, uint16_t len) { + uint8_t ind[len]; + uint8_t mind = 0; + uint8_t index = 0; + uint8_t flg; + float min = FLT_MAX; + + for (uint8_t hcnt = 0; hcntnumvals & AND_FILT_MASK; + if (ipos) *ipos = mflp->index; + return mflp->rbuff; + } + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); + } + return 0; +} + +char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonParserObject *jo); + + +float *get_array_by_name(char *name, uint16_t *alen) { + struct T_INDEX ind; + uint8_t vtype; + isvar(name, &vtype, &ind, 0, 0, 0); + if (vtype==VAR_NV) return 0; + if (vtype&STYPE) return 0; + uint16_t index = glob_script_mem.type[ind.index].index; + + if (glob_script_mem.type[ind.index].bits.is_filter) { + float *fa = Get_MFAddr(index, alen, 0); + return fa; + } + return 0; +} + +float Get_MFVal(uint8_t index, int16_t bind) { + uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; + for (uint8_t count = 0; countnumvals & AND_FILT_MASK; + if (!bind) { + return mflp->index; + } + if (bind<0) { + return maxind; + } + if (bind<1 || bind>maxind) bind = maxind; + return mflp->rbuff[bind - 1]; + } + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); + } + return 0; +} + +void Set_MFVal(uint8_t index, uint16_t bind, float val) { + uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; + for (uint8_t count = 0; countnumvals & AND_FILT_MASK; + 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 & AND_FILT_MASK) - 1) * sizeof(float); + } +} + + +float Get_MFilter(uint8_t index) { + uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; + for (uint8_t count = 0; countnumvals & OR_FILT_MASK) { + + return mflp->maccu / (mflp->numvals & AND_FILT_MASK); + } else { + + return median_array(mflp->rbuff, mflp->numvals); + } + } + mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 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 & OR_FILT_MASK) { + + mflp->maccu -= mflp->rbuff[mflp->index]; + mflp->maccu += invar; + mflp->rbuff[mflp->index] = invar; + mflp->index++; + if (mflp->index>=(mflp->numvals&AND_FILT_MASK)) 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 & AND_FILT_MASK) - 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 + + +#ifdef USE_ANGLE_FUNC +uint32_t pulse_time_hl; +uint32_t pulse_time_lh; +uint32_t pulse_ltime_hl; +uint32_t pulse_ltime_lh; +uint8_t pt_pin; + +#define MPT_DEBOUNCE 10 + +void ICACHE_RAM_ATTR MP_Timer(void) { + uint32_t level = digitalRead(pt_pin&0x3f); + uint32_t ms = millis(); + uint32_t time; + if (level) { + + pulse_ltime_lh = ms; + time = ms - pulse_ltime_hl; + if (time>MPT_DEBOUNCE) pulse_time_hl = time; + } else { + + pulse_ltime_hl = ms; + time = ms - pulse_ltime_lh; + if (time>MPT_DEBOUNCE) pulse_time_lh = time; + } +} + +uint32_t MeasurePulseTime(int32_t in) { + if (in >= 0) { + + pt_pin = in; + pinMode(pt_pin & 0x3f, INPUT_PULLUP); + attachInterrupt(pt_pin & 0x3f, MP_Timer, CHANGE); + pulse_ltime_lh = millis(); + pulse_ltime_hl = millis(); + return 0; + } + uint32_t ptime; + if (in==-1) { + ptime = pulse_time_lh; + pulse_time_lh = 0; + } else { + ptime = pulse_time_hl; + pulse_time_hl = 0; + } + return ptime; +} +#endif + +#ifdef USE_SCRIPT_GLOBVARS +uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind) { + uint16_t olen = strlen(dvnam); + struct T_INDEX *vtp = glob_script_mem.type; + for (uint32_t count = 0; count0 && glob_script_mem.last_index_string[isind]) { + free(glob_script_mem.last_index_string[isind]); + } + char *sstart = lp; + uint8_t slen = 0; + for (uint32_t cnt = 0; cnt<256; cnt++) { + if (*lp=='\n' || *lp=='"' || *lp==0) { + lp++; + if (cnt>0 && !slen) { + slen++; + } + glob_script_mem.siro_num[isind] = slen; + break; + } + if (*lp=='|') { + slen++; + } + lp++; + } + + glob_script_mem.si_num[isind] = fvar; + if (glob_script_mem.si_num[isind]>0) { + if (glob_script_mem.si_num[isind]>MAX_SARRAY_NUM) { + glob_script_mem.si_num[isind] = MAX_SARRAY_NUM; + } + + glob_script_mem.last_index_string[isind] = (char*)calloc(glob_script_mem.max_ssize*glob_script_mem.si_num[isind], 1); + for (uint32_t cnt = 0; cntglob_script_mem.si_num[isind]) { + index = glob_script_mem.si_num[isind]; + } + strlcpy(str,glob_script_mem.last_index_string[isind] + (index * glob_script_mem.max_ssize), glob_script_mem.max_ssize); + } + } + lp++; + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + return lp; +} + + + +char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonParserObject *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; + last_sindex = -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 = GetNumericArgument(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) { + + char jvname[32]; + strcpy(jvname, vname); + const char* str_value; + uint8_t aindex; + String vn; + char *ja=strchr(jvname, '['); + if (ja) { + + *ja = 0; + ja++; + + float fvar; + GetNumericArgument(ja, OPER_EQU, &fvar, 0); + aindex = fvar; + if (aindex<1 || aindex>6) aindex = 1; + aindex--; + } + if (jo->isValid()) { + char *subtype = strchr(jvname, '#'); + char *subtype2; + if (subtype) { + *subtype = 0; + subtype++; + subtype2 = strchr(subtype, '#'); + if (subtype2) { + *subtype2 = 0; + *subtype2++; + } + } + vn = jvname; + str_value = (*jo)[vn].getStr(); + if ((*jo)[vn].isValid()) { + if (subtype) { + JsonParserObject jobj1 = (*jo)[vn]; + if (jobj1.isValid()) { + vn = subtype; + jo = &jobj1; + str_value = (*jo)[vn].getStr(); + if ((*jo)[vn].isValid()) { + + if (subtype2) { + JsonParserObject jobj2 = (*jo)[vn]; + if ((*jo)[vn].isValid()) { + vn = subtype2; + jo = &jobj2; + str_value = (*jo)[vn].getStr(); + if ((*jo)[vn].isValid()) { + goto skip; + } else { + goto chknext; + } + } else { + goto chknext; + } + } + + goto skip; + } + } else { + goto chknext; + } + } + skip: + if (ja) { + + str_value = (*jo)[vn].getArray()[aindex].getStr(); + } + if (str_value && *str_value) { + if ((*jo)[vn].isStr()) { + if (!strncmp(str_value, "ON", 2)) { + if (fp) *fp = 1; + goto nexit; + } else if (!strncmp(str_value, "OFF", 3)) { + if (fp) *fp = 0; + goto nexit; + } 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); + } + } + nexit: + *vtype = NUM_RES; + tind->bits.constant = 1; + tind->bits.is_string = 0; + return lp + len; + } + } + } + } + } + +chknext: + switch (vname[0]) { + case 'a': +#ifdef USE_ANGLE_FUNC + if (!strncmp(vname, "acos(", 5)) { + lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = acosf(fvar); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "abs(", 4)) { + lp=GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = fabs(fvar); + lp++; + len = 0; + goto exit; + } +#endif + if (!strncmp(vname, "asc(", 4)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = str[0]; + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "adc(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + while (*lp==' ') lp++; + float fvar1 = 1; + if (*lp!=')') { + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + if (fvar1<32 || fvar1>39) fvar1 = 32; + } + lp++; + if (fvar > 7) fvar = 7; +#ifdef ESP32 + +#ifdef USE_ADC + fvar = AdcRead(fvar1, fvar); +#else + fvar = 999.999; +#endif +#else + +#ifndef USE_ADC_VCC + fvar = AdcRead(17, fvar); +#else + fvar = (float)ESP.getVcc() / 1000.0; +#endif +#endif + len = 0; + goto exit; + } + break; + + case 'b': + if (!strncmp(vname, "boot", 4)) { + if (rules_flag.system_boot) { + rules_flag.system_boot = 0; + fvar = 1; + } + goto exit; + } +#ifdef USE_BUTTON_EVENT + if (!strncmp(vname, "bt[", 3)) { + + GetNumericArgument(vname+3, OPER_EQU, &fvar, 0); + 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; + } +#endif + 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; + } + } + } +#ifdef ESP32 + if (!strncmp(vname, "core", 4)) { + fvar = xPortGetCoreID(); + goto exit; + } +#ifdef USE_SCRIPT_TASK + if (!strncmp(vname, "ct(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + while (*lp==' ') lp++; + float fvar1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + while (*lp==' ') lp++; + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + float prio = STASK_PRIO; + if (*lp!=')') { + lp = GetNumericArgument(lp, OPER_EQU, &prio, 0); + } + lp++; + fvar = scripter_create_task(fvar, fvar1, fvar2, prio); + len = 0; + goto exit; + } +#endif +#endif + 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; + } + if (!strncmp(vname, "eres", 4)) { + fvar = event_handeled; + tind->index = SCRIPT_EVENT_HANDLED; + goto exit_settable; + } +#ifdef USE_ENERGY_SENSOR + if (!strncmp(vname, "enrg[", 5)) { + lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + while (*lp==' ') lp++; + switch ((uint32_t)fvar) { + case 0: + fvar = Energy.total; + break; + case 1: + fvar = Energy.voltage[0]; + break; + case 2: + fvar = Energy.voltage[1]; + break; + case 3: + fvar = Energy.voltage[2]; + break; + case 4: + fvar = Energy.current[0]; + break; + case 5: + fvar = Energy.current[1]; + break; + case 6: + fvar = Energy.current[2]; + break; + case 7: + fvar = Energy.active_power[0]; + break; + case 8: + fvar = Energy.active_power[1]; + break; + case 9: + fvar = Energy.active_power[2]; + break; + + default: + fvar = 99999; + break; + } + len = 0; + lp++; + goto exit; + } +#endif + break; + case 'f': + +#ifdef USE_SCRIPT_FATFS + if (!strncmp(vname, "fo(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + while (*lp==' ') lp++; + uint8_t mode = 0; + if ((*lp=='r') || (*lp=='w') || (*lp=='a')) { + switch (*lp) { + case 'r': + mode = 0; + break; + case 'w': + mode = 1; + break; + case 'a': + mode = 2; + break; + } + lp++; + } else { + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + mode = fvar; + } + fvar = -1; + for (uint8_t cnt = 0;cntopen(str, FILE_READ); + if (glob_script_mem.files[cnt].isDirectory()) { + glob_script_mem.files[cnt].rewindDirectory(); + glob_script_mem.file_flags[cnt].is_dir = 1; + } else { + glob_script_mem.file_flags[cnt].is_dir = 0; + } + } + else { + if (mode==1) { + glob_script_mem.files[cnt] = fsp->open(str,FILE_WRITE); +#ifdef DEBUG_FS + AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for write %d"), cnt); +#endif + } else { + glob_script_mem.files[cnt] = fsp->open(str,FILE_APPEND); +#ifdef DEBUG_FS + AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for append %d"), cnt); +#endif + } + } + if (glob_script_mem.files[cnt]) { + fvar = cnt; + glob_script_mem.file_flags[cnt].is_open = 1; + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("file open failed")); + } + break; + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "fc(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + if (fvar>=0) { + uint8_t ind = fvar; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; +#ifdef DEBUG_FS + AddLog_P2(LOG_LEVEL_INFO, PSTR("closing file %d"), ind); +#endif + 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 = GetNumericArgument(lp + 3, 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)) { + char str[SCRIPT_MAXSSIZE]; + lp = ForceStringVar(lp + 3, str); + while (*lp==' ') lp++; + lp = GetNumericArgument(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)) { + struct T_INDEX ind; + uint8_t vtype; + uint8_t sindex = 0; + lp = isvar(lp + 3, &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 = GetNumericArgument(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())) { + char *ep = (char*)entry.name(); + if (*ep=='/') ep++; + char *lcp = strrchr(ep,'/'); + if (lcp) { + ep = lcp + 1; + } + strcpy(str, ep); + 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)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fsp->remove(str); + lp++; + len = 0; + goto exit; + } +#if defined(ESP32) && defined(USE_WEBCAM) + if (!strncmp(vname, "fwp(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + while (*lp==' ') lp++; + float fvar1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + uint8_t ind = fvar1; + if (ind>=SFS_MAX) ind = SFS_MAX - 1; + if (glob_script_mem.file_flags[ind].is_open) { + uint8_t *buff; + float maxps = WcGetPicstore(-1, 0); + if (fvar<1 || fvar>maxps) fvar = 1; + uint32_t len = WcGetPicstore(fvar - 1, &buff); + if (len) { + + fvar = glob_script_mem.files[ind].write(buff, len); + } else { + fvar = 0; + } + + } else { + fvar = 0; + } + lp++; + len = 0; + goto exit; + } +#endif +#ifdef USE_SCRIPT_FATFS_EXT + if (!strncmp(vname, "fe(", 3)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + + File ef = fsp->open(str, FILE_READ); + 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)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = fsp->mkdir(str); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "frd(", 4)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + fvar = fsp->rmdir(str); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "fx(", 3)) { + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + if (fsp->exists(str)) fvar = 1; + else fvar = 0; + lp++; + len = 0; + goto exit; + } + + if (!strncmp(vname, "fsi(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = get_fsinfo(fvar); + lp++; + len = 0; + goto exit; + } + + if (!strncmp(vname, "fwa(", 4)) { + struct T_INDEX ind; + uint8_t vtype; + lp = isvar(lp + 4, &vtype, &ind, 0, 0, 0); + if (vtype!=VAR_NV && (vtype&STYPE)==0 && glob_script_mem.type[ind.index].bits.is_filter) { + + + } else { + + fvar = 0; + goto exit; + } + + while (*lp==' ') lp++; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + uint8_t index = fvar; + if (index>=SFS_MAX) index = SFS_MAX - 1; + if (glob_script_mem.file_flags[index].is_open) { + uint16_t len = 0; + float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0); + char dstr[24]; + for (uint32_t cnt = 0; cnt=SFS_MAX) find = SFS_MAX - 1; + char str[glob_script_mem.max_ssize + 1]; + if (glob_script_mem.file_flags[find].is_open) { + uint16_t len = 0; + float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0); + char dstr[24]; + for (uint32_t cnt = 0; cnt=glob_script_mem.max_ssize - 1) break; + } + } + *cp = 0; + *fa++=CharToFloat(str); + } + } else { + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + +#endif + if (!strncmp(vname, "fl1(", 4) || !strncmp(vname, "fl2(", 4) ) { + uint8_t lknum = *(lp+2)&3; + char str[glob_script_mem.max_ssize + 1]; + lp = GetStringArgument(lp + 4, 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; + } +#endif + if (!strncmp(vname, "freq", 4)) { +#ifdef ESP32 + fvar = getCpuFrequencyMhz(); +#else + fvar = ESP.getCpuFreqMHz(); +#endif + goto exit; + } + break; + case 'g': + if (!strncmp(vname, "gtmp", 4)) { + fvar = global_temperature_celsius; + goto exit; + } + if (!strncmp(vname, "ghum", 4)) { + fvar = global_humidity; + goto exit; + } + if (!strncmp(vname, "gprs", 4)) { + fvar = global_pressure_hpa; + goto exit; + } + if (!strncmp(vname, "gtopic", 6)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTT_GRP_TOPIC), glob_script_mem.max_ssize); + goto strexit; + } + +#ifdef SCRIPT_GET_HTTPS_JP + if (!strncmp(vname, "gjp(", 4)) { + char host[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 4, OPER_EQU, host, 0); + SCRIPT_SKIP_SPACES + char path[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, path, 0); + fvar = call2https(host, path); + lp++; + len = 0; + goto exit; + } +#endif + 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 = GetNumericArgument(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 = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + lp++; + len = 0; + if (sp) { + sprintf(sp, "%08x", (uint32_t)fvar); + } + goto strexit; + } + if (!strncmp(vname, "hd(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fvar = strtol(str, NULL, 16); + lp++; + len = 0; + goto exit; + } +#ifdef USE_LIGHT + if (!strncmp(vname, "hsvrgb(", 7)) { + lp = GetNumericArgument(lp + 7, OPER_EQU, &fvar, 0); + if (fvar<0 || fvar>360) fvar = 0; + SCRIPT_SKIP_SPACES + + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + if (fvar2<0 || fvar2>100) fvar2 = 0; + SCRIPT_SKIP_SPACES + + float fvar3; + lp = GetNumericArgument(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 = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = floor(fvar); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "is(", 3)) { + lp = isargs(lp + 3, 0); + fvar = 0; + len = 0; + goto exit; + } + if (!strncmp(vname, "is1(", 4)) { + lp = isargs(lp + 4, 1); + fvar = 0; + len = 0; + goto exit; + } + if (!strncmp(vname, "is2(", 4)) { + lp = isargs(lp + 4, 2); + fvar = 0; + len = 0; + goto exit; + } + if (!strncmp(vname, "is[", 3)) { + lp = isget(lp + 3, sp, 0); + len = 0; + goto strexit; + } + if (!strncmp(vname, "is1[", 4)) { + lp = isget(lp + 4, sp, 1); + len = 0; + goto strexit; + } + if (!strncmp(vname, "is2[", 4)) { + lp = isget(lp + 4, sp, 2); + len = 0; + goto strexit; + } + break; + case 'l': + if (!strncmp(vname, "lip", 3)) { + if (sp) strlcpy(sp, (const char*)WiFi.localIP().toString().c_str(), glob_script_mem.max_ssize); + goto strexit; + } +#ifdef USE_SCRIPT_GLOBVARS + if (!strncmp(vname, "luip", 4)) { + if (sp) strlcpy(sp, IPAddressToString(last_udp_ip), glob_script_mem.max_ssize); + goto strexit; + } +#endif + 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 = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = DoMedian5(fvar1, fvar2); + lp++; + len = 0; + goto exit; + } +#ifdef USE_ANGLE_FUNC + if (!strncmp(vname, "mpt(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = MeasurePulseTime(fvar); + lp++; + len = 0; + goto exit; + } +#endif + 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; + } + if (!strncmp(vname, "mp(", 3)) { + float fvar1; + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + while (*lp!=')') { + char *opp = lp; + lp++; + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + SCRIPT_SKIP_SPACES + fvar = fvar1; + if ((*opp=='<' && fvar1' && fvar1>fvar2) || + (*opp=='=' && fvar1==fvar2)) { + if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { + float fvar3; + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + SCRIPT_SKIP_SPACES + fvar=fvar3; + } else { + fvar = fvar2; + } + break; + } + while (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) lp++; + } + len = 0; + goto exit; + } +#ifdef USE_MORITZ + if (!strncmp(vname, "mo(", 3)) { + float fvar1; + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + SCRIPT_SKIP_SPACES + char rbuff[64]; + fvar = mo_getvars(fvar1, fvar2, rbuff); + lp++; + if (sp) strlcpy(sp, rbuff, glob_script_mem.max_ssize); + len = 0; + goto strexit; + } +#endif + break; + case 'p': + if (!strncmp(vname, "pin[", 4)) { + + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); + fvar = digitalRead((uint8_t)fvar); + + len++; + goto exit; + } + if (!strncmp(vname, "pn[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + fvar = Pin(fvar); + + len++; + goto exit; + } +#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) + if (!strncmp(vname, "pl(", 3)) { + char path[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, path, 0); + Play_mp3(path); + len++; + len = 0; + goto exit; + } +#endif + if (!strncmp(vname, "pd[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + uint8_t gpiopin = fvar; +# 2640 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) { + fvar = gpio_pin[gpiopin]; + + len++; + goto exit; + } + fvar = 999; + goto exit; + } +#ifdef ESP32 + if (!strncmp(vname, "pheap", 5)) { + fvar = ESP.getFreePsram(); + goto exit; + } +#endif + if (!strncmp(vname, "prefix1", 7)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX1), glob_script_mem.max_ssize); + goto strexit; + } + if (!strncmp(vname, "prefix2", 7)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX2), glob_script_mem.max_ssize); + goto strexit; + } + if (!strncmp(vname, "prefix3", 7)) { + if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX3), glob_script_mem.max_ssize); + goto strexit; + } + if (!strncmp(vname, "pow(", 4)) { + + float fvar1; + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + lp++; + fvar = FastPrecisePowf(fvar1, fvar2); + len = 0; + goto exit; + } + if (!strncmp(vname, "pwr[", 4)) { + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); + uint8_t index = fvar; + if (index<=devices_present) { + fvar = bitRead(power, index - 1); + } else { + fvar = -1; + } + len += 1; + goto exit; + } + if (!strncmp(vname, "pc[", 3)) { + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + uint8_t index = fvar; + if (index<1 || index>MAX_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) + (PMEM_SIZE); + goto exit; + } + if (!strncmp(vname, "rnd(", 4)) { + + GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); + if (fvar<0) { + randomSeed(-fvar); + fvar = 0; + } else { + fvar = random(fvar); + } + + len++; + goto exit; + } + break; + case 's': + if (!strncmp(vname, "secs", 4)) { + fvar = RtcTime.second; + goto exit; + } + if (!strncmp(vname, "sw[", 3)) { + + GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); + fvar = SwitchLastState((uint32_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)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + lp++; + len = 0; + fvar = strlen(str); + goto exit; + } + if (!strncmp(vname, "sb(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + SCRIPT_SKIP_SPACES + float fvar1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + float fvar2; + lp = GetNumericArgument(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)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + while (*lp==' ') lp++; + char token[2]; + token[0] = *lp++; + token[1] = 0; + while (*lp==' ') lp++; + lp = GetNumericArgument(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 = GetNumericArgument(lp + 2, OPER_EQU, &fvar, 0); + char str[glob_script_mem.max_ssize + 1]; + f2char(fvar, glob_script_mem.script_dprec, glob_script_mem.script_lzero, str); + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + lp++; + len = 0; + goto strexit; + } +#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) + if (!strncmp(vname, "say(", 4)) { + char text[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 4, OPER_EQU, text, 0); + Say(text); + len++; + len = 0; + goto exit; + } +#endif + +#ifdef ESP32 + if (!strncmp(vname, "sf(", 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); + if (fvar<80) fvar = 80; + if (fvar>240) fvar = 240; + setCpuFrequencyMhz(fvar); + fvar = getCpuFrequencyMhz(); + lp++; + len = 0; + goto exit; + } +#endif +#ifdef USE_TTGO_WATCH + if (!strncmp(vname, "slp(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + SCRIPT_SKIP_SPACES + TTGO_Sleep(fvar); + lp++; + len = 0; + goto exit; + } +#endif +#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 + +#ifdef USE_SHUTTER + if (!strncmp(vname, "sht[", 4)) { + GetNumericArgument(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 +#ifdef USE_ANGLE_FUNC + if (!strncmp(vname, "sin(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = sinf(fvar); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sqrt(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = sqrtf(fvar); + lp++; + len = 0; + goto exit; + } +#endif + +#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) + if (!strncmp(vname, "sml[", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + SCRIPT_SKIP_SPACES + fvar = SML_GetVal(fvar); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sml(", 4)) { + float fvar1; + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + SCRIPT_SKIP_SPACES + if (fvar2==0) { + float fvar3; + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + fvar = SML_SetBaud(fvar1, fvar3); + } else if (fvar2==1) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, str, 0); + fvar = SML_Write(fvar1, str); + } else if (fvar2==2) { + char str[SCRIPT_MAXSSIZE]; + str[0] = 0; + fvar = SML_Read(fvar1, str, SCRIPT_MAXSSIZE); + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + lp++; + len = 0; + goto strexit; + + } else { +#ifdef ED300L + fvar = SML_Status(fvar1); +#else + fvar = 0; +#endif + } + lp++; + len = 0; + 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)) { + fvar = rules_flag.time_init; + goto exit; + } + if (!strncmp(vname, "tset", 4)) { + fvar = rules_flag.time_set; + 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, SettingsText(SET_MQTT_TOPIC), glob_script_mem.max_ssize); + goto strexit; + } +#ifdef USE_SCRIPT_TIMER + if (!strncmp(vname, "ts1(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; + Script_ticker1.attach_ms(fvar, Script_ticker1_end); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "ts2(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; + Script_ticker2.attach_ms(fvar, Script_ticker2_end); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "ts3(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; + Script_ticker3.attach_ms(fvar, Script_ticker3_end); + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "ts4(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + if (fvar<10) fvar = 10; + Script_ticker4.attach_ms(fvar, Script_ticker4_end); + lp++; + len = 0; + goto exit; + } +#endif + +#ifdef USE_DISPLAY +#ifdef USE_TOUCH_BUTTONS + if (!strncmp(vname, "tbut[", 5)) { + GetNumericArgument(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.on_off; + } 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 defined(ESP32) && defined(USE_WEBCAM) + if (!strncmp(vname, "wc(", 3)) { + float fvar1; + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); + SCRIPT_SKIP_SPACES + switch ((uint32)fvar1) { + case 0: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetup(fvar2); + } + break; + case 1: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcGetFrame(fvar2); + } + break; + case 2: + { float fvar2,fvar3; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); + fvar = WcSetOptions(fvar2, fvar3); + } + break; + case 3: + fvar = WcGetWidth(); + break; + case 4: + fvar = WcGetHeight(); + break; + case 5: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetStreamserver(fvar2); + } + break; + case 6: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetMotionDetect(fvar2); + } + break; +#ifdef USE_FACE_DETECT + case 7: + { float fvar2; + lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); + fvar = WcSetFaceDetect(fvar2); + } + break; +#endif + default: + fvar = 0; + } + lp++; + len = 0; + goto exit; + } +#endif +#if defined(USE_TTGO_WATCH) && defined(USE_BMA423) + if (!strncmp(vname, "wdclk", 5)) { + fvar = TTGO_doubleclick(); + goto exit; + } + if (!strncmp(vname, "wbut", 4)) { + fvar = TTGO_button(); + goto exit; + } +#endif +#if defined(USE_TTGO_WATCH) && defined(USE_FT5206) + if (!strncmp(vname, "wtch(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + fvar = Touch_Status(fvar); + lp++; + len = 0; + goto exit; + } +#endif + if (!strncmp(vname, "wm", 2)) { + fvar = glob_script_mem.web_mode; + goto exit; + } + 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; +} + + +#ifdef ESP8266 +extern "C" { +#include + extern cont_t* g_pcont; +} +uint16_t GetStack(void) { + register uint32_t *sp asm("a1"); + return (4 * (sp - g_pcont->stack)); +} +#else +uint16_t GetStack(void) { + register uint8_t *sp asm("a1"); + return (sp - pxTaskGetStackStart(NULL)); +} +#endif + +char *GetStringArgument(char *lp, uint8_t lastop, char *cp, JsonParserObject *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) - strlen(str1)); + 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; + } + } + return lp; +} + +char *GetNumericArgument(char *lp, uint8_t lastop, float *fp, JsonParserObject *jo) { +uint8_t operand = 0; +float fvar1,fvar; +char *slp; +uint8_t vtype; +struct T_INDEX ind; + while (1) { + + if (*lp=='(') { + lp++; + lp = GetNumericArgument(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 = GetStringArgument(lp, OPER_EQU, dstr, 0); + if (glob_script_mem.glob_error) { + + lp = GetNumericArgument(slp, OPER_EQU, &fvar, 0); + dtostrfd(fvar, 6, dstr); + glob_script_mem.glob_error = 0; + } + return lp; +} + + +void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { + char *cp; + uint16_t count; + uint8_t vtype; + uint8_t dprec = glob_script_mem.script_dprec; + uint8_t lzero = glob_script_mem.script_lzero; + float fvar; + cp = srcbuf; + struct T_INDEX ind; + char string[SCRIPT_MAXSSIZE]; + dstsize -= 2; + for (count = 0; count=sizeof(str)) 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, JsonParserObject *jo) { + float fvar,*dfvar,fvar1; + uint8_t numeric; + struct T_INDEX ind; + uint8_t vtype = 0,lastop; + uint8_t res = 0; + char *llp = lp; + char *slp; + + SCRIPT_SKIP_SPACES + if (*lp=='(') { + uint8_t res = 0; + uint8_t xand_or = 0; + lp++; + +loop: + SCRIPT_SKIP_SPACES + lp = Evaluate_expression(lp, xand_or, &res, jo); + if (*lp==')') { + lp++; + goto exit0; + } + + SCRIPT_SKIP_SPACES + if (!strncmp(lp, "or", 2)) { + lp += 2; + xand_or = 1; + goto loop; + } else if (!strncmp(lp, "and", 3)) { + lp += 3; + xand_or = 2; + goto loop; + } +exit0: + if (!and_or) { + *result = res; + } else if (and_or==1) { + *result|=res; + } else { + *result &= res; + } + goto exit10; + } + + llp = lp; + + dfvar = &fvar; + glob_script_mem.glob_error = 0; + slp = lp; + numeric = 1; + lp = GetNumericArgument(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 = GetStringArgument(lp, OPER_EQU, str, jo); + if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { + res = strcmp(cmpstr, str); + if (lastop==OPER_EQUEQU) res=!res; + goto exit; + } + + } else { + + + lp = getop(lp, &lastop); + lp = GetNumericArgument(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; + } + +exit: + if (!and_or) { + *result = res; + } else if (and_or==1) { + *result |= res; + } else { + *result &= res; + } + } + + +exit10: +#if IFTHEN_DEBUG>0 + char tbuff[128]; + sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d,and_or=%d line: ", (int32_t)*dfvar, (int32_t)fvar1, *result, and_or); + toLogEOL(tbuff, llp); +#endif + return lp; +} + +#ifdef ESP32 + +TimerHandle_t beep_th; +void StopBeep( TimerHandle_t xTimer ); + +void StopBeep( TimerHandle_t xTimer ) { + ledcWriteTone(7, 0); + xTimerStop(xTimer, 0); +} + +void esp32_beep(int32_t freq ,uint32_t len) { + if (freq<0) { + ledcSetup(7, 500, 10); + ledcAttachPin(-freq, 7); + ledcWriteTone(7, 0); + if (!beep_th) { + beep_th = xTimerCreate("beep", 100, pdFALSE, ( void * ) 0, StopBeep); + } + } else { + if (!beep_th) return; + if (!freq) { + ledcWriteTone(7, 0); + xTimerStop(beep_th, 10); + return; + } + if (len < 10) return; + if (xTimerIsTimerActive(beep_th)) return; + ledcWriteTone(7, freq); + uint32_t ticks = pdMS_TO_TICKS(len); + xTimerChangePeriod( beep_th, ticks, 10); + } +} +#endif + + + +char *scripter_sub(char *lp, uint8_t fromscriptcmd) { + lp += 1; + char *slp = lp; + uint8_t plen = 0; + while (*lp) { + if (*lp=='\n'|| *lp=='\r'|| *lp=='(') { + break; + } + lp++; + plen++; + } + if (fromscriptcmd) { + char *sp = glob_script_mem.scriptptr; + glob_script_mem.scriptptr = glob_script_mem.scriptptr_bu; + Run_Scripter(slp, plen, 0); + glob_script_mem.scriptptr = sp; + } else { + Run_Scripter(slp, plen, 0); + } + lp = slp; + return lp; +} + +#define IF_NEST 8 + +int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { +int16_t retval; + + if (!glob_script_mem.scriptptr) { + return -99; + } + + if (tasm_cmd_activ && tlen>0) return 0; + + JsonParserObject jo; + if (js) { + + + JsonParser parser(js); + jo = parser.getRootObject(); + retval = Run_script_sub(type, tlen, &jo); + } else { + retval = Run_script_sub(type, tlen, 0); + } + return retval; +} + +int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { + uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0; + char *lp_next; + int16_t globaindex,saindex; + 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; + + 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_next = 0; + 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 = GetNumericArgument(lp, OPER_EQU, cv_count, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &cv_max, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &cv_inc, 0); + + cv_ptr = lp; + if (*cv_count<=cv_max && cv_inc>0) { + + floop = 1; + } else { + + floop = 2; + if (cv_inc>0) { + floop = 1; + } + } + } else { + + toLogEOL("for error", lp); + } + } else if (!strncmp(lp, "next", 4)) { + lp_next = lp; + if (floop>0) { + + *cv_count += cv_inc; + if (floop==1) { + if (*cv_count<=cv_max) { + lp = cv_ptr; + } else { + lp += 4; + floop = 0; + } + } else { + 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 = GetNumericArgument(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 = GetNumericArgument(lp, OPER_EQU, &cvar, 0); + if (swvar!=cvar) { + swflg = 2; + } else { + swflg = 1; + } + } else { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(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)) { + lp += 5; + if (floop) { + + if (lp_next) { + lp = lp_next; + } + floop = 0; + } else { + section = 0; + } + goto next_line; + } else if (!strncmp(lp, "dp", 2) && isdigit(*(lp + 2))) { + lp += 2; + + if (*(lp + 1)== '.') { + glob_script_mem.script_lzero = atoi(lp); + lp+=2; + } + glob_script_mem.script_dprec = atoi(lp); + goto next_line; + } +#ifdef USE_DISPLAY + else if (!strncmp(lp, "dt", 2)) { + char dstbuf[256]; + lp += 2; + SCRIPT_SKIP_SPACES + Replace_Cmd_Vars(lp, 1, dstbuf, sizeof(dstbuf)); + char *savptr = XdrvMailbox.data; + XdrvMailbox.data = dstbuf; + XdrvMailbox.data_len = 0; + DisplayText(); + XdrvMailbox.data = savptr; + goto next_line; + } +#endif + else if (!strncmp(lp, "delay(", 6)) { + + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + delay(fvar); + goto next_line; + } else if (!strncmp(lp, "spinm(", 6)) { + + lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); + int8_t pinnr = fvar; + SCRIPT_SKIP_SPACES + uint8_t mode = 0; + if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { + switch (*lp) { + case 'I': + mode = 0; + break; + case 'O': + mode = 1; + break; + case 'P': + mode = 2; + break; + } + lp++; + } else { + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + mode = fvar; + } + uint8_t pm=0; + if (mode==0) pm = INPUT; + if (mode==1) pm = OUTPUT; + if (mode==2) pm = INPUT_PULLUP; + pinMode(pinnr, pm); + goto next_line; + } else if (!strncmp(lp, "spin(", 5)) { + + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + int8_t pinnr = fvar; + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(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_SCRIPT_GLOBVARS + else if (!strncmp(lp, "gvr", 3)) { + lp += 3; + + Restart_globvars(); + goto next_line; + } +#endif +#ifdef USE_LIGHT +#ifdef USE_WS2812 + else if (!strncmp(lp, "ws2812(", 7)) { + lp = isvar(lp + 7, &vtype, &ind, 0, 0, 0); + if (vtype!=VAR_NV) { + SCRIPT_SKIP_SPACES + if (*lp!=')') { + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + } else { + fvar = 0; + } + + uint8_t index = glob_script_mem.type[ind.index].index; + if ((vtype&STYPE)==0) { + + if (glob_script_mem.type[ind.index].bits.is_filter) { + uint16_t len = 0; + float *fa = Get_MFAddr(index, &len, 0); + + if (fa && len) ws2812_set_array(fa, len, fvar); + } + } + } + goto next_line; + } +#endif +#endif +#ifdef ESP32 + else if (!strncmp(lp, "beep(", 5)) { + lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); + SCRIPT_SKIP_SPACES + float fvar1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); + esp32_beep(fvar, fvar1); + lp++; + goto next_line; + } +#endif + else if (!strncmp(lp, "wcs", 3)) { + lp+=4; + + char tmp[256]; + Replace_Cmd_Vars(lp ,1 , tmp, sizeof(tmp)); + WSContentFlush(); + WSContentSend_P(PSTR("%s"),tmp); + WSContentFlush(); + goto next_line; + } + else if (!strncmp(lp,"=>",2) || !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; + if (*lp=='+') sflag = 2; + 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", 1, jo); + glob_script_mem.scriptptr = svd_sp; + } + + + if (if_state[ifstck]==1) { + + lp = Evaluate_expression(lp, and_or, &if_result[ifstck], jo); + SCRIPT_SKIP_SPACES + if (*lp=='{' && if_state[ifstck]==1) { + lp += 1; + if_state[ifstck] = 2; + if (if_exe[ifstck - 1]) if_exe[ifstck] = if_result[ifstck]; + } + goto next_line; + } else { + char *vnp = lp; + lp = isvar(lp, &vtype, &ind, &sysvar, 0, 0); + if (vtype!=VAR_NV) { +#ifdef USE_SCRIPT_GLOBVARS + char varname[16]; + uint32_t vnl = (uint32_t)lp - (uint32)vnp; + strncpy(varname, vnp, vnl); + varname[vnl] = 0; +#endif + + + globvindex = ind.index; + globaindex = last_findex; + uint8_t index = glob_script_mem.type[ind.index].index; + if ((vtype&STYPE)==0) { + + if (ind.bits.settable || ind.bits.is_filter) { + dfvar = &sysvar; + if (ind.bits.settable) { + sysv_type = ind.index; + } else { + sysv_type = 0; + } + + } else { + dfvar = &glob_script_mem.fvars[index]; + sysv_type = 0; + } + numeric = 1; + lp = getop(lp, &lastop); + char *slp = lp; + glob_script_mem.glob_error = 0; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, jo); + if (glob_script_mem.glob_error==1) { + + + lp = isvar(slp, &vtype, &ind, 0, cmpstr, jo); + fvar = CharToFloat(cmpstr); + } + switch (lastop) { + case OPER_EQU: + if (glob_script_mem.var_not_found) { + if (!jo) toLogEOL("var not found: ",lp); + goto next_line; + } + *dfvar = fvar; + break; + case OPER_PLSEQU: + *dfvar += fvar; + break; + case OPER_MINEQU: + *dfvar -= fvar; + break; + case OPER_MULEQU: + *dfvar *= fvar; + break; + case OPER_DIVEQU: + *dfvar /= fvar; + break; + case OPER_PERCEQU: + *dfvar = fmodf(*dfvar, fvar); + break; + case OPER_ANDEQU: + *dfvar = (uint32_t)*dfvar & (uint32_t)fvar; + break; + case OPER_OREQU: + *dfvar = (uint32_t)*dfvar | (uint32_t)fvar; + break; + case OPER_XOREQU: + *dfvar = (uint32_t)*dfvar ^ (uint32_t)fvar; + break; + default: + + break; + } + + glob_script_mem.type[globvindex].bits.changed = 1; +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.type[globvindex].bits.global) { + script_udp_sendvar(varname, dfvar, 0); + } +#endif + if (glob_script_mem.type[globvindex].bits.is_filter) { + 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) { + 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; + case SCRIPT_EVENT_HANDLED: + event_handeled = *dfvar; + break; + } + sysv_type = 0; + } + } else { + + numeric = 0; + sindex = index; + saindex = last_sindex; + + char str[SCRIPT_MAXSSIZE]; + lp = getop(lp, &lastop); + char *slp = lp; + glob_script_mem.glob_error = 0; + lp = GetStringArgument(lp, OPER_EQU, str, jo); + if (!jo && glob_script_mem.glob_error) { + + lp = GetNumericArgument(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; +#ifdef USE_SCRIPT_GLOBVARS + if (glob_script_mem.type[globvindex].bits.global) { + script_udp_sendvar(varname, 0, str); + } +#endif + if (saindex>=0) { + if (lastop==OPER_EQU) { + strlcpy(glob_script_mem.last_index_string[glob_script_mem.sind_num] + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); + } else if (lastop==OPER_PLSEQU) { + strncat(glob_script_mem.last_index_string[glob_script_mem.sind_num] + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); + } + last_sindex = -1; + } else { + 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; + GetNumericArgument((char*)ctype, OPER_EQU, &fparam, 0); + if (glob_script_mem.glob_error==1) { + + numeric = 0; + + GetStringArgument((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 (Settings.rule_enabled) { + 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; countglob_script_mem.script_pram_size) { + vtp[count].bits.is_permanent = 0; + return; + } + while (len--) { + *fp++ = *fa++; + } + } else { + mlen += sizeof(float); + if (mlen>glob_script_mem.script_pram_size) { + vtp[count].bits.is_permanent = 0; + return; + } + *fp++ = glob_script_mem.fvars[index]; + } + } + } + char *cp = (char*)fp; + for (uint8_t count = 0; countglob_script_mem.script_pram_size) { + vtp[count].bits.is_permanent = 0; + return; + } + strcpy(cp, sp); + cp += slen + 1; + } + } +} + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_SCRIPT "s10" + +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 = + "
" + "
" + "
" + ""; + +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_FILE_UPGc[] PROGMEM = +"
total size: %s kB - free: %s kB
"; + +const char HTTP_FORM_SDC_DIRa[] PROGMEM = +"
"; +const char HTTP_FORM_SDC_DIRb[] PROGMEM = + "
%s     %s : %8d
"; +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 + + +uint8_t *script_ex_ptr; +uint16_t uplsize; +uint8_t sc_state; + + +void script_upload_start(void) { + + + + HTTPUpload& upload = Webserver->upload(); + if (upload.status == UPLOAD_FILE_START) { + + script_ex_ptr = (uint8_t*)glob_script_mem.script_ram; + + + if (strcmp(upload.filename.c_str(), "execute_script")) { + Web.upload_error = 1; + WSSend(500, CT_PLAIN, F("500: wrong filename")); + return; + } + if (upload.totalSize>=glob_script_mem.script_size) { + Web.upload_error = 1; + WSSend(500, CT_PLAIN, F("500: file to large")); + return; + } + uplsize = 0; + + sc_state = bitRead(Settings.rule_enabled, 0); + bitWrite(Settings.rule_enabled, 0, 0); + + } else if(upload.status == UPLOAD_FILE_WRITE) { + + uint32_t csiz = upload.currentSize; + uint32_t tsiz = glob_script_mem.script_size - 1; + if (uplsize0 +#undef REJCMPL +#define REJCMPL 6 +#else +#undef REJCMPL +#define REJCMPL 8 +#endif + +uint8_t reject(char *name) { + + char *lcp = strrchr(name,'/'); + if (lcp) { + name = lcp + 1; + } + + while (*name=='/') name++; + if (*name=='_') return 1; + if (*name=='.') return 1; + + 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; + if (!strncasecmp(name, "System Volume", 13)) return 1; + 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 = fsp->open(path, FILE_READ); + 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, ".."); + } + char *ep; + while (true) { + File entry = dir.openNextFile(); + if (!entry) { + break; + } + + ep = (char*)entry.name(); + if (*ep=='/') ep++; + char *lcp = strrchr(ep,'/'); + if (lcp) { + ep = lcp + 1; + } + + time_t tm = entry.getLastWrite(); + char tstr[24]; + strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm)); + + char *pp = path; + if (!*(pp + 1)) pp++; + char *cp = name; + + if (reject((char*)ep)) goto fclose; + + for (uint8_t cnt = 0; cnt1) { + strcat(path, "/"); + } + strcat(path, ep); + ListDir(path, depth + 4); + path[plen] = 0; + } else { + snprintf_P(npath, sizeof(npath), HTTP_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp,ep); + WSContentSend_P(HTTP_FORM_SDC_DIRb, npath, ep, name, tstr, 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, D_SCRIPT_UPLOAD); +#ifdef SDCARD_DIR + char ts[16]; + char fs[16]; + form1000(get_fsinfo(0), ts, '.'); + form1000(get_fsinfo(1), fs, '.'); + WSContentSend_P(HTTP_FORM_FILE_UPGc, ts, fs); + 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; +} + +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(); +} + + +File upload_file; + +void script_upload(void) { + + HTTPUpload& upload = Webserver->upload(); + if (upload.status == UPLOAD_FILE_START) { + char npath[48]; +#if defined(ESP32) && defined(USE_SCRIPT_FATFS) && USE_SCRIPT_FATFS==-1 + + sprintf(npath, "%s/%s", path, upload.filename.c_str()); +#else + sprintf(npath, "%s/%s", path, upload.filename.c_str()); +#endif + fsp->remove(npath); + upload_file = fsp->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 (!fsp->exists(file)) { + AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); + return 0; + } + + download_file = fsp->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); + + +#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 + + + 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 SaveScript(void) { + +#ifdef EEP_SCRIPT_SIZE + 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) { + fsp->remove(FAT_SCRIPT_NAME); + File file = fsp->open(FAT_SCRIPT_NAME, FILE_WRITE); + file.write((const uint8_t*)glob_script_mem.script_ram, FAT_SCRIPT_SIZE); + file.close(); + } +#endif + +#ifdef LITTLEFS_SCRIPT_SIZE + if (glob_script_mem.flags&1) { + SaveFile("/script.txt", (uint8_t*)glob_script_mem.script_ram, LITTLEFS_SCRIPT_SIZE); + } +#endif +} + +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"); + +#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); + + if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); + bitWrite(Settings.rule_enabled, 0, 0); + } + + SaveScript(); + + } + + SaveScriptEnd(); +} + +void SaveScriptEnd(void) { + +#ifdef USE_SCRIPT_GLOBVARS + Script_Stop_UDP(); +#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; + } + +#ifdef USE_SCRIPT_COMPRESSION + + uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); + if (len_compressed > 0) { + Settings.rules[0][len_compressed] = 0; + AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); + } +#endif + + if (bitRead(Settings.rule_enabled, 0)) { + + + + int16_t res = Init_Scripter(); + if (res) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); + return; + } + + Run_Scripter(">B\n", 3, 0); + Run_Scripter(">BS", 3, 0); + + fast_script = Run_Scripter(">F", -2, 0); + } +} + +#endif + + +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +#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\":\"{m1}\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +# 5264 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +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\"" +"}"; +# 5345 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +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")); + String light_status = ""; + if (hue_script[hue_devs].index[1]>0) { + + 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) { + + uint32_t hue = glob_script_mem.fvars[hue_script[hue_devs].index[2] - 1]; + + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + } + if (hue_script[hue_devs].index[3]>0) { + + 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) { + + uint32_t ct = glob_script_mem.fvars[hue_script[hue_devs].index[4] - 1]; + light_status += "\"ct\":"; + light_status += String(ct); + light_status += ","; + } + + float temp; + switch (hue_script[hue_devs].type) { + case 'C': + response->replace("{type}","Color Ligh"); + response->replace("{m1","LST001"); + break; + case 'D': + response->replace("{type}","Dimmable Light"); + response->replace("{m1","LWB004"); + break; + case 'T': + response->replace("{type}","Color Temperature Light"); + response->replace("{m1","LTW011"); + break; + case 'E': + response->replace("{type}","Extended color light"); + response->replace("{m1","LCT007"); + break; + case 'S': + response->replace("{type}","On/Off light"); + response->replace("{m1","LCT007"); + break; + default: + response->replace("{type}","color light"); + response->replace("{m1","LST001"); + break; + } + + response->replace("{light_status}", light_status); + response->replace("{j1", hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + +} + +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 tmp[256]; + 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!=';') { + + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + + + cp = tmp; + cp = strchr(cp,','); + if (!cp) break; + *cp = 0; + + strlcpy(hue_script[hue_devs].name, tmp, HUE_DEV_NSIZE); + cp++; + while (*cp==' ') cp++; + + hue_script[hue_devs].type = *cp; + + for (vindex = 0; vindex0) *response += ",\""; + else *response += "\""; + } + *response += String(EncodeLightId(hue_devs + devices_present + 1))+"\":"; + Script_HueStatus(response, hue_devs); + + } + + hue_devs++; + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } +#if 0 + 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\"}}]"; + + + +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 = "["; + + JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); + JsonParserObject root = parser.getRootObject(); + JsonParserToken hue_on = root[PSTR("on")]; + if (hue_on) { + + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + + bool on = hue_on.getBool(); + if (on==false) { + glob_script_mem.fvars[hue_script[index].index[0] - 1] = 0; + response.replace("{re", "false"); + } else { + glob_script_mem.fvars[hue_script[index].index[0] - 1] = 1; + response.replace("{re", "true"); + } + glob_script_mem.type[hue_script[index].vindex[0]].bits.changed = 1; + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_bri = root[PSTR("bri")]; + if (hue_bri) { + tmp = hue_bri.getUInt(); + 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; + } + + JsonParserToken hue_xy = root[PSTR("xy")]; + if (hue_xy) { + float x, y; + JsonParserArray arr_xy = JsonParserArray(hue_xy); + JsonParserToken tok_x = arr_xy[0]; + JsonParserToken tok_y = arr_xy[1]; + x = tok_x.getFloat(); + y = tok_y.getFloat(); + String x_str = tok_x.getStr(); + String y_str = tok_y.getStr(); + 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; + } + + JsonParserToken hue_hue = root[PSTR("hue")]; + if (hue_hue) { + tmp = hue_hue.getUInt(); + + + 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; + } + + JsonParserToken hue_sat = root[PSTR("sat")]; + if (hue_sat) { + tmp = hue_sat.getUInt(); + 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; + } + + JsonParserToken hue_ct = root[PSTR("ct")]; + if (hue_ct) { + ct = hue_ct.getUInt(); + 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 + + +#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++ = '#'; + 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 { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + } + 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; + + if (tasm_cmd_activ) return false; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); + if (-1 == command_code) { + serviced = false; + } + else if ((CMND_SCRIPT == command_code) && (index > 0)) { + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + 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]) { + + 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 + +#ifndef MQTT_EVENT_MSIZE +#define MQTT_EVENT_MSIZE 256 +#endif +#ifndef MQTT_EVENT_JSIZE +#define MQTT_EVENT_JSIZE 400 +#endif +# 5867 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" +bool ScriptMqttData(void) +{ + bool serviced = false; + + + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > MQTT_EVENT_MSIZE) { + 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 { + JsonParser parser((char*)sData.c_str()); + JsonParserObject jsonData = parser.getRootObject(); + String key1 = event_item.Key; + String key2; + if (!jsonData) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + lkey = key2; + JsonParserToken val = jsonData[key1.c_str()].getObject()[key2.c_str()]; + if (!val) break; + value = val.getStr(); + } else { + JsonParserToken val = jsonData[key1.c_str()]; + if (!val) break; + value = val.getStr(); + 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; +} +# 5944 "/workspace/Tasmota/tasmota/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; +} +# 6024 "/workspace/Tasmota/tasmota/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 + +#ifdef SCRIPT_FULL_WEBPAGE +const char HTTP_WEB_FULL_DISPLAY[] PROGMEM = + "

"; + +const char HTTP_SCRIPT_FULLPAGE1[] PROGMEM = + "" + "" + "" + "" + "%s - %s" + ""; + + +#ifdef USE_SCRIPT_FATFS + +const char HTTP_SCRIPT_MIMES[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "Content-disposition: inline; filename=%s" + "Content-type: %s\r\n\r\n"; + +void ScriptGetSDCard(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + String stmp = Webserver->uri(); + char *cp = strstr_P(stmp.c_str(), PSTR("/sdc/")); + + if (cp) { +#ifdef ESP32 + cp += 4; +#else + cp += 5; +#endif + if (strstr_P(cp, PSTR("scrdmp.bmp"))) { + SendFile(cp); + return; + } else { + if (fsp->exists(cp)) { + SendFile(cp); + return; + } + } + } + HandleNotFound(); +} + +extern uint8_t *buffer; + +void SendFile(char *fname) { +char buff[512]; + const char *mime; + uint8_t sflg = 0; + char *jpg = strstr(fname,".jpg"); + if (jpg) { + mime = "image/jpeg"; + } + +#ifdef USE_DISPLAY_DUMP + char *sbmp = strstr_P(fname, PSTR("scrdmp.bmp")); + if (sbmp) { + mime = "image/bmp"; + sflg = 1; + } +#endif + + char *bmp = strstr(fname, ".bmp"); + if (bmp) { + mime = "image/bmp"; + } + char *html = strstr(fname, ".html"); + if (html) { + mime = "text/html"; + } + char *txt = strstr(fname, ".txt"); + if (txt) { + mime = "text/plain"; + } + + WSContentSend_P(HTTP_SCRIPT_MIMES, fname, mime); + + if (sflg) { +#ifdef USE_DISPLAY_DUMP + + #define fileHeaderSize 14 + #define infoHeaderSize 40 + if (buffer) { + uint8_t *bp = buffer; + uint8_t *lbuf = (uint8_t*)calloc(Settings.display_width + 2, 3); + uint8_t *lbp; + uint8_t fileHeader[fileHeaderSize]; + createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader); + Webserver->client().write((uint8_t *)fileHeader, fileHeaderSize); + uint8_t infoHeader[infoHeaderSize]; + createBitmapInfoHeader(Settings.display_height, Settings.display_width, infoHeader ); + Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); + for (uint32_t lins = 0; lins>1; + } + bp++; + } + Webserver->client().write((const char*)lbuf, Settings.display_width * 3); + } + if (lbuf) free(lbuf); + Webserver->client().stop(); + } +#endif + } else { + File file = fsp->open(fname,FILE_READ); + uint32_t siz = file.size(); + uint32_t len = sizeof(buff); + while (siz > 0) { + if (len>siz) len = siz; + file.read((uint8_t *)buff, len); + Webserver->client().write((const char*)buff, len); + siz -= len; + } + file.close(); + } + Webserver->client().stop(); +} +#endif + +void ScriptFullWebpage(void) { + uint32_t fullpage_refresh=10000; + if (!HttpCheckPriviledgedAccess()) { return; } + + String stmp = Webserver->uri(); + + if (Webserver->hasArg("m")) { + if (Webserver->hasArg("sv")) { + Script_Check_HTML_Setvars(); + } + WSContentBegin(200, CT_HTML); + ScriptWebShow('w'); + WSContentEnd(); + Serial.printf("fwp update sv %s\n",stmp.c_str() ); + return; + + + + + return; + } else { + Serial.printf("fwp other %s\n",stmp.c_str() ); + } + + WSContentBegin(200, CT_HTML); + const char *title = "Full Screen"; + WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, SettingsText(SET_DEVICENAME), title, fullpage_refresh); + WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh); + + + + + + WSContentSend_P(PSTR("
")); + ScriptWebShow('w'); + WSContentSend_P(PSTR("
")); + + ScriptWebShow('x'); + + WSContentStop(); +} +#endif + +void Script_Check_HTML_Setvars(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (Webserver->hasArg("sv")) { + String stmp = Webserver->arg("sv"); + Serial.printf("fwp has arg dv %s\n", stmp.c_str()); + 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 = + ""; + +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 = + "
"; + + +#ifdef USE_GOOGLE_CHARTS +const char SCRIPT_MSG_GTABLE[] PROGMEM = + "" + "" + "" + ""; + +const char SCRIPT_MSG_TABLE[] PROGMEM = + ""; +const char SCRIPT_MSG_GAUGE[] PROGMEM = + ""; +const char SCRIPT_MSG_TIMELINE[] PROGMEM = + ""; + + +const char SCRIPT_MSG_GTABLEa[] PROGMEM = + ""; + +const char SCRIPT_MSG_GOPT1[] PROGMEM = +"title:'%s',isStacked:false"; + +const char SCRIPT_MSG_GAUGEOPT[] PROGMEM = +"max:%d,redFrom:%d,redTo:%d,yellowFrom:%d,yellowTo:%d"; + +const char SCRIPT_MSG_GOPT2[] PROGMEM = +"showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; + +const char SCRIPT_MSG_GOPT3[] PROGMEM = +"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; + +const char SCRIPT_MSG_GOPT4[] PROGMEM = + +"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'},theme: 'maximized'"; + +const char SCRIPT_MSG_GOPT5[] PROGMEM = +"new Date(0,1,1,%d,%d)"; + +const char SCRIPT_MSG_GOPT6[] PROGMEM = +"title:'%s',isStacked:false,vAxis:{viewWindow:{min:%d,max:%d}}%s"; + +const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; + +#define GLIBS_MAIN 1<<0 +#define GLIBS_TABLE 1<<1 +#define GLIBS_GAUGE 1<<2 +#define GLIBS_TIMELINE 1<<3 + +#define MAX_GARRAY 4 + + +char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint16_t *rentries, uint16_t *ipos) { +struct T_INDEX ind; +uint8_t vtype; +uint16 entries = 0; +uint16_t cipos = 0; + + uint8_t anum = 0; + while (anum=entries) { + if (!entries) { + entries = len; + } + + arrays[anum] = fa; + anum++; + } + } else { + + arrays[anum] = &glob_script_mem.fvars[index]; + anum++; + entries = 1; + } + } else { + lp = lp1; + break; + } + } + } + + *ranum = anum; + *rentries = entries; + *ipos = cipos; + return lp; +} + +char *gc_send_labels(char *lp,uint32_t anum) { + WSContentSend_PD("["); + for (uint32_t cnt = 0; cnt < anum + 1; cnt++) { + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + WSContentSend_PD(SCRIPT_MSG_GTE1, label); + + if (cntw", -2, 0); + } else { + web_script = Run_Scripter(">W", -2, 0); + } + + if (web_script==99) { + char tmp[256]; + uint8_t optflg = 0; + uint8_t chartindex = 1; + uint8_t google_libs = 0; + char *lp = glob_script_mem.section_ptr + 2; + if (mc=='w') { + while (*lp) { + if (*lp=='\n') break; + lp++; + } + } + char *cv_ptr; + float cv_max=0; + float cv_inc=0; + float *cv_count=0; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + SCRIPT_SKIP_SPACES + if (!strncmp(lp, "%for ", 5)) { + + struct T_INDEX ind; + uint8_t vtype; + lp = isvar(lp + 5, &vtype, &ind, 0, 0, 0); + if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { + uint16_t index = glob_script_mem.type[ind.index].index; + cv_count = &glob_script_mem.fvars[index]; + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp , OPER_EQU, cv_count, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp , OPER_EQU, &cv_max, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp , OPER_EQU, &cv_inc, 0); + cv_ptr = lp; + goto nextwebline; + } else { + continue; + } + } else if (!strncmp(lp, "%next", 5)) { + if (cv_count) { + + *cv_count += cv_inc; + if (*cv_count<=cv_max) { + lp = cv_ptr; + } else { + cv_count = 0; + goto nextwebline; + } + } else { + goto nextwebline; + } + } else if (!strncmp(lp, "%=#", 3)) { + + lp = scripter_sub(lp + 1, 0); + goto nextwebline; + } + + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + char *lin = tmp; + if ((!mc && (*lin!='$')) || (mc=='w' && (*lin!='$'))) { +# 6589 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" + if (*lin=='@') { + lin++; + optflg = 1; + } else { + optflg = 0; + } + + if (!strncmp(lin, "sl(", 3)) { + + char *lp = lin; + float min; + lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + + float max; + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); + SCRIPT_SKIP_SPACES + float val; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + char left[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, left, 0); + SCRIPT_SKIP_SPACES + char mid[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, mid, 0); + SCRIPT_SKIP_SPACES + char right[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, right, 0); + SCRIPT_SKIP_SPACES + + WSContentSend_PD(SCRIPT_MSG_SLIDER, left,mid, right, (uint32_t)min, (uint32_t)max, (uint32_t)val, vname); + + } else if (!strncmp(lin, "ck(", 3)) { + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + const char *cp; + uint8_t uval; + if (val>0) { + 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; cnt < bcnt; cnt++) { + float val; + char *slp = lp; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char ontxt[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, ontxt, 0); + SCRIPT_SKIP_SPACES + char offtxt[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, offtxt, 0); + + char *cp; + uint8_t uval; + if (val>0) { + 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
"), lin); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"), lin); + } + } + } + + } else { + + if (*lin==mc) { + +#ifdef USE_GOOGLE_CHARTS + lin++; +exgc: + char *lp; + if (!strncmp(lin, "gc(", 3)) { + + lp = lin + 3; + SCRIPT_SKIP_SPACES + const char *type; + const char *func; + char options[312]; + uint8_t nanum = MAX_GARRAY; + uint8_t y2f = 0; + uint8_t tonly = 0; + char ctype; + ctype = *lp; + lp++; + if (!(google_libs & GLIBS_MAIN)) { + google_libs |= GLIBS_MAIN; + WSContentSend_PD(SCRIPT_MSG_GTABLE); + } + switch (ctype) { + case 'l': + type = PSTR("LineChart"); + break; + case 'b': + type = PSTR("BarChart"); + break; + case 'p': + type = PSTR("PieChart"); + break; + case 'g': + type = PSTR("Gauge"); + if (!(google_libs & GLIBS_GAUGE)) { + google_libs |= GLIBS_GAUGE; + WSContentSend_PD(SCRIPT_MSG_GAUGE); + } + break; + case 't': + type = PSTR("Table"); + if (!(google_libs & GLIBS_TABLE)) { + google_libs |= GLIBS_TABLE; + WSContentSend_PD(SCRIPT_MSG_TABLE); + } + break; + case 'T': + type = PSTR("Timeline"); + if (!(google_libs & GLIBS_TIMELINE)) { + google_libs |= GLIBS_TIMELINE; + WSContentSend_PD(SCRIPT_MSG_TIMELINE); + } + break; + case 'h': + type = PSTR("Histogram"); + break; + case 'c': + type = PSTR("ColumnChart"); + break; + case 'C': + type = PSTR("ComboChart"); + break; + case 'e': + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); + chartindex++; + goto nextwebline; + break; + default: + + goto nextwebline; + break; + } + if (ctype=='l' && *lp=='f') { + lp++; + func = PSTR(",curveType:'function'"); + } else { + func = ""; + } + if (*lp=='2') { + lp++; + nanum = 2; + y2f = 1; + } + if (*lp=='t') { + lp++; + tonly = 1; + } + SCRIPT_SKIP_SPACES + + + + float *arrays[MAX_GARRAY]; + uint8_t anum = 0; + uint16_t entries = 0; + uint16_t ipos = 0; + lp = gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); + + if (anum>nanum) { + goto nextwebline; + } + + + + if (ctype=='T') { + if (anum && !(entries & 1)) { + WSContentSend_PD(SCRIPT_MSG_GTABLEa); + WSContentSend_PD(SCRIPT_MSG_GTABLEd); + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + for (uint32_t ind = 0; ind < anum; ind++) { + char lbl[16]; + GetTextIndexed(lbl, sizeof(lbl), ind, label); + for (uint32_t cnt = 0; cnt < entries; cnt += 2) { + WSContentSend_PD("['%s',",lbl); + float *fp = arrays[ind]; + uint32_t time = fp[cnt]; + WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); + WSContentSend_PD(","); + time = fp[cnt + 1]; + WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); + WSContentSend_PD("]"); + if (cnt < entries - 2) { WSContentSend_PD(","); } + } + if (ind < anum - 1) { WSContentSend_PD(","); } + } + snprintf_P(options,sizeof(options), SCRIPT_MSG_GOPT4); + } + } else { + + WSContentSend_PD(SCRIPT_MSG_GTABLEa); + lp = gc_send_labels(lp, anum); + + + + char label[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, label, 0); + SCRIPT_SKIP_SPACES + + int16_t divflg = 1; + int16_t todflg = -1; + if (!strncmp(label, "cnt", 3)) { + char *cp = &label[3]; + + todflg = strtol(cp, &cp, 10); + if (todflg>=entries) todflg = entries - 1; + if (*cp=='/') { + cp++; + divflg = strtol(cp, &cp, 10); + } + } else { + char *lp = label; + if (!strncmp(label, "wdh:", 4)) { + + todflg = -2; + lp += 4; + } + uint16 segments = 1; + for (uint32_t cnt = 0; cnt < strlen(lp); cnt++) { + if (lp[cnt]=='|') { + segments++; + } + } + divflg = entries / segments; + } + + uint32_t aind = ipos; + if (aind>=entries) aind = entries - 1; + for (uint32_t cnt = 0; cnt < entries; cnt++) { + WSContentSend_PD("['"); + char lbl[16]; + if (todflg>=0) { + sprintf(lbl, "%d", todflg / divflg); + todflg++; + if (todflg >= entries) { + todflg = 0; + } + } else { + if (todflg==-1) { + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label); + } else { + + GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label + 4); + sprintf(lbl, "%s-%02d", lbl, aind % divflg); + } + } + WSContentSend_PD(lbl); + WSContentSend_PD("',"); + for (uint32_t ind = 0; ind < anum; ind++) { + char acbuff[32]; + float *fp = arrays[ind]; + f2char(fp[aind], glob_script_mem.script_dprec, glob_script_mem.script_lzero, acbuff); + WSContentSend_PD("%s", acbuff); + if (ind=entries) { + aind = 0; + } + } + + if (tonly) { + WSContentSend_PD("]);"); + goto nextwebline; + } + + char header[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, header, 0); + SCRIPT_SKIP_SPACES + + switch (ctype) { + case 't': + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); + break; + default: + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); + break; + } + + if (y2f) { + + SCRIPT_SKIP_SPACES + float max1; + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); + SCRIPT_SKIP_SPACES + float max2; + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); + SCRIPT_SKIP_SPACES + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); + } else { + SCRIPT_SKIP_SPACES + if (ctype!='g') { + if (*lp!=')') { + float max1; + lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); + SCRIPT_SKIP_SPACES + float max2; + lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); + SCRIPT_SKIP_SPACES + snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); + } + } + } + + if (ctype=='g') { + float yellowFrom; + lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); + SCRIPT_SKIP_SPACES + float redFrom; + lp = GetNumericArgument(lp, OPER_EQU, &redFrom, 0); + SCRIPT_SKIP_SPACES + float maxValue; + lp = GetNumericArgument(lp, OPER_EQU, &maxValue, 0); + SCRIPT_SKIP_SPACES + float redTo = maxValue; + float yellowTo = redFrom; + snprintf_P(options, sizeof(options), SCRIPT_MSG_GAUGEOPT, (uint32_t)maxValue, (uint32_t)redFrom, (uint32_t)redTo, + (uint32_t)yellowFrom, (uint32_t)yellowTo); + } + } + WSContentSend_PD(SCRIPT_MSG_GTABLEb, options); + WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); + chartindex++; + } else { + WSContentSend_PD(PSTR("%s"), lin); + } +#else + lin++; + WSContentSend_PD(PSTR("%s"), lin); + } else { + +#endif + } + } + } +nextwebline: + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } +} +#endif + + +#ifdef USE_SENDMAIL + +void script_send_email_body(void(*func)(char *)) { +uint8_t msect = Run_Scripter(">m", -2, 0); + if (msect==99) { + char tmp[256]; + char *lp = glob_script_mem.section_ptr + 2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + + func(tmp); + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } else { + + func((char*)"*"); + } +} +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT +void ScriptJsonAppend(void) { + uint8_t web_script = Run_Scripter(">J", -2, 0); + if (web_script==99) { + char tmp[256]; + char *lp = glob_script_mem.section_ptr + 2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); + ResponseAppend_P(PSTR("%s"), tmp); + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } +} +#endif + + +bool RulesProcessEvent(char *json_event) { + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E", 2, json_event); + return true; +} + +#ifdef ESP32 +#ifdef USE_SCRIPT_TASK + +#ifndef STASK_STACK +#define STASK_STACK 8192 +#endif + +#if 1 + +struct ESP32_Task { + uint16_t task_timer; + TaskHandle_t task_t; +} esp32_tasks[2]; + + +void script_task1(void *arg) { + + + while (1) { + + + + + + delay(esp32_tasks[0].task_timer); + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">t1", 3, 0); + } + } +} + +void script_task2(void *arg) { + + + while (1) { + + + + + + delay(esp32_tasks[1].task_timer); + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">t2", 3, 0); + } + } +} +uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) { + + BaseType_t res = 0; + if (core > 1) { core = 1; } + if (num == 1) { + if (esp32_tasks[0].task_t) { vTaskDelete(esp32_tasks[0].task_t); } + res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &esp32_tasks[0].task_t, core); + esp32_tasks[0].task_timer = time; + } else { + if (esp32_tasks[1].task_t) { vTaskDelete(esp32_tasks[1].task_t); } + res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &esp32_tasks[1].task_t, core); + esp32_tasks[1].task_timer = time; + } + return res; +} +#else + +uint16_t task_timer1; +uint16_t task_timer2; +TaskHandle_t task_t1; +TaskHandle_t task_t2; + +void script_task1(void *arg) { + while (1) { + delay(task_timer1); + Run_Scripter(">t1", 3, 0); + } +} + +void script_task2(void *arg) { + while (1) { + delay(task_timer2); + Run_Scripter(">t2", 3, 0); + } +} + +uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) { + + BaseType_t res = 0; + if (core > 1) { core = 1; } + if (num == 1) { + if (task_t1) { vTaskDelete(task_t1); } + res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &task_t1, core); + task_timer1 = time; + } else { + if (task_t2) { vTaskDelete(task_t2); } + res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &task_t2, core); + task_timer2 = time; + } + return res; +} +#endif + +#endif +#endif + +#ifdef SCRIPT_GET_HTTPS_JP +#ifdef ESP8266 +#include "WiFiClientSecureLightBearSSL.h" +#else +#include +#endif + + +uint32_t call2https(const char *host, const char *path) { + if (global_state.wifi_down) return 1; + uint32_t status = 0; +#ifdef ESP32 + WiFiClientSecure *httpsClient; + httpsClient = new WiFiClientSecure; +#else + BearSSL::WiFiClientSecure_light *httpsClient; + httpsClient = new BearSSL::WiFiClientSecure_light(1024, 1024); +#endif + + httpsClient->setTimeout(1500); + + uint32_t retry = 0; + while ((!httpsClient->connect(host, 443)) && (retry < 5)) { + delay(100); + retry++; + } + if (retry == 5) { + return 2; + } + String request = String("GET ") + path + + " HTTP/1.1\r\n" + + "Host: " + host + + "\r\n" + "Connection: close\r\n\r\n"; + httpsClient->print(request); + + while (httpsClient->connected()) { + String line = httpsClient->readStringUntil('\n'); + if (line == "\r") { + break; + } + } + String result; + while (httpsClient->available()) { + String line = httpsClient->readStringUntil('\n'); + if (line!="") { + result += line; + } + } + httpsClient->stop(); + delete httpsClient; + Run_Scripter(">jp", 3, (char*)result.c_str()); + return 0; +} +#endif + + +void cpy2lf(char *dst, uint32_t dstlen, char *src) { + for (uint32_t cnt=0; cnt0) glob_script_mem.script_ram[len_decompressed] = 0; + + bitWrite(Settings.rule_once, 6, 1); + +#else + + bitWrite(Settings.rule_once, 6, 0); +#endif + +#ifdef USE_BUTTON_EVENT + for (uint32_t cnt = 0; cnt < MAX_KEYS; cnt++) { + script_button[cnt] = -1; + } +#endif + +#ifdef EEP_SCRIPT_SIZE + if (eeprom_init(EEP_SCRIPT_SIZE)) { + + 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; + + 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 USE_SCRIPT_FATFS>=0 + +#ifdef ESP32 + if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) { + SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); + } +#endif + fsp = &SD; + if (SD.begin(USE_SCRIPT_FATFS)) { +#else + +#ifdef ESP32 + + + fsp = &FFat; + if (FFat.begin(true)) { +#else + + fsp = &LittleFS; + if (fsp->begin()) { +#endif + +#endif + AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!")); + + 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 (fsp->exists(FAT_SCRIPT_NAME)) { + File file = fsp->open(FAT_SCRIPT_NAME, FILE_READ); + file.read((uint8_t*)script, FAT_SCRIPT_SIZE); + file.close(); + } + script[FAT_SCRIPT_SIZE - 1] = 0; + + 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 { + AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount failed!")); + glob_script_mem.script_sd_found = 0; + } +#endif + + +#ifdef LITTLEFS_SCRIPT_SIZE + +#ifdef ESP32 + + fsp = &SPIFFS; + + +#else + + fsp = &LittleFS; +#endif + char *script; + script = (char*)calloc(LITTLEFS_SCRIPT_SIZE + 4, 1); + if (!script) break; + LoadFile("/script.txt", (uint8_t*)script, LITTLEFS_SCRIPT_SIZE); + + glob_script_mem.script_ram = script; + glob_script_mem.script_size = LITTLEFS_SCRIPT_SIZE; + script[LITTLEFS_SCRIPT_SIZE-1] = 0; + + 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 + + + if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { + + memset(glob_script_mem.script_ram, 0 ,glob_script_mem.script_size); + strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D")); + bitWrite(Settings.rule_enabled, 0, 0); + } + + + { uint32_t ptr = (uint32_t)glob_script_mem.script_pram; + ptr &= 0xfffffffc; + ptr += 4; + 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\n", 3, 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: + ScripterEvery100ms(); + break; + case FUNC_EVERY_SECOND: + ScriptEverySecond(); + break; + case FUNC_COMMAND: + result = ScriptCommand(); + break; + case FUNC_SET_POWER: +#ifdef SCRIPT_POWER_SECTION + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P", 2, 0); +#else + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">E", 2, 0); + result = event_handeled; + } +#endif + break; + case FUNC_RULES_PROCESS: + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">E", 2, mqtt_data); + result = event_handeled; + } + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_RULES); + break; +#ifdef USE_SCRIPT_WEB_DISPLAY + case FUNC_WEB_ADD_MAIN_BUTTON: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptWebShow('$'); +#ifdef SCRIPT_FULL_WEBPAGE + uint8_t web_script = Run_Scripter(">w", -2, 0); + if (web_script==99) { + char bname[48]; + cpy2lf(bname, sizeof(bname), glob_script_mem.section_ptr + 3); + WSContentSend_PD(HTTP_WEB_FULL_DISPLAY, bname); + Webserver->on("/sfd", ScriptFullWebpage); +#ifdef USE_SCRIPT_FATFS + Webserver->onNotFound(ScriptGetSDCard); +#endif + } +#endif + } + break; +#endif + case FUNC_WEB_ADD_HANDLER: + Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); + Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); + Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);}, script_upload_start); + Webserver->on("/exs", HTTP_GET, ScriptExecuteUploadSuccess); + +#ifdef USE_SCRIPT_FATFS + Webserver->on("/u13", HTTP_POST,[]() { Webserver->sendHeader("Location","/u13");Webserver->send(303);}, script_upload); + Webserver->on("/u13", 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(); + } +#ifdef USE_SCRIPT_GLOBVARS + Script_Stop_UDP(); +#endif + 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(0); + } + break; +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT + case FUNC_JSON_APPEND: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptJsonAppend(); + } + break; +#endif + +#ifdef USE_BUTTON_EVENT + case FUNC_BUTTON_PRESSED: + if (bitRead(Settings.rule_enabled, 0)) { + if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { + script_button[XdrvMailbox.index] = XdrvMailbox.payload; + Run_Scripter(">b", 2, 0); + } + } + break; +#endif + +#ifdef USE_SCRIPT_GLOBVARS + case FUNC_LOOP: + Script_PollUdp(); + break; +#endif + + } + return result; +} + + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" +#ifdef USE_KNX +# 51 "/workspace/Tasmota/tasmota/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_SCENE , 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", + D_KNX_TX_SCENE , + 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", + D_KNX_RX_SCENE , + 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" +#define D_CMND_KNXTXSCENE "Tx_Scene" + + +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 "|" D_CMND_KNXTXSCENE ; + +void (* const KnxCommand[])(void) PROGMEM = { + &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb, &CmndKnxTxScene }; + +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 ); +# 477 "/workspace/Tasmota/tasmota/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_SWT1 + 4; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1; i < GPIO_KEY1 + 4; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + } + for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT1_NP + 4; ++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_KEY1_NP + 4; ++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; } +#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; } + +#if defined(USE_ENERGY_SENSOR) + + 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; + } +#endif + +#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; + device_param[KNX_SCENE-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) { + + sprintf(tempchar,"%d",msg.data[0]); + } else if (chan->type == KNX_SCENE) { + + uint8_t tempvar = knx.data_to_1byte_uint(msg.data); + dtostrfd(tempvar,0,tempchar); + } 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; + } + } + } + else if (chan->type == KNX_SCENE) + { + if (!toggle_inhibit) { + char command[25]; + + snprintf_P(command, sizeof(command), PSTR("event KNX_SCENE=%s"), 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(void) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; +# 714 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" + 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_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 CmndKnxTxScene(void) +{ + if ( (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled ) { + + uint8_t i = KNX_GA_Search(KNX_SCENE); + if ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + + uint8_t tempvar = TextToInt(XdrvMailbox.data); + dtostrfd(tempvar,0,XdrvMailbox.data); + + knx.write_1byte_uint(KNX_addr, tempvar); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1byte_uint(KNX_addr, tempvar); + knx.write_1byte_uint(KNX_addr, tempvar); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), + device_param_ga[KNX_SCENE-1], XdrvMailbox.data, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + 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.network_down) { knx.loop(); } + break; + case FUNC_EVERY_50_MSECOND: + if (toggle_inhibit) { + toggle_inhibit--; + } + break; + case FUNC_ANY_KEY: + KnxSendButtonPower(); + 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(PSTR("/kn"), HandleKNXConfiguration); + break; +#endif +#endif + case FUNC_COMMAND: + result = DecodeCommand(kKnxCommands, KnxCommand); + break; + case FUNC_PRE_INIT: + KNX_INIT(); + break; + + + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" +#ifdef USE_HOME_ASSISTANT + +#define XDRV_12 12 + + +const char kHAssJsonSensorTypes[] PROGMEM = + D_JSON_TEMPERATURE "|" D_JSON_DEWPOINT "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" + D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" D_JSON_TOTAL_START_TIME "|" + D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY "|" + D_JSON_CO2 "|" D_JSON_ECO2 "|" D_JSON_TVOC "|Red|Green|Blue|CCT|" D_PROXIMITY "|"; + + +const char kHAssJsonSensorUnits[] PROGMEM = + "||||" + "VA|%|A|cm|Hz|%|lux|" + "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³|Cos φ|W| |" + "VAr|kWh|kWh|V|kg|kWh|" + "ppm|ppm|ppb|R|G|B|" D_UNIT_KELVIN "| |"; + +const char kHAssJsonSensorDevCla[] PROGMEM = + "dev_cla\":\"temperature|ic\":\"mdi:weather-rainy|dev_cla\":\"pressure|dev_cla\":\"pressure|" + "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" + "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" + "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|ic\":\"mdi:progress-clock|" + "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power|" + "ic\":\"mdi:molecule-co2|ic\":\"mdi:molecule-co2|ic\":\"mdi:air-filter|" + "ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:temperature-kelvin|ic\":\"mdi:ruler|dev_cla\":\"illuminance|"; + + + +const char HASS_DISCOVER_BASE[] PROGMEM = + "{\"name\":\"%s\"," + "\"stat_t\":\"%s\""; + +const char HASS_DISCOVER_SENSOR[] PROGMEM = + ",\"unit_of_meas\":\"%s\",\"%s\"," + "\"frc_upd\":true," + "\"val_tpl\":\"{{value_json['%s']['%s']"; + +const char HASS_DISCOVER_SENSOR_LWT[] PROGMEM = + ",\"avty_t\":\"%s\"," + "\"pl_avail\":\"" MQTT_LWT_ONLINE "\"," + "\"pl_not_avail\":\"" MQTT_LWT_OFFLINE "\""; + +const char HASS_DISCOVER_RELAY[] PROGMEM = + ",\"cmd_t\":\"%s\"," + "\"val_tpl\":\"{{value_json.%s}}\"," + "\"pl_off\":\"%s\"," + "\"pl_on\":\"%s\""; + +const char HASS_DISCOVER_BIN_SWITCH[] PROGMEM = + ",\"val_tpl\":\"{{value_json.%s}}\"," + "\"frc_upd\":true," + "\"pl_on\":\"%s\"," + "\"pl_off\":\"%s\""; + +const char HASS_DISCOVER_BIN_PIR[] PROGMEM = + ",\"val_tpl\":\"{{value_json.%s}}\"," + "\"frc_upd\":true," + "\"pl_on\":\"%s\"," + "\"off_dly\":1"; + +const char HASS_DISCOVER_BASE_LIGHT[] PROGMEM = + ",\"bri_cmd_t\":\"%s\"," + "\"bri_stat_t\":\"%s\"," + "\"bri_scl\":100," + "\"on_cmd_type\":\"%s\"," + "\"bri_val_tpl\":\"{{value_json.%s}}\""; + +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\"," + "\"whit_val_scl\":100," + "\"whit_val_tpl\":\"{{value_json." D_CMND_WHITE "}}\""; + +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_SHUTTER_BASE[] PROGMEM = + ",\"cmd_t\":\"%s\"," + "\"pl_open\":\"ShutterOpen%d\"," + "\"pl_cls\":\"ShutterClose%d\"," + "\"pl_stop\":\"ShutterStop%d\"," + "\"opt\":false," + "\"ret\":false," + "\"qos\":1"; + +const char HASS_DISCOVER_SHUTTER_POS[] PROGMEM = + ",\"pos_t\":\"%s%d\"," + "\"pos_clsd\":0," + "\"pos_open\":100," + "\"set_pos_t\":\"%s%d\""; + +const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = + ",\"json_attr_t\":\"%s\"," + "\"unit_of_meas\":\"%%\"," + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," + "\"ic\":\"mdi:information-outline\""; + +const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"dev\":{\"ids\":[\"%06X\"]," + "\"name\":\"%s\"," + "\"mdl\":\"%s\"," + "\"sw\":\"%s%s\"," + "\"mf\":\"Tasmota\"}"; + +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"dev\":{\"ids\":[\"%06X\"]}"; + +const char HASS_TRIGGER_TYPE[] PROGMEM = + "{\"atype\":\"trigger\"," + "\"t\":\"%sT\"," + "\"pl\":\"{\\\"TRIG\\\":\\\"%s\\\"}\"," + "\"type\":\"%s\"," + "\"stype\":\"%s\"," + "\"dev\":{\"ids\":[\"%06X\"]}}"; + +const char kHAssTriggerType[] PROGMEM = + "none|button_short_press|button_long_press|button_double_press"; + +const char kHAssTriggerTypeButtons[] PROGMEM = + "|button_short_press|button_double_press|button_triple_press|button_quadruple_press|button_quintuple_press|button_long_press|"; + +const char kHAssTriggerStringButtons[] PROGMEM = + "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|"; + +const char kHAssRelayType[] PROGMEM = + "|RL|LI|SHT|FAN"; + +const char kHAssError1[] PROGMEM = + "HASS: MQTT discovery failed due to too long topic or device/friendly name. Please shorten topic and/or device/friendly name. Failed to format"; + +const char kHAssError2[] PROGMEM = + "HASS: The configuration of the Relays is wrong, there is a Light that is using an index higher than the number of the validated relay.\n " + "The Relays have priority over the Lights, an incorrect order could lead to an erroneous Light control.\n " + "Please update your configuration to avoid inconsistent results.\n " + "Entities for Relays and Lights will not be available in Home Assistant until the configuration will be updated."; + +const char kHAssError3[] PROGMEM = + "HASS: Unable to create one or more entities from Json data, please check your configuration. Failed to parse"; + +uint8_t hass_init_step = 0; +uint8_t hass_mode = 0; +int hass_tele_period = 0; + + + +const char HASS_DISCOVER_DEVICE[] PROGMEM = + "{\"ip\":\"%s\"," + "\"dn\":\"%s\"," + "\"fn\":[%s]," + "\"hn\":\"%s\"," + "\"mac\":\"%s\"," + "\"md\":\"%s\"," + "\"ty\":%d," + "\"ofln\":\"" MQTT_LWT_OFFLINE "\"," + "\"onln\":\"" MQTT_LWT_ONLINE "\"," + "\"state\":[\"%s\",\"%s\",\"%s\",\"%s\"]," + "\"sw\":\"%s\"," + "\"t\":\"%s\"," + "\"ft\":\"%s\"," + "\"tp\":[\"%s\",\"%s\",\"%s\"]," + "\"rl\":[%s],\"swc\":[%s],\"btn\":[%s]," + "\"so\":{\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," + "\"30\":%d,\"68\":%d,\"73\":%d,\"80\":%d,\"82\":%d}," + "\"lk\":%d,\"lt_st\":%d,\"ver\":1}"; + +typedef struct HASS { + uint16_t Relay[MAX_RELAYS]; + char RelLst[MAX_RELAYS*2]; + bool RelPst; +} HASS; + +void HassDiscoveryRelays(struct HASS &Hass) +{ + Hass = {.Relay={0,0,0,0,0,0,0,0}, .RelLst={'\0'}}; + uint16_t Shutter[8] = {0,0,0,0,0,0,0,0}; + uint8_t lightidx = MAX_RELAYS + 1; + bool iFan = false; + + Hass.RelPst = devices_present > 0; + +#ifdef ESP8266 + if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { iFan = true;} +#endif + + if (Light.subtype > LST_NONE) { + if (!light_controller.isCTRGBLinked()) { + lightidx = devices_present - 2; + } else { + lightidx = devices_present - 1; + } + } + + if (Light.device > 0 && Settings.flag3.pwm_multi_channels) { + lightidx = devices_present - Light.subtype; + } + + for (uint32_t i = 0; i < MAX_RELAYS; i++) { + + if (i < devices_present) { + +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t k = 0; k < MAX_SHUTTERS; k++) { + if (0 == Settings.shutter_startrelay[k]) { + break; + } else { + if (Settings.shutter_startrelay[k] > 0 && Settings.shutter_startrelay[k] <= MAX_RELAYS) { + Shutter[Settings.shutter_startrelay[k]-1] = Shutter[Settings.shutter_startrelay[k]] = 1; + } + } + } + } +#endif + + if (Shutter[i] != 0) { + Hass.Relay[i] = 3; + } else { + if (i >= lightidx || (iFan && i == 0)) { + Hass.Relay[i] = 2; + } else { + if (!iFan) { + Hass.Relay[i] = 1; + } + } + } + } + snprintf_P(Hass.RelLst, sizeof(Hass.RelLst), PSTR("%s%s%d"), Hass.RelLst, (i > 0 ? "," : ""), Hass.Relay[i]); + } +} + +void NewHAssDiscovery(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[200]; + char stemp3[TOPSZ]; + char stemp4[TOPSZ]; + char unique_id[30]; + char relays[TOPSZ]; + char *state_topic = stemp1; + bool SerialButton = false; + bool TuyaMod = false; + + stemp2[0] = '\0'; + struct HASS Hass; + HassDiscoveryRelays(Hass); + + uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; + for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { + char fname[TOPSZ]; + snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); + snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%s"), stemp2, (i > 0 ? "," : ""), (i < maxfn) ? fname : "null"); + } + + stemp3[0] = '\0'; + + auto discover_switches = ((KeyTopicActive(1) && (strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic))) || !Hass.RelPst); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & discover_switches) ? Settings.switchmode[i] : -1); + } + + stemp4[0] = '\0'; + + for (uint32_t i = 0; i < MAX_KEYS; i++) { + +#ifdef ESP8266 + if (i == 0 && (SONOFF_DUAL == my_module_type )) { SerialButton = true; } + if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } +#endif + + snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%d"), stemp4, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons)); + SerialButton = false; + } + + mqtt_data[0] = '\0'; + + + String mac_address = WiFi.macAddress(); + mac_address.replace(":", ""); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%s"), mac_address.c_str()); + snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id); + + + masterlog_level = 4; + if (!Settings.flag.hass_discovery) { + Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME), + stemp2, my_hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), + my_version, mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, + Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, + Settings.flag3.mqtt_buttons, Settings.flag3.shutter_mode, Settings.flag4.alexa_ct_range, light_controller.isCTRGBLinked(), Light.subtype); + } + MqttPublish(stopic, true); + + if (!Settings.flag.hass_discovery) { + snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), unique_id); + Response_P(PSTR("{\"sn\":")); + MqttShowSensor(); + ResponseAppend_P(PSTR(",\"ver\":1}")); + MqttPublish(stopic, true); + } + masterlog_level = 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("%s (%u/%u):"), kHAssError1, 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 LightControl = light_controller.isCTRGBLinked(); + bool PwmMulti = Settings.flag3.pwm_multi_channels; + bool is_topic_light = false; + bool ind_light = false; + bool ct_light = false; + bool wt_light = false; + bool err_flag = false; + bool TuyaMod = false; + bool PwmMod = false; + bool FanMod = false; + uint8_t ShowTopic; + + uint8_t dimmer = 1; + uint8_t valid_relay = 0; + uint8_t max_lights = 1; + uint8_t TuyaRel = 0; + uint8_t TuyaRelInv = 0; + uint8_t TuyaDim = 0; + uint8_t shutter_mask = 0; + + #ifdef ESP8266 + if (PWM_DIMMER == my_module_type ) { PwmMod = true; } + if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { FanMod = true; } + if (SONOFF_DUAL == my_module_type) { valid_relay = 2; } + if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } + #endif + + + + if (PwmMulti) { max_lights = Light.subtype; } + + if (!LightControl) { + ind_light = true; + if (!PwmMulti) { max_lights = 2;} + } + +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_RELAYS) { + bitSet(shutter_mask, Settings.shutter_startrelay[i] -1); + bitSet(shutter_mask, Settings.shutter_startrelay[i]); + } + } + } +#endif + + for (uint32_t i = 1; i <= MAX_RELAYS; i++) + { + +#ifdef USE_TUYA_MCU + TuyaRel = TuyaGetDpId((TUYA_MCU_FUNC_REL1+ i-1) + active_device - 1); + TuyaRelInv = TuyaGetDpId((TUYA_MCU_FUNC_REL1_INV+ i-1) + active_device - 1); + TuyaDim = TuyaGetDpId((TUYA_MCU_FUNC_DIMMER) + active_device - 1); +#endif + + masterlog_level = ShowTopic = 4; + + bool RelayX = PinUsed(GPIO_REL1, i-1) || (valid_relay >= i) || (TuyaRel > 0 && TuyaMod) || (TuyaRelInv > 0 && TuyaMod); + is_topic_light = Settings.flag.hass_light && RelayX || light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); + 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 (bitRead(shutter_mask, i-1)) { + + } else if ((i < Light.device) && !RelayX) { + err_flag = true; + AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s"), kHAssError2); + } else { + if (Settings.flag.hass_discovery && (RelayX || (Light.device > 0) && (max_lights > 0)) && !err_flag ) + { + char name[TOPSZ]; + char value_template[33]; + char prefix[TOPSZ]; + char *command_topic = stemp1; + char *state_topic = stemp2; + char *availability_topic = stemp3; + + ShowTopic = 0; + + if (i > MAX_FRIENDLYNAMES) { + snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i-1); + } else { + snprintf_P(name, sizeof(name), PSTR ("%s"), SettingsText(SET_FRIENDLYNAME1 + 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); + Response_P(HASS_DISCOVER_BASE, name, state_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); + + #ifdef USE_LIGHT + if (i >= Light.device) { + if (!RelayX || PwmMod || (TuyaDim > 0 && TuyaMod)) { + char *brightness_command_topic = stemp1; + strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); + char channel_num[9]; + if (PwmMulti) { + snprintf_P(channel_num, sizeof(channel_num), PSTR("Channel%d"), i); + } else { + if (!LightControl) { + snprintf_P(channel_num, sizeof(channel_num), PSTR("" D_CMND_DIMMER "%d"), dimmer); + dimmer ++; + } else { + snprintf_P(channel_num, sizeof(channel_num), PSTR("" D_CMND_DIMMER "")); + } + } + GetTopic_P(brightness_command_topic, CMND, mqtt_topic, channel_num); + TryResponseAppend_P(HASS_DISCOVER_BASE_LIGHT, brightness_command_topic, state_topic, stemp3, channel_num); + } + if ((ind_light && !PwmMulti) || LightControl) { + + if (Light.subtype >= LST_RGB) { + char *rgb_command_topic = stemp1; + + GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + 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); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); + } + if (LST_RGBW <= Light.subtype) { wt_light = true; } + if (LST_RGBCW == Light.subtype) { ct_light = true; } + } + + if ((!ind_light && ct_light) || (LST_COLDWARM == Light.subtype && + !PwmMulti && LightControl)) { + char *color_temp_command_topic = stemp1; + + GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); + ct_light = false; + } + if ((!ind_light && wt_light) || (LST_RGBW <= Light.subtype && + !PwmMulti && LightControl)) { + char *white_temp_command_topic = stemp1; + + GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); + wt_light = false; + } + ind_light = false; + max_lights--; + } + #endif + TryResponseAppend_P(PSTR("}")); + } + } + masterlog_level = ShowTopic; + MqttPublish(stopic, true); + } +} + +void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold, uint8_t single, uint8_t trg_start, uint8_t trg_end) +{ + + + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + char trigger2[8]; + uint8_t ShowTopic; + mqtt_data[0] = '\0'; + + for (uint8_t i = trg_start; i <= trg_end; i++) { + GetTextIndexed(trigger2, sizeof(trigger2), i, kHAssTriggerStringButtons); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d_%s"), ESP_getChipId(), key ? "SW" : "BTN", device + 1, key ? GetStateText(i) : trigger2); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/device_automation/%s/config"), unique_id); + + masterlog_level = ShowTopic = 4; + + if (Settings.flag.hass_discovery && present) { + char name[TOPSZ]; + char value_template[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + char jsoname[8]; + ShowTopic = 0; + + GetPowerDevice(value_template, device + 1, sizeof(value_template), key + Settings.flag.device_index_enable); + snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); + GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + char param[21]; + char subtype[9]; + uint8_t pload = toggle; + if (key) { + if ((i == 2 && toggle != 0) || (i == 3 && hold != 0)) { + if (i == 3) { pload = hold; } + GetTextIndexed(param, sizeof(param), pload, kHAssTriggerType); + snprintf_P(subtype, sizeof(subtype), PSTR("switch_%d"), device + 1); + Response_P(HASS_TRIGGER_TYPE, state_topic, GetStateText(i), param, subtype, ESP_getChipId()); + } else { mqtt_data[0] = '\0'; } + } else { + char trigger1[24]; + GetTextIndexed(trigger1, sizeof(trigger1), i, kHAssTriggerTypeButtons); + snprintf_P(subtype, sizeof(subtype), PSTR("button_%d"), device + 1); + if (i > 1 && single) { + mqtt_data[0] = '\0'; + } else { + Response_P(HASS_TRIGGER_TYPE, state_topic, trigger2, trigger1, subtype, ESP_getChipId()); + } + } + } + masterlog_level = ShowTopic; + MqttPublish(stopic, true); + } +} + +void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint8_t toggle, uint8_t pir) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + uint8_t ShowTopic; + + mqtt_data[0] = '\0'; + masterlog_level = 4; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SW_%d"), ESP_getChipId(), device + 1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + + masterlog_level = ShowTopic = 4; + + if (Settings.flag.hass_discovery && present ) { + if (!toggle || dual) { + char name[TOPSZ]; + char value_template[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + char jsoname[8]; + + ShowTopic = 0; + + GetPowerDevice(value_template, device + 1, sizeof(value_template), 1 + Settings.flag.device_index_enable); + snprintf_P(jsoname, sizeof(jsoname), PSTR("SWITCH%d"), device + 1); + GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + snprintf_P(name, sizeof(name), PSTR("%s Switch%d"), SettingsText(SET_DEVICENAME), device + 1); + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + if (!pir) { + TryResponseAppend_P(HASS_DISCOVER_BIN_SWITCH, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); + } else { + TryResponseAppend_P(HASS_DISCOVER_BIN_PIR, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2)); + } + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); +#ifdef DEEPSLEEP_LWT_HA_DISCOVERY + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); +#else + if (Settings.deepsleep == 0) + { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); + } +#endif + TryResponseAppend_P(PSTR("}")); + } + } + masterlog_level = ShowTopic; + MqttPublish(stopic, true); + +} + +void HAssAnnounceSwitches(void) +{ + for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) + { + uint8_t switch_present = 0; + uint8_t dual = 0; + uint8_t toggle = 1; + uint8_t hold = 0; + uint8_t pir = 0; + + if (PinUsed(GPIO_SWT1, switch_index)) { switch_present = 1; } + + if (KeyTopicActive(1) && strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic)) + { +# 696 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" + uint8_t swmode = Settings.switchmode[switch_index]; + + switch (swmode) { + case FOLLOW: + case FOLLOW_INV: + toggle = 0; + break; + case PUSHBUTTON: + case PUSHBUTTON_INV: + dual = 1; + break; + case PUSHBUTTONHOLD: + case PUSHBUTTONHOLD_INV: + dual = 1; + hold = 2; + break; + case TOGGLEMULTI: + hold = 3; + break; + case FOLLOWMULTI: + case FOLLOWMULTI_INV: + dual = 1; + toggle = 0; + hold = 3; + break; + case PUSHON: + case PUSHON_INV: + toggle = 0; + pir = 1; + } + + } else { switch_present = 0;} + + HAssAnnouncerTriggers(switch_index, switch_present, 1, toggle, hold, 0, 2, 3); + HAssAnnouncerBinSensors(switch_index, switch_present, dual, toggle, pir); + } +} + +void HAssAnnounceButtons(void) +{ + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) + { + uint8_t button_present = 0; + uint8_t single = 0; + +#ifdef ESP8266 + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) + { + button_present = 1; + } else +#endif + { + if (PinUsed(GPIO_KEY1, button_index)) { + button_present = 1; + } + } +# 766 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" + if (!Settings.flag3.mqtt_buttons) { + button_present = 0; + } else { + if (Settings.flag.button_single) { + single = 1; + } + } + HAssAnnouncerTriggers(button_index, button_present, 0, 0, 0, single, 1, 6); + } +} + +void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, bool nested, const char* SubKey) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + char subname[20]; + + mqtt_data[0] = '\0'; + + + NoAlNumToUnderscore(subname, MultiSubName); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP_getChipId(), sensorname, subname); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + if (Settings.flag.hass_discovery) + { + char name[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + masterlog_level = 0; + + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_DEVICENAME), sensorname, MultiSubName); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic); +#ifdef DEEPSLEEP_LWT_HA_DISCOVERY + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); +#else + if (Settings.deepsleep == 0) + { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); + } +#endif + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); + + + char jname[32]; + int sensor_index = GetCommandCode(jname, sizeof(jname), SubKey, kHAssJsonSensorTypes); + if (sensor_index > -1) { + + char param1[20]; + GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); + switch (sensor_index) { + case 0: + case 1: + snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); + break; + case 2: + case 3: + snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); + break; + } + char param2[50]; + GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); + TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); + + } else { + TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); + } + + if (nested) { TryResponseAppend_P(PSTR("['%s']"), SubKey); } + + if (subqty != 0) { TryResponseAppend_P(PSTR("[%d]"), subqty -1); } + + 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; + size_t sensordata_len = strlen(mqtt_data); + char sensordata[sensordata_len+2]; + strcpy(sensordata, mqtt_data); + + + + + + + + if (sensordata_len > 0) + { + + sensordata[0] = '{'; + + sensordata[sensordata_len] = '}'; + sensordata[sensordata_len+1] = '\0'; + + JsonParser parser(sensordata); + JsonParserObject root = parser.getRootObject(); + if (!root) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s '%s' (ERR1)"), kHAssError3, sensordata); + continue; + } + for (auto sensor_key : root) + { + + const char *sensorname = sensor_key.getStr(); + JsonParserObject sensors = sensor_key.getValue().getObject(); + + if (!sensors) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s '%s' (ERR2)"), kHAssError3, sensorname); + continue; + } + + for (auto subsensor_key_token : sensors) + { + const char * subsensor_key = subsensor_key_token.getStr(); + JsonParserToken subsensor = subsensor_key_token.getValue(); + if (subsensor.isObject()) { + + JsonParserObject subsensors = subsensor.getObject(); + char NewSensorName[20]; + for (auto subsensor2_key : subsensors) { + snprintf_P(NewSensorName, sizeof(NewSensorName), PSTR("%s %s"), subsensor_key, subsensor2_key.getStr()); + HAssAnnounceSensor(sensorname, subsensor_key, NewSensorName, 0, 1, subsensor2_key.getStr()); + } + } else if (subsensor.isArray()) { + + JsonParserArray subsensors = subsensor.getArray(); + uint8_t subqty = subsensors.size(); + char MultiSubName[20]; + for (int i = 1; i <= subqty; i++) { + snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor_key, i); + HAssAnnounceSensor(sensorname, subsensor_key, MultiSubName, i, 0, subsensor_key); + } + } else { + HAssAnnounceSensor(sensorname, subsensor_key, subsensor_key, 0, 0, subsensor_key);} + } + } + } + yield(); + } while (hass_xsns_index != 0); +} + +void HAssAnnounceShutters(void) +{ +#ifdef USE_SHUTTER + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + uint8_t ShowTopic; + + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + mqtt_data[0] = '\0'; + masterlog_level = ShowTopic = 4; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SHT_%d"), ESP_getChipId(), i + 1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/cover/%s/config"), unique_id); + + if (Settings.flag.hass_discovery && Settings.flag3.shutter_mode && Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_RELAYS) { + ShowTopic = 0; + if (i > MAX_FRIENDLYNAMES) { + snprintf_P(stemp1, sizeof(stemp1), PSTR("%s Shutter %d"), SettingsText(SET_DEVICENAME), i + 1); + } else { + snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), SettingsText(SET_FRIENDLYNAME1 + i)); + } + GetTopic_P(stemp2, TELE, mqtt_topic, D_RSLT_STATE); + Response_P(HASS_DISCOVER_BASE, stemp1, stemp2); + + GetTopic_P(stemp1, TELE, mqtt_topic, S_LWT); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, stemp1); + + GetTopic_P(stemp1, CMND, mqtt_topic, PSTR("Backlog")); + TryResponseAppend_P(HASS_DISCOVER_SHUTTER_BASE, stemp1, i + 1, i + 1, i + 1); + + GetTopic_P(stemp1, STAT, mqtt_topic, PSTR("SHUTTER")); + GetTopic_P(stemp2, CMND, mqtt_topic, PSTR("ShutterPosition")); + TryResponseAppend_P(HASS_DISCOVER_SHUTTER_POS, stemp1, i + 1, stemp2, i + 1); + + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); + TryResponseAppend_P(PSTR("}")); + } + + masterlog_level = ShowTopic; + MqttPublish(stopic, true); + } +#endif +} + +void HAssAnnounceDeviceInfoAndStatusSensor(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + uint8_t ShowTopic; + + + mqtt_data[0] = '\0'; + masterlog_level = ShowTopic = 4; + + 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[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + ShowTopic = 0; + snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_DEVICENAME)); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME), + ModuleName().c_str(), my_version, my_image); + TryResponseAppend_P(PSTR("}")); + } + masterlog_level = ShowTopic; + MqttPublish(stopic, true); + + if (!Settings.flag.hass_discovery) { + masterlog_level = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG "Home Assistant MQTT Discovery disabled.")); + } +} + +void HAssPublishStatus(void) +{ + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_CMND_MODULE " or " D_CMND_TEMPLATE"\":\"%s\"," + "\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\"," + "\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(), + GetUptime().c_str(), my_hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), + WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), 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 (Settings.flag.hass_discovery || (1 == hass_mode)) + { + hass_mode = 2; + + HAssAnnounceButtons(); + + + HAssAnnounceSwitches(); + + + HAssAnnounceSensors(); + + + HAssAnnounceShutters(); + + + HAssAnnounceRelayLight(); + + + HAssAnnounceDeviceInfoAndStatusSensor(); + masterlog_level = 0; + hass_mode = 3; + } +} + +void HAssDiscover(void) +{ + hass_mode = 1; + hass_init_step = 1; +} + +void HAssAnyKey(void) +{ + if (!Settings.flag.hass_discovery) { return; } + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + + if (!key && KeyTopicActive(0)) { + device = (XdrvMailbox.payload >> 24) & 0xFF; + } + + char scommand[CMDSZ]; + char sw_topic[TOPSZ]; + char key_topic[TOPSZ]; + char trg_state[8]; + char *tmpbtn = SettingsText(SET_MQTT_BUTTON_TOPIC); + char *tmpsw = SettingsText(SET_MQTT_SWITCH_TOPIC); + uint8_t evkey = 0; + Format(sw_topic, tmpsw, sizeof(sw_topic)); + Format(key_topic, tmpbtn, sizeof(key_topic)); + + if (state >= 2) { evkey = 1;} + snprintf_P(scommand, sizeof(scommand), PSTR("%s%d%s"), (key) ? "SWITCH" : "BUTTON", device, (evkey) ? "T" : ""); + + char stopic[TOPSZ]; + + if (!key) { + if (state == 3) { + snprintf_P(trg_state, sizeof(trg_state), GetStateText(3)); + } else { + if (state == 2) { state = 10; } + GetTextIndexed(trg_state, sizeof(trg_state), state -9, kHAssTriggerStringButtons); + } + } + + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, (evkey) ? "TRIG" : PSTR(D_RSLT_STATE), (key) ? GetStateText(state) : trg_state); + MqttPublish(stopic); +} + +bool HAssMqttLWT(void) +{ + if (strncasecmp_P(XdrvMailbox.topic, PSTR(HOME_ASSISTANT_LWT_TOPIC), strlen(HOME_ASSISTANT_LWT_TOPIC)) != 0) { + return false; + } + if (Settings.flag.hass_discovery && (strncasecmp_P(XdrvMailbox.data, PSTR("online"), strlen("online")) == 0) && (XdrvMailbox.data_len == 6)) { + MqttPublishTeleState(); + return true; + } else { return false; } +} + +void HassLwtSubscribe(bool hasslwt) +{ + char htopic[TOPSZ]; + snprintf_P(htopic, sizeof(htopic), PSTR(HOME_ASSISTANT_LWT_TOPIC)); + if (hasslwt && (Settings.flag.hass_discovery)) { + MqttSubscribe(htopic); + } else { MqttUnsubscribe(htopic); } +} + + + + + +bool Xdrv12(uint8_t function) +{ + bool result = false; + bool hasslwt = HOME_ASSISTANT_LWT_SUBSCRIBE; + if (Settings.flag.mqtt_enabled) + { + switch (function) + { + case FUNC_EVERY_SECOND: + if (hass_init_step) + { + hass_init_step--; + if (!hass_init_step) + { + HAssDiscovery(); + NewHAssDiscovery(); + } + } + 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; + case FUNC_ANY_KEY: + HAssAnyKey(); + break; + case FUNC_MQTT_INIT: + hass_mode = 0; + hass_init_step = 2; + + + + break; + + case FUNC_MQTT_SUBSCRIBE: + HassLwtSubscribe(hasslwt); + break; + case FUNC_MQTT_DATA: + result = HAssMqttLWT(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" +#if defined(USE_I2C) || defined(USE_SPI) +#ifdef USE_DISPLAY + +#define XDRV_13 13 + +#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 = 64; +const uint8_t DISPLAY_MAX_ROWS = 64; + +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 }; + +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]; +char disp_pres[5]; + +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) +{ + ExecuteCommandPower(disp_device, on, SRC_DISPLAY); +} + + + + +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 '~' + + +uint32_t decode_te(char *line) { + uint32_t skip = 0; + 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)); + skip++; + } else { + + if (strlen(cp)<2) { + + return skip; + } + + sbuf[0]=*(cp); + sbuf[1]=*(cp+1); + sbuf[2]=0; + *line=strtol(sbuf,0,16); + + memmove(cp,cp+2,strlen(cp)-1); + skip += 2; + } + } + line++; + } + return skip; +} + + + +#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': + DisplayOnOff(0); + break; + case 'O': + DisplayOnOff(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': { + uint8_t param1 = RtcTime.day_of_month; + uint8_t param2 = RtcTime.month; + if (*cp=='U') { + cp++; + param1 = RtcTime.month; + param2 = RtcTime.day_of_month; + } + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), param1, param2, 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; uint8_t dflg=1; + if (*cp=='e' || *cp=='d') { + + uint8_t dis=0; + if (*cp=='d') dis=1; + cp++; + var=atoiv(cp,&num); + num=num%MAXBUTTONS; + cp+=var; + if (buttons[num]) { + buttons[num]->vpower.disable=dis; + if (!dis) { + if (buttons[num]->vpower.is_virtual) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); + else buttons[num]->xdrawButton(bitRead(power,num)); + } + } + break; + } + if (*cp=='-') { + cp++; + dflg=0; + } + 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]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ + renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); + if (!bflags) { + + if (dflg) buttons[num]->xdrawButton(bitRead(power,num)); + buttons[num]->vpower.is_virtual=0; + } else { + + buttons[num]->vpower.is_virtual=1; + if (bflags==2) { + + buttons[num]->vpower.is_pushbutton=1; + } else { + + buttons[num]->vpower.is_pushbutton=0; + } + if (dflg) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); + buttons[num]->vpower.disable=!dflg; + } + } + } + } + break; +#endif + default: + + Response_P(PSTR("Unknown Escape")); + goto exit; + break; + } + } + } + } + exit: + + dp -= decode_te(linebuf); + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { + *dp = 0; + } else { + linebuf[abs(int(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()); + snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); + + 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"), NetworkHostname()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), NetworkMacAddress().c_str()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), NetworkAddress().toString().c_str()); + DisplayLogBufferAdd(buffer); + if (!global_state.wifi_down) { + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); + 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%s"), value, disp_pres); + } + 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) +{ +# 1168 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" + String jsonStr = json; + JsonParser parser((char*)jsonStr.c_str()); + JsonParserObject root = parser.getRootObject(); + if (root) { + + const char *unit = root.getStr(PSTR(D_JSON_TEMPERATURE_UNIT), nullptr); + if (unit) { + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); + } + unit = root.getStr(PSTR(D_JSON_PRESSURE_UNIT), nullptr); + if (unit) { + snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); + } + for (auto key1 : root) { + JsonParserToken value1 = key1.getValue(); + if (value1.isObject()) { + JsonParserObject Object2 = value1.getObject(); + for (auto key2 : Object2) { + JsonParserToken value2 = key2.getValue(); + if (value2.isObject()) { + JsonParserObject Object3 = value2.getObject(); + for (auto key3 : Object3) { + const char* value3 = key3.getValue().getStr(nullptr); + if (value3 != nullptr) { + DisplayJsonValue(topic, key1.getStr(), key3.getStr(), value3); + } + } + } else { + const char* value = value2.getStr(nullptr); + if (value != nullptr) { + DisplayJsonValue(topic, key1.getStr(), key2.getStr(), value); + } + } + } + } else { + const char* value = value1.getStr(nullptr); + if (value != nullptr) { + DisplayJsonValue(topic, key1.getStr(), key1.getStr(), value); + } + } + } + } +} + +void DisplayMqttSubscribe(void) +{ + + + + + + + if (Settings.display_model && (Settings.display_mode &0x04)) { + + char stopic[TOPSZ]; + char ntopic[TOPSZ]; + + ntopic[0] = '\0'; + strlcpy(stopic, SettingsText(SET_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, SettingsText(SET_MQTTPREFIX3), 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/"), SettingsText(SET_MQTTPREFIX3)); + 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++; + if (!PinUsed(GPIO_BACKLIGHT)) { + if (light_type && (4 == 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); + + + + 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) { +# 1453 "/workspace/Tasmota/tasmota/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); +} + + + + +#ifdef ESP32 +#ifdef JPEG_PICTS +#include "img_converters.h" +#include "esp_jpg_decode.h" +bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); +char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height); +void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len); +#endif +#endif + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +extern FS *fsp; +#define XBUFF_LEN 128 +void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { + if (!renderer) return; + File fp; + char *ending = strrchr(file,'.'); + if (!ending) return; + ending++; + char estr[8]; + memset(estr,0,sizeof(estr)); + for (uint32_t cnt=0; cntopen(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 + renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); + uint16_t rgb[xsize]; + for (int16_t j=0; jpushColors(rgb,xsize,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(); + } else if (!strcmp(estr,"jpg")) { + +#ifdef ESP32 +#ifdef JPEG_PICTS + if (psramFound()) { + fp=fsp->open(file,FILE_READ); + if (!fp) return; + uint32_t size = fp.size(); + uint8_t *mem = (uint8_t *)heap_caps_malloc(size+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (mem) { + uint8_t res=fp.read(mem, size); + if (res) { + uint16_t xsize; + uint16_t ysize; + if (mem[0]==0xff && mem[1]==0xd8) { + get_jpeg_size(mem, size, &xsize, &ysize); + + if (xsize && ysize) { + uint8_t *out_buf = (uint8_t *)heap_caps_malloc((xsize*ysize*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (out_buf) { + uint8_t *ob=out_buf; + jpg2rgb888(mem, size, out_buf, (jpg_scale_t)JPG_SCALE_NONE); + uint16_t pixels=xsize*ysize/XBUFF_LEN; + renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); + for(int32_t j=0; jpushColors(rbuff,XBUFF_LEN,true); + OsWatchLoop(); + } + renderer->setAddrWindow(0,0,0,0); + free(out_buf); + } + } + } + } + free(mem); + } + fp.close(); + } +#endif +#endif + } +} +#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) +#ifdef ESP32 +#include +#endif + +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; + fsp->remove(path); + fp=fsp->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=fsp->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 + +#ifdef USE_FT5206 + +#include + +#undef FT5206_address +#define FT5206_address 0x38 + +FT5206_Class *touchp; +TP_Point pLoc; +bool FT5206_found; + +bool Touch_Init(TwoWire &i2c) { + FT5206_found = false; + touchp = new FT5206_Class(); + if (touchp->begin(i2c, FT5206_address)) { + I2cSetActiveFound(FT5206_address, "FT5206"); + FT5206_found = true; + } + return FT5206_found; +} + +uint32_t Touch_Status(uint32_t sel) { + if (FT5206_found) { + switch (sel) { + case 0: + return touchp->touched(); + case 1: + return pLoc.x; + case 2: + return pLoc.y; + } + return 0; + } else { + return 0; + } +} + + +#ifdef USE_TOUCH_BUTTONS +void Touch_MQTT(uint8_t index, const char *cp) { + ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, buttons[index]->vpower.on_off); + MqttPublishTeleSensor(); +} + +void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower.on_off = 1; + else buttons[count]->vpower.on_off = 0; +} + + +void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { +uint16_t temp; +uint8_t rbutt=0; +uint8_t vbutt=0; + + + if (touchp->touched()) { + + pLoc = touchp->getPoint(0); + + if (renderer) { + + rotconvert(&pLoc.x, &pLoc.y); + + + + for (uint8_t count=0; countvpower.disable) { + if (buttons[count]->contains(pLoc.x, pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!buttons[count]->vpower.is_virtual) { + uint8_t pwr=bitRead(power, rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + Touch_RDW_BUTT(count, !pwr); + } + } else { + + const char *cp; + if (!buttons[count]->vpower.is_pushbutton) { + + buttons[count]->vpower.on_off ^= 1; + cp="TBT"; + } else { + + buttons[count]->vpower.on_off = 1; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower.on_off); + Touch_MQTT(count,cp); + } + } + } + if (!buttons[count]->vpower.is_virtual) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countpress(false); + if (buttons[count]->justReleased()) { + if (buttons[count]->vpower.is_virtual) { + if (buttons[count]->vpower.is_pushbutton) { + + buttons[count]->vpower.on_off = 0; + Touch_MQTT(count,"PBT"); + buttons[count]->xdrawButton(buttons[count]->vpower.on_off); + } + } + } + if (!buttons[count]->vpower.is_virtual) { + + uint8_t pwr = bitRead(power, rbutt); + uint8_t vpwr = buttons[count]->vpower.on_off; + if (pwr != vpwr) { + Touch_RDW_BUTT(count, pwr); + } + rbutt++; + } + } + } + pLoc.x = 0; + pLoc.y = 0; + } +} + +#endif +#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 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_MP3_DFR562)) { + switch (function) { + case FUNC_PRE_INIT: + MP3PlayerInit(); + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_15_pca9685.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_15_pca9685.ino" +#ifdef USE_I2C +#ifdef USE_PCA9685 + + + + + + +#define XDRV_15 15 +#define XI2C_01 1 + +#define PCA9685_REG_MODE1 0x00 +#define PCA9685_REG_LED0_ON_L 0x06 +#define PCA9685_REG_PRE_SCALE 0xFE + +#ifndef USE_PCA9685_ADDR + #define USE_PCA9685_ADDR 0x40 +#endif +#ifndef USE_PCA9685_FREQ + #define USE_PCA9685_FREQ 50 +#endif + +bool pca9685_detected = false; +uint16_t pca9685_freq = USE_PCA9685_FREQ; +uint16_t pca9685_pin_pwm_value[16]; + +void PCA9685_Detect(void) +{ + if (I2cActive(USE_PCA9685_ADDR)) { 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 = true; + I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); + 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) +{ + 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) { + MqttPublishTeleSensor(); + } +} + +bool Xdrv15(uint8_t function) +{ + if (!I2cEnabled(XI2C_01)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PCA9685_Detect(); + } + else if (pca9685_detected) { + switch (function) { + case FUNC_EVERY_SECOND: + if (tele_period == 0) { + PCA9685_OutputTelemetry(true); + } + break; + case FUNC_COMMAND_DRIVER: + if (XDRV_15 == XdrvMailbox.index) { + result = PCA9685_Command(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +#ifdef USE_LIGHT +#ifdef USE_TUYA_MCU + +#define XDRV_16 16 +#define XNRG_32 32 + +#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_CMD_SET_TIME 0x1C + +#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 +#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 +#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 +#define TUYA_LOW_POWER_CMD_STATE 0x05 + +#define TUYA_TYPE_BOOL 0x01 +#define TUYA_TYPE_VALUE 0x02 +#define TUYA_TYPE_STRING 0x03 +#define TUYA_TYPE_ENUM 0x04 + +#define TUYA_BUFFER_SIZE 256 + +#include + +TasmotaSerial *TuyaSerial = nullptr; + +struct TUYA { + uint16_t Levels[5] = {0,0,0,0,0}; + uint16_t Snapshot[5] = {0,0,0,0,0}; + char HSBColor[13]; + uint16_t CTMin = 153; + uint16_t CTMax = 500; + bool ModeSet = false; + uint8_t FanState = 0; + bool SuspendTopic = false; + uint32_t ignore_topic_timeout = 0; + bool ignore_dim = false; + uint8_t cmd_status = 0; + uint8_t cmd_checksum = 0; + uint8_t data_len = 0; + uint8_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; + bool low_power_mode = false; + bool send_success_next_second = false; + uint32_t ignore_dimmer_cmd_timeout = 0; + bool ignore_tuyareceived = false; +} Tuya; + +const char kTuyaCommand[] PROGMEM = "|" + D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; + +void (* const TuyaCommand[])(void) PROGMEM = { + &CmndTuyaMcu, &CmndTuyaSend +}; + + + + +bool IsModuleTuya(void) +{ + return ((TUYA_DIMMER == my_module_type) || (SK03_TUYA == my_module_type)); +} + +bool AsModuleTuyaMS(void) +{ + return ((light_type > LT_RGB) && TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0); +} + +bool IsTuyaFanCtrl(void) +{ + return ((TuyaGetDpId(TUYA_MCU_FUNC_FAN3) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN4) != 0) || + (TuyaGetDpId(TUYA_MCU_FUNC_FAN5) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN6) != 0)); +} + +bool TuyaModeSet(void) +{ + return Tuya.ModeSet; +} + +uint8_t TuyaFanSpeeds(void) +{ + uint8_t FanSpeeds = 0; + for (uint32_t i = 0; i <= 3; i++) { + if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { + FanSpeeds = i + 2; + } + } + return FanSpeeds; +} + +uint8_t TuyaFanState(void) +{ + return Tuya.FanState; +} +# 143 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +void CmndTuyaSend(void) { + if (XdrvMailbox.index > 4 && XdrvMailbox.index < 8) { + return; + } + if (XdrvMailbox.index == 0) { + TuyaRequestState(0); + } else if (XdrvMailbox.index == 8) { + TuyaRequestState(8); + } else if (XdrvMailbox.index == 9) { + if (Settings.tuyamcu_topic) { Settings.tuyamcu_topic = 0; } else { Settings.tuyamcu_topic = 1; } + AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: TuyaMCU Stat Topic %s"), (Settings.tuyamcu_topic ? PSTR("enabled") : PSTR("disabled"))); + + } else { + if (XdrvMailbox.data_len > 0) { + char *p; + char *data; + uint8_t i = 0; + uint8_t dpId = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + if ( i == 0) { + dpId = strtoul(str, nullptr, 0); + } else { + data = str; + } + i++; + } + + if (1 == XdrvMailbox.index) { + TuyaSendBool(dpId, strtoul(data, nullptr, 0)); + } else if (2 == XdrvMailbox.index) { + TuyaSendValue(dpId, strtoull(data, nullptr, 0)); + } else if (3 == XdrvMailbox.index) { + TuyaSendString(dpId, data); + } else if (4 == XdrvMailbox.index) { + TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); + } + } + } + ResponseCmndDone(); +} + + + +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])) { + + + + + + bool DualDim; + if (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { DualDim = true; } + } else if (TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { DualDim = true; } + } else if ((TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] == 0) || (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] == 0)) { DualDim = false; }; + if (DualDim) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_CT, 0); } + if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_RGB, 0); } + if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_WHITE, 0); } + Settings.flag3.pwm_multi_channels = 1; + } else { Settings.flag3.pwm_multi_channels = 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("{\"" D_CMND_TUYA_MCU "\":[")); + 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_REPORT2) || + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_BATTERY_PERCENTAGE) || + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || + (fnId >= TUYA_MCU_FUNC_FAN3 && fnId <= TUYA_MCU_FUNC_FAN6) || + (fnId >= TUYA_MCU_FUNC_MOTOR_DIR && fnId <= TUYA_MCU_FUNC_DUMMY) || + (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); +} + +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: + case TUYA_TYPE_ENUM: + 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)); +} + +void TuyaSendEnum(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); +} + +void TuyaSendString(uint8_t id, char data[]) { + + uint16_t len = strlen(data); + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = TUYA_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + for (uint16_t i = 0; i < len; i++) { + payload_buffer[4+i] = data[i]; + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +bool TuyaSetPower(void) +{ + bool status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); + if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); + + if (source != SRC_SWITCH && TuyaSerial) { + TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + delay(20); + status = true; + } + return status; +} + +bool TuyaSetChannels(void) +{ + uint16_t hue, TuyaData; + uint8_t sat, bri; + uint8_t TuyaIdx = 0; + char hex_char[13]; + bool noupd = false; + bool LightMode = TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0; + uint8_t idx = 0; + snprintf_P(hex_char, sizeof(hex_char), PSTR("000000000000")); + + if (LT_SERIAL1 == light_type) { + Tuya.Snapshot[0] = light_state.getDimmer(); + } + if (LT_SERIAL2 == light_type || LT_RGBWC == light_type) { + idx = 1; + if (LT_SERIAL2 == light_type && Settings.flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) { + + Tuya.Snapshot[0] = changeUIntScale(Light.current_color[0], 0, 255, 0, 100); + Tuya.Snapshot[1] = changeUIntScale(Light.current_color[1], 0, 255, 0, 100); + } else { + light_state.getCTRange(&Tuya.CTMin, &Tuya.CTMax); + Tuya.Snapshot[0] = light_state.getDimmer(); + Tuya.Snapshot[1] = light_state.getCT(); + } + } + if (LT_RGBW == light_type) { + idx = 1; + Tuya.Snapshot[0] = light_state.getDimmer(1); + Tuya.Snapshot[1] = light_state.getDimmer(2); + } + + if (light_type > LT_BASIC) { + + if (LT_RGB != light_type) { + for (uint8_t i = 0; i <= idx; i++) { + if (Tuya.Snapshot[i] != Tuya.Levels[i]) { + if (i == 0 && LightMode && Tuya.ModeSet ) { noupd = true;} + if (!noupd) { + LightSerialDuty(Tuya.Snapshot[i], &hex_char[0], i+1); + Tuya.Levels[i] = Tuya.Snapshot[i]; + } + noupd = false; + } + } + } + + if (light_type >= LT_RGB) { + + light_state.getHSB(&hue, &sat, &bri); + sat = changeUIntScale(sat, 0, 255, 0, 100); + bri = changeUIntScale(bri, 0, 255, 0, 100); + if (hue != Tuya.Snapshot[2] || sat != Tuya.Snapshot[3] || bri != Tuya.Snapshot[4]) { + if ((LightMode && Tuya.ModeSet) || LT_RGB == light_type) { + snprintf_P(hex_char, sizeof(hex_char), PSTR("%04X%04X%04X"), hue, sat * 10, bri * 10); + LightSerialDuty(0, &hex_char[0], 3); + memcpy_P(Tuya.HSBColor, hex_char, strlen(hex_char)); + Tuya.Snapshot[2] = hue; + Tuya.Snapshot[3] = sat; + Tuya.Snapshot[4] = bri; + } + } + } + } + return true; +} + +void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) +{ + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); + bool CTLight = false; + + if (TuyaIdx > 0 && TuyaIdx <= 2) { + + if (TuyaIdx == 2) { + if (!Settings.flag3.pwm_multi_channels) { + CTLight = true; + dpid = TuyaGetDpId(TUYA_MCU_FUNC_CT); + } else { dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2); } + } + + if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { + if (TuyaIdx == 2 && CTLight) { + duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0); + } else { duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max); } + + if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } + Tuya.ignore_dimmer_cmd_timeout = millis() + 250; + if (Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { + TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 0); + } + TuyaSendValue(dpid, duty); + + } else if (dpid > 0 && TuyaIdx <= 2) { + + Tuya.ignore_dim = false; + + if (TuyaIdx == 2 && CTLight) { + duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0); + } else { + duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value %d for dpid %d"), duty, dpid); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); + } + } + + if (TuyaIdx == 3) { + dpid = TuyaGetDpId(TUYA_MCU_FUNC_RGB); + if (!Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { + TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 1); + } + TuyaSendString(dpid, hex_char); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: TX RGB hex %s to dpId %d"), hex_char, dpid); + } +} + +void TuyaRequestState(uint8_t state_type) +{ + if (TuyaSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); + Tuya.SuspendTopic = true; + Tuya.ignore_topic_timeout = millis() + 1000; + switch (state_type) { + case 0: + TuyaSendCmd(TUYA_CMD_QUERY_STATE); + break; + case 8: + TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); + break; + } + } +} + +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 TuyaProcessStatePacket(void) { + char scmnd[20]; + uint8_t dpidStart = 6; + uint8_t fnId; + uint16_t dpDataLen; + + while (dpidStart + 4 < Tuya.byte_counter) { + dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); + + if (Tuya.buffer[dpidStart + 1] == 1) { + + 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[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], 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[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 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[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); + SwitchHandler(1); + } + } + } + else if (Tuya.buffer[dpidStart + 1] == 2) { + bool tuya_energy_enabled = (XNRG_32 == energy_flg); + uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; + uint8_t dimIndex; + if ((fnId == TUYA_MCU_FUNC_FAN3) || (fnId == TUYA_MCU_FUNC_FAN4) || + (fnId == TUYA_MCU_FUNC_FAN5) || (fnId == TUYA_MCU_FUNC_FAN6)) { + Tuya.FanState = packetValue; + } + + if (fnId == TUYA_MCU_FUNC_DIMMER || fnId == TUYA_MCU_FUNC_REPORT1) { dimIndex = 0; } + + if (fnId == TUYA_MCU_FUNC_DIMMER2 || fnId == TUYA_MCU_FUNC_REPORT2 || fnId == TUYA_MCU_FUNC_CT) { dimIndex = 1; } + + if (dimIndex == 1 && !Settings.flag3.pwm_multi_channels) { + Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, Tuya.CTMax, Tuya.CTMin); + } else { + Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX value %d from dpId %d "), packetValue, Tuya.buffer[dpidStart]); + + if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1) || + (fnId == TUYA_MCU_FUNC_DIMMER2) || (fnId == TUYA_MCU_FUNC_REPORT2) || + (fnId == TUYA_MCU_FUNC_CT) || (fnId == TUYA_MCU_FUNC_WHITE)) { + + if (Tuya.ignore_dimmer_cmd_timeout < millis()) { + + if ((power || Settings.flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { + + Tuya.ignore_dim = true; + skip_light_fade = true; + + scmnd[0] = '\0'; + if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1)) { + if (Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[0] - changeUIntScale(Light.current_color[0], 0, 255, 0, 100))) > 1) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "1 %d"), Tuya.Levels[0]); + } + else if ((abs(Tuya.Levels[0] - light_state.getDimmer())) > 1) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER "3 %d"), Tuya.Levels[0]); + } + } + if (((fnId == TUYA_MCU_FUNC_DIMMER2) || (fnId == TUYA_MCU_FUNC_REPORT2)) && + Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[1] - changeUIntScale(Light.current_color[1], 0, 255, 0, 100))) > 1) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "2 %d"), Tuya.Levels[1]); + } + if ((fnId == TUYA_MCU_FUNC_CT) && (abs(Tuya.Levels[1] - light_state.getCT())) > 1) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLORTEMPERATURE " %d"), Tuya.Levels[1]); + } + if ((fnId == TUYA_MCU_FUNC_WHITE) && (abs(Tuya.Levels[1] - light_state.getDimmer(2))) > 1) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WHITE " %d"), Tuya.Levels[1]); + } + if (scmnd[0] != '\0') { + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + } + } + #ifdef USE_ENERGY_SENSOR + else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current[0] = (float)packetValue / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); + + 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 + } + else if (Tuya.buffer[dpidStart + 1] == 3) { + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + if ((TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) && dpDataLen == 12) { + + + char RgbData[13]; + snprintf_P(RgbData, sizeof(RgbData), PSTR("%.*s"), dpDataLen, dpData); + char HSB1[5], HSB2[5], HSB3[5]; + snprintf_P(HSB1, sizeof(HSB1), PSTR("%.4s\n"), &RgbData[0]); + snprintf_P(HSB2, sizeof(HSB2), PSTR("%.4s\n"), &RgbData[4]); + snprintf_P(HSB3, sizeof(HSB3), PSTR("%.4s\n"), &RgbData[8]); + + if ((Tuya.Snapshot[2] != ((int)strtol(HSB1, NULL, 16)) || + Tuya.Snapshot[3] != ((int)strtol(HSB2, NULL, 16)) / 10 || Tuya.Snapshot[4] !=((int)strtol(HSB3, NULL, 16)) / 10)) { + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_HSBCOLOR " %d,%d,%d"), ((int)strtol(HSB1, NULL, 16)), + ((int)strtol(HSB2, NULL, 16)) / 10, ((int)strtol(HSB3, NULL, 16)) / 10); + ExecuteCommand(scmnd, SRC_SWITCH); + + memcpy_P(Tuya.HSBColor, RgbData, strlen(RgbData)); + } + } + } + else if (Tuya.buffer[dpidStart + 1] == 4) { + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + if (fnId == TUYA_MCU_FUNC_MODESET) { + Tuya.ModeSet = dpData[0]; + Tuya.Levels[3] = dpData[0]; + } + } + dpidStart += dpDataLen + 4; + } +} +void TuyaLowPowerModePacketProcess(void) { + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSetWifiLed(); + break; + + case TUYA_LOW_POWER_CMD_STATE: + TuyaProcessStatePacket(); + Tuya.send_success_next_second = true; + break; + } + +} + +void TuyaHandleProductInfoPacket(void) { + uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + char *data = &Tuya.buffer[6]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); +} + +void TuyaSendLowPowerSuccessIfNeeded(void) { + uint8_t success = 1; + + if (Tuya.send_success_next_second) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); + Tuya.send_success_next_second = false; + } +} + +void TuyaNormalPowerModePacketProcess(void) +{ + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSendCmd(TUYA_CMD_MCU_CONF); + break; + + 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: + TuyaProcessStatePacket(); + 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 = TuyaGetTuyaWifiState(); + 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { + if (Settings.my_gp.io[i] == AGPIO(GPIO_LED1)) led1_set = true; + else if (Settings.my_gp.io[i] == AGPIO(GPIO_KEY1)) key1_set = true; + } + if (!Settings.my_gp.io[led1_gpio] && !led1_set) { + Settings.my_gp.io[led1_gpio] = AGPIO(GPIO_LED1); + restart_flag = 2; + } + if (!Settings.my_gp.io[key1_gpio] && !key1_set) { + Settings.my_gp.io[key1_gpio] = AGPIO(GPIO_KEY1); + restart_flag = 2; + } + } + TuyaRequestState(0); + break; + + default: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); + } +} + + + + + +bool TuyaModuleSelected(void) +{ + if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { + SetPin(1, AGPIO(GPIO_TUYA_TX)); + SetPin(3, AGPIO(GPIO_TUYA_RX)); + Settings.my_gp.io[1] = AGPIO(GPIO_TUYA_TX); + Settings.my_gp.io[3] = AGPIO(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; + + 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 && TuyaGetDpId(TUYA_MCU_FUNC_DUMMY) == 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + devices_present++; + SettingsSaveAll(); + } +# 831 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { + light_type = LT_RGBWC; + } else if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { + light_type = LT_RGBW; + } else { light_type = LT_RGB; } + } else if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { + light_type = LT_RGBWC; + } else { light_type = LT_SERIAL2; } + } else { light_type = LT_SERIAL1; } + } else { + light_type = LT_BASIC; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { + Tuya.low_power_mode = true; + Settings.flag3.fast_power_cycle_disable = true; + } + + UpdateDevices(); + return true; +} + +void TuyaInit(void) +{ + int baudrate = 9600; + if (Settings.flag4.tuyamcu_baudrate) { baudrate = 115200; } + + 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(baudrate)) { + if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } + + Tuya.SuspendTopic = true; + Tuya.ignore_topic_timeout = millis() + 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration at %d bps"), baudrate); + TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); + + } + } + 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; + + char hex_char[(Tuya.byte_counter * 2) + 2]; + uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + + Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); + + uint16_t DataVal = 0; + uint8_t dpId = 0; + uint8_t dpDataType = 0; + char DataStr[13]; + + if (len > 0) { + ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + + + uint8_t dpidStart = 6; + + while (dpidStart + 4 < Tuya.byte_counter) { + dpId = Tuya.buffer[dpidStart]; + dpDataType = Tuya.buffer[dpidStart + 1]; + uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); + + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); + if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + DataVal = dpData[0]; + } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { + uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; + ResponseAppend_P(PSTR("%u"), dpValue); + DataVal = dpValue; + } else if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); + snprintf_P(DataStr, sizeof(DataStr), PSTR("%.*s"), dpDataLen, dpData); + } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + DataVal = dpData[0]; + } else { + ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + snprintf_P(DataStr, sizeof(DataStr), PSTR("%s"), dpHexData); + } + } + + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); + if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); + } + ResponseAppend_P(PSTR("}")); + dpidStart += dpDataLen + 4; + } + } + } + ResponseAppend_P(PSTR("}}")); + + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + } else { + AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); + } + XdrvRulesProcess(); + + if (dpId != 0 && Settings.tuyamcu_topic) { + if (!Tuya.SuspendTopic) { + char scommand[10]; + snprintf_P(scommand, sizeof(scommand), PSTR("TuyaSend%d"), dpDataType); + + if (dpDataType != 3 && dpDataType != 5) { Response_P(PSTR("%d,%u"), dpId, DataVal); } + else { Response_P(PSTR("%d,%s"), dpId, DataStr); } + MqttPublishPrefixTopic_P(STAT, (PSTR("%s"), scommand)); + } + } + + if (!Tuya.low_power_mode) { + TuyaNormalPowerModePacketProcess(); + } else { + TuyaLowPowerModePacketProcess(); + } + + 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; +} + +uint8_t TuyaGetTuyaWifiState(void) { + + uint8_t wifi_state = 0x02; + switch(WifiState()){ + case WIFI_MANAGER: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + if (MqttIsConnected()) { + wifi_state = 0x04; + } + + return wifi_state; +} + +void TuyaSetWifiLed(void) +{ + Tuya.wifi_state = TuyaGetTuyaWifiState(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); + + if (Tuya.low_power_mode) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } else { + TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } +} + +#ifdef USE_TUYA_TIME +void TuyaSetTime(void) { + if (!RtcTime.valid) { return; } + + uint16_t payload_len = 8; + uint8_t payload_buffer[8]; + payload_buffer[0] = 0x01; + payload_buffer[1] = RtcTime.year %100; + payload_buffer[2] = RtcTime.month; + payload_buffer[3] = RtcTime.day_of_month; + payload_buffer[4] = RtcTime.hour; + payload_buffer[5] = RtcTime.minute; + payload_buffer[6] = RtcTime.second; + payload_buffer[7] = RtcTime.day_of_week; + + TuyaSendCmd(TUYA_CMD_SET_TIME, payload_buffer, payload_len); +} +#endif + +#ifdef USE_ENERGY_SENSOR + + + + + +bool Xnrg32(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_32; + } + } + } + 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_PRE_INIT: + TuyaInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = TuyaSetPower(); + break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; + case FUNC_EVERY_SECOND: + TuyaSetChannels(); + if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } + if (!Tuya.low_power_mode) { + Tuya.heartbeat_timer++; + if (Tuya.heartbeat_timer > 10) { + Tuya.heartbeat_timer = 0; + TuyaSendCmd(TUYA_CMD_HEARTBEAT); + } +#ifdef USE_TUYA_TIME + if (!(uptime % 60)) { + TuyaSetTime(); + } +#endif + } else { + TuyaSendLowPowerSuccessIfNeeded(); + } + if (Tuya.ignore_topic_timeout < millis()) { Tuya.SuspendTopic = false; } + break; + + + + case FUNC_COMMAND: + result = DecodeCommand(kTuyaCommand, TuyaCommand); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_17_rcswitch.ino" +# 20 "/workspace/Tasmota/tasmota/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); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, data); +#endif + } + mySwitch.resetAvailable(); + } +} + +void RfInit(void) +{ + if (PinUsed(GPIO_RFSEND)) { + mySwitch.enableTransmit(Pin(GPIO_RFSEND)); + } + if (PinUsed(GPIO_RFRECV)) { + pinMode( Pin(GPIO_RFRECV), INPUT); + 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; + + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (root) { + + char parm_uc[10]; + data = root.getUInt(PSTR(D_JSON_RF_DATA), data); + bits = root.getUInt(PSTR(D_JSON_RF_BITS), bits); + protocol = root.getInt(PSTR(D_JSON_RF_PROTOCOL), protocol); + repeat = root.getInt(PSTR(D_JSON_RF_REPEAT), repeat); + pulse = root.getInt(PSTR(D_JSON_RF_PULSE), 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 (PinUsed(GPIO_RFSEND) || PinUsed(GPIO_RFRECV)) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (PinUsed(GPIO_RFRECV)) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (PinUsed(GPIO_RFSEND)) { + result = DecodeCommand(kRfSendCommands, RfSendCommand); + } + break; + case FUNC_INIT: + RfInit(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" +# 20 "/workspace/Tasmota/tasmota/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) +{ + devices_present++; + 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_MANAGER: + 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 "/workspace/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_PS_16_DZ + + + + +#define XDRV_19 19 + +#define PS16DZ_BUFFER_SIZE 80 + +#include + +TasmotaSerial *PS16DZSerial = nullptr; + +struct PS16DZ { + char *rx_buffer = nullptr; + int byte_counter = 0; + uint8_t dimmer = 0; +} Ps16dz; + + + + + +void PS16DZSerialSend(const char *tx_buffer) +{ + + + PS16DZSerial->print(tx_buffer); + PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); +} + +void PS16DZSerialSendOk(void) +{ + char tx_buffer[16]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); + PS16DZSerialSend(tx_buffer); +} + + + + +void PS16DZSerialSendUpdateCommand(void) +{ + uint8_t light_state_dimmer = light_state.getDimmer(); + + 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; + + 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); + + PS16DZSerialSend(tx_buffer); +} + + + + + +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; + + + + + if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { + + } + else 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 is_switch_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)) { + bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + is_switch_change = (switch_state != power); + if (is_switch_change) { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"bright\"", 8)) { + Ps16dz.dimmer = atoi(token3); + + + + 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)) { + + + + } + token = strtok_r(nullptr, ",", &end_str); + } + + if (!is_brightness_change) { + + + + PS16DZSerialSendOk(); + } + } + 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 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; +} + + + + + +bool Xdrv19(uint8_t function) +{ + bool result = false; + + if (PS_16_DZ == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); + break; + case FUNC_INIT: + PS16DZInit(); + break; + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +# 31 "/workspace/Tasmota/tasmota/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.24.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); + bridgeid += "FFFE"; + bridgeid += 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); + String uuid = HueUuid(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, uuid.c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, uuid.c_str(), uuid.c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, uuid.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)); + } + + PrepLog_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 size_t HUE_DESCRIPTION_XML_SIZE = 626; +const char HUE_DESCRIPTION_XML_COMPRESSED[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" + "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\xF0\x62\x98\xDB\xF1\xD6\x2C" + "\x67\x0C\x3A\xF3\xE3\xC7\x98\x8C\xCF\x43\x67\x59\xC8\x75\xB3\xD8\x7E\x1E\x85\xE1" + "\x8C\x32\x33\x04\x1C\x78\xFC\x3D\x06\xD9\xAF\x3E\x7E\x1C\x87\xA1\xD8\x40\x83\x14" + "\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x8F\x85\x1E\xC3\xD0" + "\x85\x97\xC8\x22\x1D\x7E\x67\xE0\xAA\xA1\x87\x99\xD8\x76\x1E\xD3\x61\xC8\x79\xFD" + "\x9D\x87\xA1\xD8\x40\x87\x50\xF4\x04\x1D\x18\x10\xE2\x15\x19\x0C\x67\xE0\x2B\x6D" + "\xC7\x99\x0E\xBF\x68\x67\x99\xC8\x7A\x1D\x84\x08\xD8\x61\xE8\x63\xFA\xF8\x40\x8C" + "\x8B\xAC\x6B\x3F\x0A\xC6\xD9\xB7\x38\xEB\x26\x18\xAC\x3A\xC8\x51\x59\xD6\x43\xBF" + "\xA2\x0F\x34\x77\x4F\x69\xB0\xE4\x3B\xC7\xA1\xD8\x40\x91\x83\x1E\x83\x6F\x85\x98" + "\xB0\xE8\x5F\xDF\xCF\xC2\xFE\x19\x58\x48\x86\x0A\xD0\xB4\x67\x91\x30\x98\x75\xFC" + "\xED\x0F\xC7\xA1\xD8\x09\x18\x20\x24\x62\x44\x2C\xBE\x41\x02\x1F\x06\xE3\xE3\xE3" + "\xE7\x41\x80\x83\x8D\x1D\x03\xC1\xA0\x93\x89\x10\xB2\xF9\x04\x7E\x1E\x83\x70\x46" + "\x11\x08\xFC\x1F\xF4\x65\x6E\x71\xF8\x08\x7A\x48\xA1\x6D\x10\xC7\xFF\x67\x58\x48" + "\x87\xF7\xEC\x27\xEF\x22\x0B\x47\x85\x56\xF0\xF1\xE8\x76\x02\x66\x2A\x2B\x08\x39" + "\x39\x75\x8D\x60\x91\x90\x0E\x04\x1E\x12\x0E\x53\x94\x40\x85\x88\x82\x17\x08\x98" + "\x23\x08\xB8\x58\xD1\xCF\xE7\xE1\xC5\x49\xB7\x55\xDA\xEC\x81\x0F\x01\x04\x1A\xC7" + "\xA7\x9F\xF6\xC1\x0E\x51\xED\x36\x1C\xB3\xD0\xEC\x20\x48\x9C\x7A\x10\xB2\x10\xB8" + "\xFC\x16\x2F\x44\x3C\xCF\x69\xB0\xE5\x1E\x87\x61\x10\xB2\x10\xB8\xFC\x04\x3E\x38" + "\xCF\xC3\xD0\xEC\xFE\x65\x1F\x93\x85\x23\x74\xE1\x48\xDC"; +# 167 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" +const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM = + "%s\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}"; +# 179 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" +const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = + ",\"type\":\"Extended color light\"," + "\"name\":\"%s\"," + "\"modelid\":\"%s\"," + "\"manufacturername\":\"%s\"," + "\"uniqueid\":\"%s\"}"; + + + +const char HUE_GROUP0_STATUS_JSON[] PROGMEM = + "{\"name\":\"Group 0\"," + "\"lights\":[{l1]," + "\"type\":\"LightGroup\"," + "\"action\":"; +# 214 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" +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_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +String GetHueDeviceId(uint16_t id) +{ + String deviceid = WiFi.macAddress(); + deviceid += F(":00:11-"); + deviceid += 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 = Decompress(HUE_DESCRIPTION_XML_COMPRESSED,HUE_DESCRIPTION_XML_SIZE); + 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; + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + } +#endif + + if (light_type) { + light_state.getHSB(&hue, &sat, nullptr); + if (sat > 254) sat = 254; + hue = changeUIntScale(hue, 0, 360, 0, 65535); + + if ((sat != prev_sat) || (hue != prev_hue)) { + 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; } + } + + const size_t buf_size = 256; + char * buf = (char*) malloc(buf_size); + + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (power & (1 << (device-1))) ? "true" : "false"); + + if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { + snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); + } + if (LST_COLDWARM <= local_light_subtype) { + snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, g_gotct ? "ct" : "hs"); + } + if (LST_RGB <= local_light_subtype) { + if (prev_x_str[0] && prev_y_str[0]) { + snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, prev_x_str, prev_y_str); + } else { + float x, y; + light_state.getXY(&x, &y); + snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, String(x, 5).c_str(), String(y, 5).c_str()); + } + snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue, sat); + } + if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { + snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); + } + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX, buf); + + *response += buf; + free(buf); +} + + + +bool HueActive(uint8_t device) { + if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } + return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); +} + +void HueLightStatus2(uint8_t device, String *response) +{ + const size_t buf_size = 300; + char * buf = (char*) malloc(buf_size); + const size_t max_name_len = 32; + char fname[max_name_len + 1]; + + strlcpy(fname, SettingsText(device <= MAX_FRIENDLYNAMES ? SET_FRIENDLYNAME1 + device -1 : SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1), max_name_len + 1); + + if (device > MAX_FRIENDLYNAMES) { + uint32_t fname_len = strlen(fname); + if (fname_len > max_name_len - 2) { fname_len = max_name_len - 2; } + fname[fname_len++] = '-'; + 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; + } + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2, + EscapeJSONString(fname).c_str(), + EscapeJSONString(Settings.user_template_name).c_str(), + PSTR("Tasmota"), + GetHueDeviceId(device).c_str()); + *response += buf; + free(buf); +} + + + + + +#ifndef USE_ZIGBEE +uint32_t EncodeLightId(uint8_t relay_id) +#else +uint32_t EncodeLightId(uint8_t relay_id, uint16_t z_shortaddr = 0) +#endif +{ + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4); + + if (relay_id >= 32) { + relay_id = 0; + } + if (relay_id > 15) { + id |= (1 << 28); + } + id |= (relay_id & 0xF); +#ifdef USE_ZIGBEE + if ((z_shortaddr) && (!relay_id)) { + + id = (1 << 29) | z_shortaddr; + } +#endif + + return id; +} + + + + + + + +#ifndef USE_ZIGBEE +uint32_t DecodeLightId(uint32_t hue_id) +#else +uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr) +#endif +{ + uint8_t relay_id = hue_id & 0xF; + if (hue_id & (1 << 28)) { + relay_id += 16; + } + if (0 == relay_id) { + relay_id = 32; + } +#ifdef USE_ZIGBEE + if (hue_id & (1 << 29)) { + + if (shortaddr) { *shortaddr = hue_id & 0xFFFF; } + relay_id = 0; + } +#endif + return relay_id; +} + + +inline uint32_t findEchoGeneration(void) { + + return Settings.flag4.alexa_gen_1 ? 1 : 2; +} + +void HueGlobalConfig(String *path) { + String response; + + path->remove(0,1); + response = F("{\"lights\":{"); + bool appending = false; + CheckHue(&response, appending); +#ifdef USE_ZIGBEE + ZigbeeCheckHue(&response, appending); +#endif + 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); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Authentication Result (%s)"), response); +} + + +void CheckHue(String * response, bool &appending) { + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + for (uint32_t i = 1; i <= maxhue; i++) { + if (HueActive(i)) { + if (appending) { *response += ","; } + *response += "\""; + *response += EncodeLightId(i); + *response += F("\":{\"state\":"); + HueLightStatus1(i, response); + HueLightStatus2(i, response); + appending = true; + } + } +} + +void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool on = false; + bool resp = false; + bool change = false; + uint8_t local_light_subtype = getLocalLightSubtype(device); + + const size_t buf_size = 100; + char * buf = (char*) malloc(buf_size); + + if (Webserver->args()) { + response = "["; + + JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); + JsonParserObject root = parser.getRootObject(); + + JsonParserToken hue_on = root[PSTR("on")]; + if (hue_on) { + on = hue_on.getBool(); + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"), + device_id, on ? "true" : "false"); + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + if (!change) { + bri = on ? 1.0f : 0.0f; + change = true; + resp = true; + response += buf; + } + } else { +#endif + ExecuteCommandPower(device, (on) ? POWER_ON : POWER_OFF, SRC_HUE); + response += buf; + resp = true; +#ifdef USE_SHUTTER + } +#endif + } + + 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; + + parser.setCurrent(); + JsonParserToken hue_bri = root[PSTR("bri")]; + if (hue_bri) { + bri = hue_bri.getUInt(); + prev_bri = bri; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "bri", bri); + response += buf; + if (LST_SINGLE <= Light.subtype) { + + if (254 <= bri) { bri = 255; } + change = true; + } + resp = true; + } + + + + parser.setCurrent(); + JsonParserToken hue_xy = root[PSTR("xy")]; + if (hue_xy) { + JsonParserArray arr_xy = JsonParserArray(hue_xy); + JsonParserToken tok_x = arr_xy[0]; + JsonParserToken tok_y = arr_xy[1]; + float x = tok_x.getFloat(); + float y = tok_y.getFloat(); + strlcpy(prev_x_str, tok_x.getStr(), sizeof(prev_x_str)); + strlcpy(prev_y_str, tok_y.getStr(), 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, 360, 0, 65535); + prev_sat = (sat > 254 ? 254 : sat); + + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/xy\":[%s,%s]}}"), + device_id, prev_x_str, prev_y_str); + response += buf; + g_gotct = false; + resp = true; + change = true; + } + + parser.setCurrent(); + JsonParserToken hue_hue = root[PSTR("hue")]; + if (hue_hue) { + hue = hue_hue.getUInt(); + prev_hue = hue; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "hue", hue); + response += buf; + if (LST_RGB <= Light.subtype) { + + hue = changeUIntScale(hue, 0, 65535, 0, 360); + g_gotct = false; + change = true; + } + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_sat = root[PSTR("sat")]; + if (hue_sat) { + sat = hue_sat.getUInt(); + prev_sat = sat; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "sat", sat); + response += buf; + if (LST_RGB <= Light.subtype) { + + if (254 <= sat) { sat = 255; } + g_gotct = false; + change = true; + } + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_ct = root[PSTR("ct")]; + if (hue_ct) { + ct = hue_ct.getUInt(); + prev_ct = ct; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "ct", ct); + response += buf; + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + g_gotct = true; + change = true; + } + resp = true; + } + + if (change) { +#ifdef USE_SHUTTER + if (ShutterState(device)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); + ShutterSetPosition(device, bri * 100.0f ); + } else +#endif + 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); + } + free(buf); +} + +void HueLights(String *path) +{ + + + + String response; + int code = 200; + uint8_t device = 1; + uint32_t device_id; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,path->indexOf(F("/lights"))); + if (path->endsWith(F("/lights"))) { + response = "{"; + bool appending = false; + CheckHue(&response, appending); +#ifdef USE_ZIGBEE + ZigbeeCheckHue(&response, appending); +#endif +#ifdef USE_SCRIPT_HUE + Script_Check_Hue(&response); +#endif + response += "}"; + } + else if (path->endsWith(F("/state"))) { + path->remove(0,8); + path->remove(path->indexOf(F("/state"))); + device_id = atoi(path->c_str()); + device = DecodeLightId(device_id); +#ifdef USE_ZIGBEE + uint16_t shortaddr; + device = DecodeLightId(device_id, &shortaddr); + if (shortaddr) { + return ZigbeeHandleHue(shortaddr, device_id, response); + } +#endif + +#ifdef USE_SCRIPT_HUE + if (device > devices_present) { + return Script_Handle_Hue(path); + } +#endif + if ((device >= 1) || (device <= maxhue)) { + HueLightsCommand(device, device_id, response); + } + + } + else if(path->indexOf(F("/lights/")) >= 0) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("/lights path=%s"), path->c_str()); + path->remove(0,8); + device_id = atoi(path->c_str()); + device = DecodeLightId(device_id); +#ifdef USE_ZIGBEE + uint16_t shortaddr; + device = DecodeLightId(device_id, &shortaddr); + if (shortaddr) { + ZigbeeHueStatus(&response, shortaddr); + goto exit; + } +#endif + +#ifdef USE_SCRIPT_HUE + 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); +} + +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 += "\""; + } + +#ifdef USE_ZIGBEE + ZigbeeHueGroups(&response); +#endif + response.replace("{l1", lights); + HueLightStatus1(1, &response); + response += F("}"); + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups Result (%s)"), path->c_str()); + WSSend(200, CT_JSON, response); +} + +void HandleHueApi(String *path) +{ +# 861 "/workspace/Tasmota/tasmota/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) from %s"), path->c_str(), Webserver->client().remoteIP().toString().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(F("/invalid/"))) {} + else if (!apilen) HueAuthentication(path); + else if (path->endsWith(F("/"))) HueAuthentication(path); + else if (path->endsWith(F("/config"))) HueConfig(path); + else if (path->indexOf(F("/lights")) >= 0) HueLights(path); + else if (path->indexOf(F("/groups")) >= 0) HueGroups(path); + else if (path->endsWith(F("/schedules"))) HueNotImplemented(path); + else if (path->endsWith(F("/sensors"))) HueNotImplemented(path); + else if (path->endsWith(F("/scenes"))) HueNotImplemented(path); + else if (path->endsWith(F("/rules"))) HueNotImplemented(path); + else if (path->endsWith(F("/resourcelinks"))) HueNotImplemented(path); + else HueGlobalConfig(path); +} + + + + + +bool Xdrv20(uint8_t function) +{ + bool result = false; + +#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) + 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(PSTR("/description.xml"), HandleUpnpSetupHue); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_21_wemo.ino" +# 20 "/workspace/Tasmota/tasmota/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)); + } + + PrepLog_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; +} + + + + + +#ifdef USE_UNISHOX_COMPRESSION + + + +const size_t WEMO_EVENTSERVICE_XML_SIZE = 779; +const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" + "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0A\xC3\xAD\xCE\x20\xB7\xD4\x08" + "\x72\x0F\xC3\xD3\xAC\x6B\x3F\x0B\xCE\x88\x76\xF5\xFC\xC8\xBD\x57\x4C\xF4\x3B\x3A" + "\xC6\xB3\xF0\xF4\xBF\x8F\x0B\x1A\xFA\x81\x0B\x0D\x04\x29\x47\xE1\xE9\xF7\x46\x76" + "\x11\xD8\x08\x58\xC0\x27\x62\xBF\x61\x5D\x31\x0B\xD5\x74\xC8\xCE\xFF\xB6\x38\x20" + "\x4A\xC1\x01\x42\xF1\xE8\x26\xFD\x82\x0E\xE7\xBC\x7A\x1D\x80\x8B\x28\xF4\x3B\x01" + "\x17\x59\x04\x48\xE0\x83\xB9\x1D\x80\x87\xC1\x20\x24\x70\x58\x43\xC0\xDA\xF8\x2C" + "\xC1\x74\x0C\x2F\x82\xD0\x42\x8A\x08\x34\x81\x0B\x92\x42\xF5\x5D\x32\xA0\x41\xCE" + "\x7C\x08\xFA\x42\xF3\xE1\x09\x99\xBE\xAF\x1F\x0F\x61\x93\xF1\xEC\x05\x5E\x0A\x44" + "\xBA\xB2\xA3\x21\x8C\xFC\x1D\x98\x11\xE8\x76\x02\x24\xB3\xD0\x46\x62\xC5\x85\x44" + "\x67\x61\x0B\x67\xE1\xC6\x7A\x1D\x84\x09\x13\x0F\x43\xB0\x12\x34\xC0\x60\x5A\xD8" + "\x4C\xCD\x84\x09\x9A\xAF\xAB\xFB\xC3\xC0\xC5\x75\x73\xB0\x13\xB8\x6A\x3B\x3C\x18" + "\xC1\x0F\xC9\xC2\x91\xBA\x70\xA4\x6E"; + + + +const size_t WEMO_METASERVICE_XML_SIZE = 479; +const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" + "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0B\xC3\x18\x64\x66\xFF\xED\xCE" + "\x3F\x0F\x41\xB6\x6B\xCF\x9F\x87\x21\xE8\x76\x10\x20\xC5\x3D\x06\xEF\x67\xCF\xC3" + "\x8C\xF4\x3B\x08\x10\x62\x9E\x87\x60\x24\x61\x56\x1D\x6E\x71\x05\xBE\xA0\x43\x90" + "\x7E\x1E\x9D\x63\x59\xF8\x43\xCE\x88\x6B\xAB\x2D\xE3\x18\x7A\x1D\x9D\x63\x59\xF8" + "\x7A\x5F\xC7\x85\x8D\x7D\x40\x83\x85\x7D\xD1\x9D\x84\x8E\xC0\x55\xC3\x3E\xC2\xBA" + "\x62\x17\xAA\xE9\x91\x9D\xFF\x6C\x70\x4C\xFC\x04\x5C\x04\x14\x2D\x9E\x82\x6F\xD8" + "\x20\xEC\x9B\xC7\xA1\xD8\x08\xB2\x8F\x43\xB0\x12\x75\xB3\xB0\x10\xF8\x0A\x04\x28" + "\xA0\x83\x48\x10\xB8\x74\x2F\x55\xD3\x2A\x2B\x04\x1C\xB7\xC0\x8F\x9E\x2F\x3E\x10" + "\x99\x9B\xEA\xF1\xF0\xF6\x19\x3F\x1E\xC0\x42\xE0\x68\x12\xF8\x17\x12\xEA\xCA\x8C" + "\x86\x33\xF3\xD5\xFD\xE1\xE3\xD0\xEC\x04\x49\xA7\xA0\x8C\xC5\x8B\x0A\x88\xCE\xC2" + "\x16\xCF\xC3\x8C\xF4\x3B\x08\x12\x26\x1E\x87\x60\x24\x69\x67\xE1\xE8\x76\x02\x76" + "\xDC\x76\x78\x31\x82\x1F\x93\x85\x23\x74\xE1\x48\xDC"; + + + +const size_t WEMO_RESPONSE_STATE_SOAP_SIZE = 282; +const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0C\x68\xD8\x34\x2E\xF1\xE7\xE3\xE1\xEC\x15\x54\x30" + "\xF3\x3B\x0E\xCF\x06\x29\x8D\xBF\x1D\x0D\x83\x42\xF6\x58\xC3\xA6\x7C\x78\xEC\xF6" + "\x58\xC3\xB1\x82\x16\x1C\x76\x1E\xC5\xE3\xCD\xF0\x78\x26\xF0\xF1\x7A\x8C\x82\x60" + "\xBF\x8C\x02\x0E\x16\x76\x1E\xC3\xF0\xF4\xF1\xE6\x43\xB0\x43\x23\xF0\xF4\x16\x79" + "\x9F\x41\xBA\x21\xDB\xD7\xF3\x22\xF5\x5D\x32\xFB\xF0\xCC\xEF\x02\x1E\xDE\x2C\xF8" + "\x7B\x05\xFF\x8F\x32\x1C\xC2\x34\xDE\x3C\xFC\xFE\x67\xA1\xB3\xCC\x75\xFB\x43\x66" + "\x6F\xA8\xF3\x39\x0F\x61\xF8\x7A\x10\x23\x63\x67\xE1\xF4\x21\xE8\x76\x02\x3C\xC3" + "\xD0\xEC\x05\x4C\xFC\xFC\x3D\x0E\xC0\x43\xD8\xCE\xC0\x45\xE1\xA0\xFC\x9C\x29\x1B" + "\x8D"; + + + +const size_t WEMO_SETUP_XML_SIZE = 923; +const char WEMO_SETUP_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" + "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\x21\xCC\x23\x4D\xE3\xCC\x46" + "\x67\xA1\xB3\xAC\xE4\x3A\xD9\xEC\x3F\x0F\x42\x04\x19\x20\x87\x10\xA8\xC8\x63\x3F" + "\x01\x33\x07\x3C\xC3\xCE\xAF\xE0\x41\x36\x79\x9C\x87\xA1\xD8\x40\x8D\x83\x9E\x86" + "\x3F\xAF\x84\x08\xC8\xBA\xC6\xB3\xF0\xF6\x9B\x0E\x43\xD0\xEC\x20\x48\x9C\x7A\x0D" + "\xBE\x16\x62\xC3\xA1\x7F\x7F\x3F\x01\x07\x31\x45\xBD\x4F\xFD\x75\xB9\xD6\x12\x2D" + "\xE0\xCE\x87\xA1\xD8\x09\x18\x21\xE8\x37\x04\x61\x17\x58\xD6\x7E\x17\xB0\x33\x47" + "\x47\xA1\xD8\x08\xB3\x81\x0A\xC8\xB1\xA3\x9F\xCF\xC3\x96\x74\x99\x34\x81\x0E\xD8" + "\x20\xD0\x3D\x08\x59\x08\x5C\x7E\x0B\x17\xA2\x1E\x67\xB4\xD8\x72\x8F\x43\xB0\x88" + "\x59\x08\x5C\x7E\x1E\x9E\x7F\xDB\x04\x3B\xA7\xB4\xD8\x72\xCF\x43\xB0\x81\x22\x71" + "\xE8\x3B\x7A\xFE\x64\x5E\xAB\xA6\x7E\x1C\x67\xA1\xD8\x40\x8F\x2C\xF4\xF3\xF9\x9E" + "\x86\xC8\x2D\xF5\x02\x24\x90\x44\x8A\x09\x7C\x46\x82\x15\x33\xCC\x75\xFB\x43\x66" + "\x6F\xA8\xF3\x39\x0F\x43\xB0\x81\x1F\x09\x04\x3C\x58\xB4\x40\x4E\xC5\x0B\x44\x04" + "\x6C\x58\x11\x71\x52\xD1\x0F\xC3\xD0\x10\xB8\xE0\x21\x65\xF2\x08\xFC\x3B\x05\x8C" + "\xE1\x87\x60\x21\x4D\x3B\x01\x23\x0D\x04\x6C\x08\xF4\x66\x6F\xA8\xBC\x2C\x70\x22" + "\xE1\xEC\xCD\xF5\x02\x4E\x1A\x08\xF8\x09\xE8\x45\xE0\xC6\x08\x2F\xE1\x11\xF8\x08" + "\x34\x81\x0B\x59\x3A\x1B\x06\x84\x7A\x1D\x80\x87\x5C\x11\x37\x2A\x01\x60\xBC\x34" + "\x0D\x75\x7B\xC6\x30\x18\x5F\x0C\xC0\x87\x8A\x03\x02\xE1\x90\x11\xB0\xB0\x5F\xE1" + "\x88\x11\xB0\xB0\x51\xE1\x80\x10\xEE\x82\xDF\x0C\x60\x87\x18\x10\x79\x7D\x04\x2E" + "\x83\xD1\xF8\x7A\x1D\x9F\xCC\xA3\xF2\x70\xA4\x6E"; +#else +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"; +#endif + + + +void LogUpnpWithClient(const char *msg) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "%s from %s"), msg, Webserver->client().remoteIP().toString().c_str()); +} + +void HandleUpnpEvent(void) +{ + LogUpnpWithClient(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>10> 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((action) ? action : 1, (action) ? 1 : 4); +#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(4, 1); +#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) { return false; } + + 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) { +# 177 "/workspace/Tasmota/tasmota/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) { + SetSerial(9600, TS_SERIAL_8N1); + } + 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 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +#ifdef USE_ZIGBEE + +#if defined(USE_ZIGBEE_ZNP) && defined(USE_ZIGBEE_EZSP) + #error "#define USE_ZIGBEE_ZNP and #define USE_ZIGBEE_EZSP are mutually incompatible" +#endif +#if !defined(USE_ZIGBEE_ZNP) && !defined(USE_ZIGBEE_EZSP) + #error "You must select one of: #define USE_ZIGBEE_ZNP or #define USE_ZIGBEE_EZSP" +#endif + + + +#define OCCUPANCY "Occupancy" +#define ZIGBEE_EZSP_RESET_LED 4 + +typedef uint64_t Z_IEEEAddress; +typedef uint16_t Z_ShortAddress; + +const uint16_t BAD_SHORTADDR = 0xFFFE; + +#ifdef USE_ZIGBEE_ZNP +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 +}; +#endif + +#ifdef USE_ZIGBEE_EZSP + +enum EZSPNodeType { + EMBER_UNKNOWN_DEVICE = 0x00, + EMBER_COORDINATOR = 0x01, + EMBER_ROUTER = 0x02, + EMBER_END_DEVICE = 0x03, + EMBER_SLEEPY_END_DEVICE = 0x04 +}; + +enum EZSPDeviceUpdate { + EMBER_STANDARD_SECURITY_SECURED_REJOIN = 0x00, + EMBER_STANDARD_SECURITY_UNSECURED_JOIN = 0x01, + EMBER_DEVICE_LEFT = 0x02, + EMBER_STANDARD_SECURITY_UNSECURED_REJOIN = 0x03, +}; + +enum EZSPJoinDecision { + EMBER_USE_PRECONFIGURED_KEY = 0x00, + EMBER_SEND_KEY_IN_THE_CLEAR = 0x01, + EMBER_DENY_JOIN = 0x02, + EMBER_NO_ACTION = 0x03 +}; + +enum EZSPCurrentSecurytBitMask { + EMBER_STANDARD_SECURITY_MODE = 0x0000, + EMBER_DISTRIBUTED_TRUST_CENTER_MODE = 0x0002, + EMBER_GLOBAL_LINK_KEY = 0x0004, + EMBER_TRUST_CENTER_GLOBAL_LINK_KEY = 0x0004, + EMBER_PRECONFIGURED_NETWORK_KEY_MODE = 0x0008, + EMBER_HAVE_TRUST_CENTER_LINK_KEY = 0x0010, + EMBER_TRUST_CENTER_USES_HASHED_LINK_KEY = 0x0084, + EMBER_HAVE_PRECONFIGURED_KEY = 0x0100, + EMBER_HAVE_NETWORK_KEY = 0x0200, + EMBER_GET_LINK_KEY_WHEN_JOINING = 0x0400, + EMBER_REQUIRE_ENCRYPTED_KEY = 0x0800, + EMBER_NO_FRAME_COUNTER_RESET = 0x1000, + EMBER_GET_PRECONFIGURED_KEY_FROM_INSTALL_CODE = 0x2000, + EMBER_HAVE_TRUST_CENTER_EUI64 = 0x0040 +}; + +enum EZSPJoinMethod { + EMBER_USE_MAC_ASSOCIATION = 0x0, + EMBER_USE_NWK_REJOIN = 0x1, + EMBER_USE_NWK_REJOIN_HAVE_NWK_KEY = 0x2, + EMBER_USE_CONFIGURED_NWK_STATE = 0x3 +}; + +enum EZSPConfigId { + EZSP_CONFIG_PACKET_BUFFER_COUNT = 0x01, + EZSP_CONFIG_NEIGHBOR_TABLE_SIZE = 0x02, + EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT = 0x03, + EZSP_CONFIG_BINDING_TABLE_SIZE = 0x04, + EZSP_CONFIG_ADDRESS_TABLE_SIZE = 0x05, + EZSP_CONFIG_MULTICAST_TABLE_SIZE = 0x06, + EZSP_CONFIG_ROUTE_TABLE_SIZE = 0x07, + EZSP_CONFIG_DISCOVERY_TABLE_SIZE = 0x08, + EZSP_CONFIG_STACK_PROFILE = 0x0C, + EZSP_CONFIG_SECURITY_LEVEL = 0x0D, + EZSP_CONFIG_MAX_HOPS = 0x10, + EZSP_CONFIG_MAX_END_DEVICE_CHILDREN = 0x11, + EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT = 0x12, + EZSP_CONFIG_END_DEVICE_POLL_TIMEOUT = 0x13, + EZSP_CONFIG_TX_POWER_MODE = 0x17, + EZSP_CONFIG_DISABLE_RELAY = 0x18, + EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE = 0x19, + EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE = 0x1A, + EZSP_CONFIG_FRAGMENT_WINDOW_SIZE = 0x1C, + EZSP_CONFIG_FRAGMENT_DELAY_MS = 0x1D, + EZSP_CONFIG_KEY_TABLE_SIZE = 0x1E, + EZSP_CONFIG_APS_ACK_TIMEOUT = 0x1F, + EZSP_CONFIG_BEACON_JITTER_DURATION = 0x20, + EZSP_CONFIG_END_DEVICE_BIND_TIMEOUT = 0x21, + EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD = 0x22, + EZSP_CONFIG_REQUEST_KEY_TIMEOUT = 0x24, + EZSP_CONFIG_CERTIFICATE_TABLE_SIZE = 0x29, + EZSP_CONFIG_APPLICATION_ZDO_FLAGS = 0x2A, + EZSP_CONFIG_BROADCAST_TABLE_SIZE = 0x2B, + EZSP_CONFIG_MAC_FILTER_TABLE_SIZE = 0x2C, + EZSP_CONFIG_SUPPORTED_NETWORKS = 0x2D, + EZSP_CONFIG_SEND_MULTICASTS_TO_SLEEPY_ADDRESS = 0x2E, + EZSP_CONFIG_ZLL_GROUP_ADDRESSES = 0x2F, + EZSP_CONFIG_ZLL_RSSI_THRESHOLD = 0x30, + EZSP_CONFIG_MTORR_FLOW_CONTROL = 0x33, + EZSP_CONFIG_RETRY_QUEUE_SIZE = 0x34, + EZSP_CONFIG_NEW_BROADCAST_ENTRY_THRESHOLD = 0x35, + EZSP_CONFIG_BROADCAST_MIN_ACKS_NEEDED = 0x37, + EZSP_CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S = 0x38, + EZSP_CONFIG_CTUNE_VALUE = 0x39 +}; + +enum EZSPValueId { + EZSP_VALUE_TOKEN_STACK_NODE_DATA = 0x00, + EZSP_VALUE_MAC_PASSTHROUGH_FLAGS = 0x01, + EZSP_VALUE_EMBERNET_PASSTHROUGH_SOURCE_ADDRESS = 0x02, + EZSP_VALUE_FREE_BUFFERS = 0x03, + EZSP_VALUE_UART_SYNCH_CALLBACKS = 0x04, + EZSP_VALUE_MAXIMUM_INCOMING_TRANSFER_SIZE = 0x05, + EZSP_VALUE_MAXIMUM_OUTGOING_TRANSFER_SIZE = 0x06, + EZSP_VALUE_STACK_TOKEN_WRITING = 0x07, + EZSP_VALUE_STACK_IS_PERFORMING_REJOIN = 0x08, + EZSP_VALUE_MAC_FILTER_LIST = 0x09, + EZSP_VALUE_EXTENDED_SECURITY_BITMASK = 0x0A, + EZSP_VALUE_NODE_SHORT_ID = 0x0B, + EZSP_VALUE_DESCRIPTOR_CAPABILITY = 0x0C, + EZSP_VALUE_STACK_DEVICE_REQUEST_SEQUENCE_NUMBER = 0x0D, + EZSP_VALUE_RADIO_HOLD_OFF = 0x0E, + EZSP_VALUE_ENDPOINT_FLAGS = 0x0F, + EZSP_VALUE_MFG_SECURITY_CONFIG = 0x10, + EZSP_VALUE_VERSION_INFO = 0x11, + EZSP_VALUE_NEXT_HOST_REJOIN_REASON = 0x12, + EZSP_VALUE_LAST_REJOIN_REASON = 0x13, + EZSP_VALUE_NEXT_ZIGBEE_SEQUENCE_NUMBER = 0x14, + EZSP_VALUE_CCA_THRESHOLD = 0x15, + EZSP_VALUE_SET_COUNTER_THRESHOLD = 0x17, + EZSP_VALUE_RESET_COUNTER_THRESHOLDS = 0x18, + EZSP_VALUE_CLEAR_COUNTERS = 0x19, + EZSP_VALUE_CERTIFICATE_283K1 = 0x1A, + EZSP_VALUE_PUBLIC_KEY_283K1 = 0x1B, + EZSP_VALUE_PRIVATE_KEY_283K1 = 0x1C, + EZSP_VALUE_NWK_FRAME_COUNTER = 0x23, + EZSP_VALUE_APS_FRAME_COUNTER = 0x24, + EZSP_VALUE_RETRY_DEVICE_TYPE = 0x25, + EZSP_VALUE_ENABLE_R21_BEHAVIOR = 0x29, + EZSP_VALUE_ANTENNA_MODE = 0x30, + EZSP_VALUE_ENABLE_PTA = 0x31, + EZSP_VALUE_PTA_OPTIONS = 0x32, + EZSP_VALUE_MFGLIB_OPTIONS = 0x33, + EZSP_VALUE_USE_NEGOTIATED_POWER_BY_LPD = 0x34, + EZSP_VALUE_PTA_PWM_OPTIONS = 0x35, + EZSP_VALUE_PTA_DIRECTIONAL_PRIORITY_PULSE_WIDTH = 0x36, + EZSP_VALUE_PTA_PHY_SELECT_TIMEOUT = 0x37, + EZSP_VALUE_ANTENNA_RX_MODE = 0x38, + EZSP_VALUE_NWK_KEY_TIMEOUT = 0x39, + EZSP_VALUE_FORCE_TX_AFTER_FAILED_CCA_ATTEMPTS = 0x3A, + EZSP_VALUE_TRANSIENT_KEY_TIMEOUT_S = 0x3B, + ZSP_VALUE_COULOMB_COUNTER_USAGE = 0x3C, + EZSP_VALUE_MAX_BEACONS_TO_STORE = 0x3D, + EZSP_VALUE_END_DEVICE_TIMEOUT_OPTIONS_MASK = 0x3E, + EZSP_VALUE_END_DEVICE_KEEP_ALIVE_SUPPORT_MODE = 0x3F, + EZSP_VALUE_GPIO_RADIO_POWER_MASK = 0x40, + EZSP_VALUE_ACTIVE_RADIO_CONFIG = 0x41 +}; + +enum EZSPEmberStatusId { + EMBER_SUCCESS = 0x00, + EMBER_ERR_FATAL = 0x01, + EMBER_BAD_ARGUMENT = 0x02, + EMBER_EEPROM_MFG_STACK_VERSION_MISMATCH = 0x04, + EMBER_INCOMPATIBLE_STATIC_MEMORY_DEFINITIONS = 0x05, + EMBER_EEPROM_MFG_VERSION_MISMATCH = 0x06, + EMBER_EEPROM_STACK_VERSION_MISMATCH = 0x07, + EMBER_NO_BUFFERS = 0x18, + EMBER_SERIAL_INVALID_BAUD_RATE = 0x20, + EMBER_SERIAL_INVALID_PORT = 0x21, + EMBER_SERIAL_TX_OVERFLOW = 0x22, + EMBER_SERIAL_RX_OVERFLOW = 0x23, + EMBER_SERIAL_RX_FRAME_ERROR = 0x24, + EMBER_SERIAL_RX_PARITY_ERROR = 0x25, + EMBER_SERIAL_RX_EMPTY = 0x26, + EMBER_SERIAL_RX_OVERRUN_ERROR = 0x27, + EMBER_MAC_TRANSMIT_QUEUE_FULL = 0x39, + EMBER_MAC_UNKNOWN_HEADER_TYPE = 0x3A, + EMBER_MAC_SCANNING = 0x3D, + EMBER_MAC_NO_DATA = 0x31, + EMBER_MAC_JOINED_NETWORK = 0x32, + EMBER_MAC_BAD_SCAN_DURATION = 0x33, + EMBER_MAC_INCORRECT_SCAN_TYPE = 0x34, + EMBER_MAC_INVALID_CHANNEL_MASK = 0x35, + EMBER_MAC_COMMAND_TRANSMIT_FAILURE = 0x36, + EMBER_MAC_NO_ACK_RECEIVED = 0x40, + EMBER_MAC_INDIRECT_TIMEOUT = 0x42, + EMBER_SIM_EEPROM_ERASE_PAGE_GREEN = 0x43, + EMBER_SIM_EEPROM_ERASE_PAGE_RED = 0x44, + EMBER_SIM_EEPROM_FULL = 0x45, + EMBER_ERR_FLASH_WRITE_INHIBITED = 0x46, + EMBER_ERR_FLASH_VERIFY_FAILED = 0x47, + EMBER_SIM_EEPROM_INIT_1_FAILED = 0x48, + EMBER_SIM_EEPROM_INIT_2_FAILED = 0x49, + EMBER_SIM_EEPROM_INIT_3_FAILED = 0x4A, + EMBER_ERR_FLASH_PROG_FAIL = 0x4B, + EMBER_ERR_FLASH_ERASE_FAIL = 0x4C, + EMBER_ERR_BOOTLOADER_TRAP_TABLE_BAD = 0x58, + EMBER_ERR_BOOTLOADER_TRAP_UNKNOWN = 0x59, + EMBER_ERR_BOOTLOADER_NO_IMAGE = 0x5A, + EMBER_DELIVERY_FAILED = 0x66, + EMBER_BINDING_INDEX_OUT_OF_RANGE = 0x69, + EMBER_ADDRESS_TABLE_INDEX_OUT_OF_RANGE = 0x6A, + EMBER_INVALID_BINDING_INDEX = 0x6C, + EMBER_INVALID_CALL = 0x70, + EMBER_COST_NOT_KNOWN = 0x71, + EMBER_MAX_MESSAGE_LIMIT_REACHED = 0x72, + EMBER_MESSAGE_TOO_LONG = 0x74, + EMBER_BINDING_IS_ACTIVE = 0x75, + EMBER_ADDRESS_TABLE_ENTRY_IS_ACTIVE = 0x76, + EMBER_ADC_CONVERSION_DONE = 0x80, + EMBER_ADC_CONVERSION_BUSY = 0x81, + EMBER_ADC_CONVERSION_DEFERRED = 0x82, + EMBER_ADC_NO_CONVERSION_PENDING = 0x84, + EMBER_SLEEP_INTERRUPTED = 0x85, + EMBER_PHY_TX_UNDERFLOW = 0x88, + EMBER_PHY_TX_INCOMPLETE = 0x89, + EMBER_PHY_INVALID_CHANNEL = 0x8A, + EMBER_PHY_INVALID_POWER = 0x8B, + EMBER_PHY_TX_BUSY = 0x8C, + EMBER_PHY_TX_CCA_FAIL = 0x8D, + EMBER_PHY_OSCILLATOR_CHECK_FAILED = 0x8E, + EMBER_PHY_ACK_RECEIVED = 0x8F, + EMBER_NETWORK_UP = 0x90, + EMBER_NETWORK_DOWN = 0x91, + EMBER_JOIN_FAILED = 0x94, + EMBER_MOVE_FAILED = 0x96, + EMBER_CANNOT_JOIN_AS_ROUTER = 0x98, + EMBER_NODE_ID_CHANGED = 0x99, + EMBER_PAN_ID_CHANGED = 0x9A, + EMBER_NO_BEACONS = 0xAB, + EMBER_RECEIVED_KEY_IN_THE_CLEAR = 0xAC, + EMBER_NO_NETWORK_KEY_RECEIVED = 0xAD, + EMBER_NO_LINK_KEY_RECEIVED = 0xAE, + EMBER_PRECONFIGURED_KEY_REQUIRED = 0xAF, + EMBER_NOT_JOINED = 0x93, + EMBER_INVALID_SECURITY_LEVEL = 0x95, + EMBER_NETWORK_BUSY = 0xA1, + EMBER_INVALID_ENDPOINT = 0xA3, + EMBER_BINDING_HAS_CHANGED = 0xA4, + EMBER_INSUFFICIENT_RANDOM_DATA = 0xA5, + EMBER_APS_ENCRYPTION_ERROR = 0xA6, + EMBER_SECURITY_STATE_NOT_SET = 0xA8, + EMBER_KEY_TABLE_INVALID_ADDRESS = 0xB3, + EMBER_SECURITY_CONFIGURATION_INVALID = 0xB7, + EMBER_TOO_SOON_FOR_SWITCH_KEY = 0xB8, + EMBER_KEY_NOT_AUTHORIZED = 0xBB, + EMBER_SECURITY_DATA_INVALID = 0xBD, + EMBER_SOURCE_ROUTE_FAILURE = 0xA9, + EMBER_MANY_TO_ONE_ROUTE_FAILURE = 0xAA, + EMBER_STACK_AND_HARDWARE_MISMATCH = 0xB0, + EMBER_INDEX_OUT_OF_RANGE = 0xB1, + EMBER_TABLE_FULL = 0xB4, + EMBER_TABLE_ENTRY_ERASED = 0xB6, + EMBER_LIBRARY_NOT_PRESENT = 0xB5, + EMBER_OPERATION_IN_PROGRESS = 0xBA, +}; + +enum EZSPStatusId { + EZSP_SUCCESS = 0x00, + EZSP_SPI_ERR_FATAL = 0x10, + EZSP_SPI_ERR_NCP_RESET = 0x11, + EZSP_SPI_ERR_OVERSIZED_EZSP_FRAME = 0x12, + EZSP_SPI_ERR_ABORTED_TRANSACTION = 0x13, + EZSP_SPI_ERR_MISSING_FRAME_TERMINATOR = 0x14, + EZSP_SPI_ERR_WAIT_SECTION_TIMEOUT = 0x15, + EZSP_SPI_ERR_NO_FRAME_TERMINATOR = 0x16, + EZSP_SPI_ERR_EZSP_COMMAND_OVERSIZED = 0x17, + EZSP_SPI_ERR_EZSP_RESPONSE_OVERSIZED = 0x18, + EZSP_SPI_WAITING_FOR_RESPONSE = 0x19, + EZSP_SPI_ERR_HANDSHAKE_TIMEOUT = 0x1A, + EZSP_SPI_ERR_STARTUP_TIMEOUT = 0x1B, + EZSP_SPI_ERR_STARTUP_FAIL = 0x1C, + EZSP_SPI_ERR_UNSUPPORTED_SPI_COMMAND = 0x1D, + EZSP_ASH_IN_PROGRESS = 0x20, + EZSP_HOST_FATAL_ERROR = 0x21, + EZSP_ASH_NCP_FATAL_ERROR = 0x22, + EZSP_DATA_FRAME_TOO_LONG = 0x23, + EZSP_DATA_FRAME_TOO_SHORT = 0x24, + EZSP_NO_TX_SPACE = 0x25, + EZSP_NO_RX_SPACE = 0x26, + EZSP_NO_RX_DATA = 0x27, + EZSP_NOT_CONNECTED = 0x28, + EZSP_ERROR_VERSION_NOT_SET = 0x30, + EZSP_ERROR_INVALID_FRAME_ID = 0x31, + EZSP_ERROR_WRONG_DIRECTION = 0x32, + EZSP_ERROR_TRUNCATED = 0x33, + EZSP_ERROR_OVERFLOW = 0x34, + EZSP_ERROR_OUT_OF_MEMORY = 0x35, + EZSP_ERROR_INVALID_VALUE = 0x36, + EZSP_ERROR_INVALID_ID = 0x37, + EZSP_ERROR_INVALID_CALL = 0x38, + EZSP_ERROR_NO_RESPONSE = 0x39, + EZSP_ERROR_COMMAND_TOO_LONG = 0x40, + EZSP_ERROR_QUEUE_FULL = 0x41, + EZSP_ERROR_COMMAND_FILTERED = 0x42, + EZSP_ERROR_SECURITY_KEY_ALREADY_SET = 0x43, + EZSP_ERROR_SECURITY_TYPE_INVALID = 0x44, + EZSP_ERROR_SECURITY_PARAMETERS_INVALID = 0x45, + EZSP_ERROR_SECURITY_PARAMETERS_ALREADY_SET = 0x46, + EZSP_ERROR_SECURITY_KEY_NOT_SET = 0x47, + EZSP_ERROR_SECURITY_PARAMETERS_NOT_SET = 0x48, + EZSP_ERROR_UNSUPPORTED_CONTROL = 0x49, + EZSP_ERROR_UNSECURE_FRAME = 0x4A, + EZSP_NO_ERROR = 0xFF +}; + +enum EZSPPolicyId { + EZSP_TRUST_CENTER_POLICY = 0x00, + EZSP_BINDING_MODIFICATION_POLICY = 0x01, + EZSP_UNICAST_REPLIES_POLICY = 0x02, + EZSP_POLL_HANDLER_POLICY = 0x03, + EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY = 0x04, + EZSP_TC_KEY_REQUEST_POLICY = 0x05, + EZSP_APP_KEY_REQUEST_POLICY = 0x06, + EZSP_PACKET_VALIDATE_LIBRARY_POLICY = 0x07, + EZSP_ZLL_POLICY = 0x08, + EZSP_TC_REJOINS_USING_WELL_KNOWN_KEY_POLICY = 0x09 +}; + +enum EZSPDecisionBitmask { + EZSP_DECISION_BITMASK_DEFAULT_CONFIGURATION = 0x0000, + EZSP_DECISION_ALLOW_JOINS = 0x0001, + EZSP_DECISION_ALLOW_UNSECURED_REJOINS = 0x0002, + EZSP_DECISION_SEND_KEY_IN_CLEAR = 0x0004, + EZSP_DECISION_IGNORE_UNSECURED_REJOINS = 0x0008, + EZSP_DECISION_JOINS_USE_INSTALL_CODE_KEY = 0x0010, + EZSP_DECISION_DEFER_JOINS = 0x0020 +}; + +enum EZSPDecisionId { + EZSP_DEFER_JOINS_REJOINS_HAVE_LINK_KEY = 0x07, + EZSP_DISALLOW_BINDING_MODIFICATION = 0x10, + EZSP_ALLOW_BINDING_MODIFICATION = 0x11, + EZSP_CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS = 0x12, + EZSP_HOST_WILL_NOT_SUPPLY_REPLY = 0x20, + EZSP_HOST_WILL_SUPPLY_REPLY = 0x21, + EZSP_POLL_HANDLER_IGNORE = 0x30, + EZSP_POLL_HANDLER_CALLBACK = 0x31, + EZSP_MESSAGE_TAG_ONLY_IN_CALLBACK = 0x40, + EZSP_MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK = 0x41, + EZSP_DENY_TC_KEY_REQUESTS = 0x50, + EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY = 0x51, + EZSP_ALLOW_TC_KEY_REQUEST_AND_GENERATE_NEW_KEY = 0x52, + EZSP_DENY_APP_KEY_REQUESTS = 0x60, + EZSP_ALLOW_APP_KEY_REQUESTS = 0x61, + EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_ENABLED = 0x62, + EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_DISABLED = 0x63 +}; + +enum EZSP_ZdoConfigurationFlags { + EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS = 0x01, + EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS = 0x02, + EMBER_APP_HANDLES_ZDO_ENDPOINT_REQUESTS = 0x04, + EMBER_APP_HANDLES_ZDO_BINDING_REQUESTS = 0x08 +}; + +enum EZSP_EmberIncomingMessageType { + EMBER_INCOMING_UNICAST = 0x00, + EMBER_INCOMING_UNICAST_REPLY = 0x01, + EMBER_INCOMING_MULTICAST = 0x02, + EMBER_INCOMING_MULTICAST_LOOPBACK = 0x03, + EMBER_INCOMING_BROADCAST = 0x04, + EMBER_INCOMING_BROADCAST_LOOPBACK = 0x05, + EMBER_INCOMING_MANY_TO_ONE_ROUTE_REQUEST = 0x06 +}; + +enum EZSP_EmberApsOption { + EMBER_APS_OPTION_NONE = 0x0000, + EMBER_APS_OPTION_ENCRYPTION = 0x0020, + EMBER_APS_OPTION_RETRY = 0x0040, + EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY = 0x0100, + EMBER_APS_OPTION_FORCE_ROUTE_DISCOVERY = 0x0200, + EMBER_APS_OPTION_SOURCE_EUI64 = 0x0400, + EMBER_APS_OPTION_DESTINATION_EUI64 = 0x0800, + EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY = 0x1000, + EMBER_APS_OPTION_POLL_RESPONSE = 0x2000, + EMBER_APS_OPTION_ZDO_RESPONSE_REQUIRED = 0x4000, + EMBER_APS_OPTION_FRAGMENT = 0x8000 +}; + +enum EZSP_EmberOutgoingMessageType { + EMBER_OUTGOING_DIRECT = 0x00, + EMBER_OUTGOING_VIA_ADDRESS_TABLE = 0x01, + EMBER_OUTGOING_VIA_BINDING = 0x02, + EMBER_OUTGOING_MULTICAST = 0x03, + EMBER_OUTGOING_MULTICAST_WITH_ALIAS = 0x04, + EMBER_OUTGOING_BROADCAST_WITH_ALIAS = 0x05, + EMBER_OUTGOING_BROADCAST = 0x06 +}; + +enum EZSP_EmberKeyStructBitmask { + EMBER_KEY_HAS_SEQUENCE_NUMBER = 0x0001, + EMBER_KEY_HAS_OUTGOING_FRAME_COUNTER = 0x0002, + EMBER_KEY_HAS_INCOMING_FRAME_COUNTER = 0x0004, + EMBER_KEY_HAS_PARTNER_EUI64 = 0x0008, + EMBER_KEY_IS_AUTHORIZED = 0x0010, + EMBER_KEY_PARTNER_IS_SLEEPY = 0x0020, + EMBER_UNCONFIRMED_TRANSIENT_KEY = 0x0040 +}; + +enum EZSP_EmberKeyType { + EMBER_TRUST_CENTER_LINK_KEY = 1, + EMBER_CURRENT_NETWORK_KEY = 3, + EMBER_NEXT_NETWORK_KEY = 4, + EMBER_APPLICATION_LINK_KEY = 5 +}; + + +enum EZSP_ZDO { + ZDO_NWK_addr_req = 0x0000, + ZDO_IEEE_addr_req = 0x0001, + ZDO_Node_Desc_req = 0x0002, + ZDO_Power_Desc_req = 0x0003, + ZDO_Simple_Desc_req = 0x0004, + ZDO_Active_EP_req = 0x0005, + ZDO_Match_Desc_req = 0x0006, + ZDO_Complex_Desc_req = 0x0010, + ZDO_User_Desc_req = 0x0011, + ZDO_Discovery_Cache_req = 0x0012, + ZDO_Device_annce = 0x0013, + ZDO_User_Desc_set = 0x0014, + ZDO_System_Server_Discovery_req = 0x0015, + ZDO_Discovery_store_req = 0x0016, + ZDO_Node_Desc_store_req = 0x0017, + ZDO_Active_EP_store_req = 0x0019, + ZDO_Simple_Desc_store_req = 0x001A, + ZDO_Remove_node_cache_req = 0x001B, + ZDO_Find_node_cache_req = 0x001C, + ZDO_Extended_Simple_Desc_req = 0x001D, + ZDO_Extended_Active_EP_req = 0x001E, + ZDO_Parent_annce = 0x001F, + + ZDO_End_Device_Bind_req = 0x0020, + ZDO_Bind_req = 0x0021, + ZDO_Unbind_req = 0x0022, + + ZDO_Mgmt_Lqi_req = 0x0031, + ZDO_Mgmt_Rtg_req = 0x0032, + ZDO_Mgmt_Bind_req = 0x0033, + ZDO_Mgmt_Leave_req = 0x0034, + ZDO_Mgmt_Permit_Joining_req = 0x0036, + ZDO_Mgmt_NWK_Update_req = 0x0038, + + + + ZDO_NWK_addr_rsp = 0x8000, + ZDO_IEEE_addr_rsp = 0x8001, + ZDO_Node_Desc_rsp = 0x8002, + ZDO_Power_Desc_rsp = 0x8003, + ZDO_Simple_Desc_rsp = 0x8004, + ZDO_Active_EP_rsp = 0x8005, + ZDO_Match_Desc_rsp = 0x8006, + ZDO_Complex_Desc_rsp = 0x8010, + ZDO_User_Desc_rsp = 0x8011, + ZDO_Discovery_Cache_rsp = 0x8012, + ZDO_User_Desc_conf = 0x8014, + ZDO_System_Server_Discovery_rsp = 0x8015, + ZDO_Discovery_Store_rsp = 0x8016, + ZDO_Node_Desc_store_rsp = 0x8017, + ZDO_Power_Desc_store_rsp = 0x8018, + ZDO_Active_EP_store_rsp = 0x8019, + ZDO_Simple_Desc_store_rsp = 0x801A, + ZDO_Remove_node_cache_rsp = 0x801B, + ZDO_Find_node_cache_rsp = 0x801C, + ZDO_Extended_Simple_Desc_rsp = 0x801D, + ZDO_Extended_Active_EP_rsp = 0x801E, + ZDO_Parent_annce_rsp = 0x801F, + + ZDO_End_Device_Bind_rsp = 0x8020, + ZDO_Bind_rsp = 0x8021, + ZDO_Unbind_rsp = 0x8022, + + ZDO_Mgmt_Lqi_rsp = 0x8031, + ZDO_Mgmt_Rtg_rsp = 0x8032, + ZDO_Mgmt_Bind_rsp = 0x8033, + ZDO_Mgmt_Leave_rsp = 0x8034, + ZDO_Mgmt_Permit_Joining_rsp = 0x8036, + ZDO_Mgmt_NWK_Update_rsp = 0x8038, +}; + +enum EZSP_Commands { + EZSP_version = 0x0000, + EZSP_getLibraryStatus = 0x0001, + EZSP_addEndpoint = 0x0002, + EZSP_getExtendedValue = 0x0003, + EZSP_getNextBeacon = 0x0004, + EZSP_nop = 0x0005, + EZSP_callback = 0x0006, + EZSP_noCallbacks = 0x0007, + EZSP_getNumStoredBeacons = 0x0008, + EZSP_setToken = 0x0009, + EZSP_getToken = 0x000A, + EZSP_getMfgToken = 0x000B, + EZSP_setMfgToken = 0x000C, + EZSP_stackTokenChangedHandler = 0x000D, + EZSP_setTimer = 0x000E, + EZSP_timerHandler = 0x000F, + EZSP_setConcentrator = 0x0010, + EZSP_setBrokenRouteErrorCode = 0x0011, + EZSP_debugWrite = 0x0012, + EZSP_getXncpInfo = 0x0013, + EZSP_requestLinkKey = 0x0014, + EZSP_setManufacturerCode = 0x0015, + EZSP_setPowerDescriptor = 0x0016, + EZSP_networkInit = 0x0017, + EZSP_networkState = 0x0018, + EZSP_stackStatusHandler = 0x0019, + EZSP_startScan = 0x001A, + EZSP_networkFoundHandler = 0x001B, + EZSP_scanCompleteHandler = 0x001C, + EZSP_stopScan = 0x001D, + EZSP_formNetwork = 0x001E, + EZSP_joinNetwork = 0x001F, + EZSP_leaveNetwork = 0x0020, + EZSP_findAndRejoinNetwork = 0x0021, + EZSP_permitJoining = 0x0022, + EZSP_childJoinHandler = 0x0023, + EZSP_trustCenterJoinHandler = 0x0024, + EZSP_zllClearTokens = 0x0025, + EZSP_getEui64 = 0x0026, + EZSP_getNodeId = 0x0027, + EZSP_getNetworkParameters = 0x0028, + EZSP_getParentChildParameters = 0x0029, + EZSP_clearBindingTable = 0x002A, + EZSP_setBinding = 0x002B, + EZSP_getBinding = 0x002C, + EZSP_deleteBinding = 0x002D, + EZSP_bindingIsActive = 0x002E, + EZSP_getBindingRemoteNodeId = 0x002F, + EZSP_setBindingRemoteNodeId = 0x0030, + EZSP_remoteSetBindingHandler = 0x0031, + EZSP_remoteDeleteBindingHandler = 0x0032, + EZSP_maximumPayloadLength = 0x0033, + EZSP_sendUnicast = 0x0034, + EZSP_getDutyCycleState = 0x0035, + EZSP_sendBroadcast = 0x0036, + EZSP_proxyBroadcast = 0x0037, + EZSP_sendMulticast = 0x0038, + EZSP_sendReply = 0x0039, + EZSP_sendMulticastWithAlias = 0x003A, + EZSP_joinNetworkDirectly = 0x003B, + EZSP_clearStoredBeacons = 0x003C, + EZSP_getFirstBeacon = 0x003D, + EZSP_getNeighborFrameCounter = 0x003E, + EZSP_messageSentHandler = 0x003F, + EZSP_setDutyCycleLimitsInStack = 0x0040, + EZSP_sendManyToOneRouteRequest = 0x0041, + EZSP_pollForData = 0x0042, + EZSP_pollCompleteHandler = 0x0043, + EZSP_pollHandler = 0x0044, + EZSP_incomingMessageHandler = 0x0045, + EZSP_macFilterMatchMessageHandler = 0x0046, + EZSP_customFrame = 0x0047, + EZSP_energyScanResultHandler = 0x0048, + EZSP_getRandomNumber = 0x0049, + EZSP_getChildData = 0x004A, + EZSP_getDutyCycleLimits = 0x004B, + EZSP_getCurrentDutyCycle = 0x004C, + EZSP_dutyCycleHandler = 0x004D, + EZSP_getTimer = 0x004E, + EZSP_getTrueRandomEntropySource = 0x004F, + EZSP_unicastCurrentNetworkKey = 0x0050, + EZSP_sendRawMessageExtended = 0x0051, + EZSP_getConfigurationValue = 0x0052, + EZSP_setConfigurationValue = 0x0053, + EZSP_customFrameHandler = 0x0054, + EZSP_setPolicy = 0x0055, + EZSP_getPolicy = 0x0056, + EZSP_invalidCommand = 0x0058, + EZSP_setSourceRouteDiscoveryMode = 0x005A, + EZSP_addressTableEntryIsActive = 0x005B, + EZSP_setAddressTableRemoteEui64 = 0x005C, + EZSP_setAddressTableRemoteNodeId = 0x005D, + EZSP_getAddressTableRemoteEui64 = 0x005E, + EZSP_getAddressTableRemoteNodeId = 0x005F, + EZSP_lookupNodeIdByEui64 = 0x0060, + EZSP_lookupEui64ByNodeId = 0x0061, + EZSP_incomingSenderEui64Handler = 0x0062, + EZSP_getMulticastTableEntry = 0x0063, + EZSP_setMulticastTableEntry = 0x0064, + EZSP_readAndClearCounters = 0x0065, + EZSP_addOrUpdateKeyTableEntry = 0x0066, + EZSP_sendTrustCenterLinkKey = 0x0067, + EZSP_setInitialSecurityState = 0x0068, + EZSP_getCurrentSecurityState = 0x0069, + EZSP_getKey = 0x006A, + EZSP_clearTransientLinkKeys = 0x006B, + EZSP_updateTcLinkKey = 0x006C, + EZSP_getTransientKeyTableEntry = 0x006D, + EZSP_switchNetworkKeyHandler = 0x006E, + EZSP_aesMmoHash = 0x006F, + EZSP_gpSinkTableInit = 0x0070, + EZSP_getKeyTableEntry = 0x0071, + EZSP_setKeyTableEntry = 0x0072, + EZSP_broadcastNextNetworkKey = 0x0073, + EZSP_broadcastNetworkKeySwitch = 0x0074, + EZSP_findKeyTableEntry = 0x0075, + EZSP_eraseKeyTableEntry = 0x0076, + EZSP_becomeTrustCenter = 0x0077, + EZSP_dsaVerifyHandler = 0x0078, + EZSP_getNeighbor = 0x0079, + EZSP_neighborCount = 0x007A, + EZSP_getRouteTableEntry = 0x007B, + EZSP_idConflictHandler = 0x007C, + EZSP_incomingManyToOneRouteRequestHandler = 0x007D, + EZSP_setExtendedTimeout = 0x007E, + EZSP_getExtendedTimeout = 0x007F, + EZSP_incomingRouteErrorHandler = 0x0080, + EZSP_echo = 0x0081, + EZSP_replaceAddressTableEntry = 0x0082, + EZSP_mfglibStart = 0x0083, + EZSP_mfglibEnd = 0x0084, + EZSP_mfglibStartTone = 0x0085, + EZSP_mfglibStopTone = 0x0086, + EZSP_mfglibStartStream = 0x0087, + EZSP_mfglibStopStream = 0x0088, + EZSP_mfglibSendPacket = 0x0089, + EZSP_mfglibSetChannel = 0x008A, + EZSP_mfglibGetChannel = 0x008B, + EZSP_mfglibSetPower = 0x008C, + EZSP_mfglibGetPower = 0x008D, + EZSP_mfglibRxHandler = 0x008E, + EZSP_launchStandaloneBootloader = 0x008F, + EZSP_sendBootloadMessage = 0x0090, + EZSP_getStandaloneBootloaderVersionPlatMicroPhy = 0x0091, + EZSP_incomingBootloadMessageHandler = 0x0092, + EZSP_bootloadTransmitCompleteHandler = 0x0093, + EZSP_aesEncrypt = 0x0094, + EZSP_overrideCurrentChannel = 0x0095, + EZSP_sendRawMessage = 0x0096, + EZSP_macPassthroughMessageHandler = 0x0097, + EZSP_rawTransmitCompleteHandler = 0x0098, + EZSP_setRadioPower = 0x0099, + EZSP_setRadioChannel = 0x009A, + EZSP_zigbeeKeyEstablishmentHandler = 0x009B, + EZSP_energyScanRequest = 0x009C, + EZSP_delayTest = 0x009D, + EZSP_generateCbkeKeysHandler = 0x009E, + EZSP_calculateSmacs = 0x009F, + EZSP_calculateSmacsHandler = 0x00A0, + EZSP_clearTemporaryDataMaybeStoreLinkKey = 0x00A1, + EZSP_setPreinstalledCbkeData = 0x00A2, + EZSP_dsaVerify = 0x00A3, + EZSP_generateCbkeKeys = 0x00A4, + EZSP_getCertificate = 0x00A5, + EZSP_dsaSign = 0x00A6, + EZSP_dsaSignHandler = 0x00A7, + EZSP_removeDevice = 0x00A8, + EZSP_unicastNwkKeyUpdate = 0x00A9, + EZSP_getValue = 0x00AA, + EZSP_setValue = 0x00AB, + EZSP_setGpioCurrentConfiguration = 0x00AC, + EZSP_setGpioPowerUpDownConfiguration = 0x00AD, + EZSP_setGpioRadioPowerMask = 0x00AE, + EZSP_addTransientLinkKey = 0x00AF, + EZSP_dsaVerify283k1 = 0x00B0, + EZSP_clearKeyTable = 0x00B1, + EZSP_zllNetworkOps = 0x00B2, + EZSP_zllSetInitialSecurityState = 0x00B3, + EZSP_zllStartScan = 0x00B4, + EZSP_zllSetRxOnWhenIdle = 0x00B5, + EZSP_zllNetworkFoundHandler = 0x00B6, + EZSP_zllScanCompleteHandler = 0x00B7, + EZSP_zllAddressAssignmentHandler = 0x00B8, + EZSP_setLogicalAndRadioChannel = 0x00B9, + EZSP_getLogicalChannel = 0x00BA, + EZSP_zllTouchLinkTargetHandler = 0x00BB, + EZSP_zllGetTokens = 0x00BC, + EZSP_zllSetDataToken = 0x00BD, + EZSP_isZllNetwork = 0x00BE, + EZSP_zllSetNonZllNetwork = 0x00BF, + EZSP_gpProxyTableLookup = 0x00C0, + EZSP_getSourceRouteTableEntry = 0x00C1, + EZSP_getSourceRouteTableFilledSize = 0x00C2, + EZSP_getSourceRouteTableTotalSize = 0x00C3, + EZSP_gpepIncomingMessageHandler = 0x00C5, + EZSP_dGpSend = 0x00C6, + EZSP_dGpSentHandler = 0x00C7, + EZSP_gpProxyTableGetEntry = 0x00C8, + EZSP_gpProxyTableProcessGpPairing = 0x00C9, + EZSP_setSecurityKey = 0x00CA, + EZSP_setSecurityParameters = 0x00CB, + EZSP_resetToFactoryDefaults = 0x00CC, + EZSP_getSecurityKeyStatus = 0x00CD, + EZSP_getTransientLinkKey = 0x00CE, + EZSP_zllSetSecurityStateWithoutKey = 0x00CF, + EZSP_setRoutingShortcutThreshold = 0x00D0, + EZSP_getRoutingShortcutThreshold = 0x00D1, + EZSP_unusedPanIdFoundHandler = 0x00D2, + EZSP_findUnusedPanId = 0x00D3, + EZSP_zllSetRadioIdleMode = 0x00D4, + EZSP_setZllNodeType = 0x00D5, + EZSP_setZllAdditionalState = 0x00D6, + EZSP_zllOperationInProgress = 0x00D7, + EZSP_zllRxOnWhenIdleGetActive = 0x00D8, + EZSP_getZllPrimaryChannelMask = 0x00D9, + EZSP_getZllSecondaryChannelMask = 0x00DA, + EZSP_setZllPrimaryChannelMask = 0x00DB, + EZSP_setZllSecondaryChannelMask = 0x00DC, + EZSP_gpSinkTableGetEntry = 0x00DD, + EZSP_gpSinkTableLookup = 0x00DE, + EZSP_gpSinkTableSetEntry = 0x00DF, + EZSP_gpSinkTableRemoveEntry = 0x00E0, + EZSP_gpSinkTableFindOrAllocateEntry = 0x00E1, + EZSP_gpSinkTableClearAll = 0x00E2, + EZSP_setLongUpTime = 0x00E3, + EZSP_setHubConnectivity = 0x00E4, + EZSP_isUpTimeLong = 0x00E5, + EZSP_isHubConnected = 0x00E6, + EZSP_setParentClassificationEnabled = 0x00E7, + EZSP_generateCbkeKeys283k1 = 0x00E8, + EZSP_generateCbkeKeysHandler283k1 = 0x00E9, + EZSP_calculateSmacs283k1 = 0x00EA, + EZSP_calculateSmacsHandler283k1 = 0x00EB, + EZSP_getCertificate283k1 = 0x00EC, + EZSP_savePreinstalledCbkeData283k1 = 0x00ED, + EZSP_clearTemporaryDataMaybeStoreLinkKey283k1 = 0x00EE, + EZSP_setBeaconClassificationParams = 0x00EF, + EZSP_getParentClassificationEnabled = 0x00F0, + EZSP_readCounters = 0x00F1, + EZSP_counterRolloverHandler = 0x00F2, + EZSP_getBeaconClassificationParams = 0x00F3, + EZSP_setMacPollFailureWaitTime = 0x00F4, + EZSP_sendLinkPowerDeltaRequest = 0x00F7, + EZSP_multiPhyStart = 0x00F8, + EZSP_multiPhyStop = 0x00F9, + EZSP_multiPhySetRadioPower = 0x00FA, + EZSP_multiPhySetRadioChannel = 0x00FB, + EZSP_getPhyInterfaceCount = 0x00FC, + EZSP_getRadioParameters = 0x00FD, + EZSP_writeNodeData = 0x00FE, + + EZSP_rstAck = 0xFFFE, +}; + +#endif + + +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 +}; + + +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, +# 962 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +}; + + enum Z_AddrMode : uint8_t { + Z_Addr_NotPresent = 0, + Z_Addr_Group = 1, + Z_Addr_ShortAddress = 2, + Z_Addr_IEEEAddress = 3, + Z_Addr_Broadcast = 0xFF +}; + + +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 +}; + +#define Z_(s) Zo_ ## s + + +String getZDPStatusMessage(uint8_t status) { + static const char StatusMsg[] PROGMEM = "SUCCESS|INV_REQUESTTYPE|DEVICE_NOT_FOUND|INVALID_EP|NOT_ACTIVE|NOT_SUPPORTED" + "|TIMEOUT|NO_MATCH|NO_ENTRY|NO_DESCRIPTOR|INSUFFICIENT_SPACE|NOT_PERMITTED" + "|TABLE_FULL|NOT_AUTHORIZED|DEVICE_BINDING_TABLE_FULL" + ; + static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x80, 0x81, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x88, 0x89, 0x8A, 0x8B, + 0x8C, 0x8D, 0x8E }; + + char msg[32]; + int32_t idx = -1; + for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { + if (status == pgm_read_byte(&StatusIdx[i])) { + idx = i; + break; + } + } + if (idx >= 0) { + GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); + } else { + *msg = 0x00; + } + return String(msg); +} + +String getEmberStatus(uint8_t status) { + static const char StatusMsg[] PROGMEM = "SUCCESS|ERR_FATAL|BAD_ARGUMENT|EEPROM_MFG_STACK_VERSION_MISMATCH|INCOMPATIBLE_STATIC_MEMORY_DEFINITIONS|EEPROM_MFG_VERSION_MISMATCH|EEPROM_STACK_VERSION_MISMATCH" + "|NO_BUFFERS|SERIAL_INVALID_BAUD_RATE|SERIAL_INVALID_PORT|SERIAL_TX_OVERFLOW|SERIAL_RX_OVERFLOW|SERIAL_RX_FRAME_ERROR|SERIAL_RX_PARITY_ERROR|SERIAL_RX_EMPTY|SERIAL_RX_OVERRUN_ERROR" + "|MAC_TRANSMIT_QUEUE_FULL|MAC_UNKNOWN_HEADER_TYPE|MAC_SCANNING|MAC_NO_DATA|MAC_JOINED_NETWORK|MAC_BAD_SCAN_DURATION|MAC_INCORRECT_SCAN_TYPE|MAC_INVALID_CHANNEL_MASK|MAC_COMMAND_TRANSMIT_FAILURE" + "|MAC_NO_ACK_RECEIVED|MAC_INDIRECT_TIMEOUT|SIM_EEPROM_ERASE_PAGE_GREEN|SIM_EEPROM_ERASE_PAGE_RED|SIM_EEPROM_FULL|ERR_FLASH_WRITE_INHIBITED|ERR_FLASH_VERIFY_FAILED|SIM_EEPROM_INIT_1_FAILED|SIM_EEPROM_INIT_2_FAILED|SIM_EEPROM_INIT_3_FAILED|ERR_FLASH_PROG_FAIL|ERR_FLASH_ERASE_FAIL" + "|ERR_BOOTLOADER_TRAP_TABLE_BAD|ERR_BOOTLOADER_TRAP_UNKNOWN|ERR_BOOTLOADER_NO_IMAGE|DELIVERY_FAILED|BINDING_INDEX_OUT_OF_RANGE|ADDRESS_TABLE_INDEX_OUT_OF_RANGE|INVALID_BINDING_INDEX" + "|INVALID_CALL|COST_NOT_KNOWN|MAX_MESSAGE_LIMIT_REACHED|MESSAGE_TOO_LONG|BINDING_IS_ACTIVE|ADDRESS_TABLE_ENTRY_IS_ACTIVE" + "|ADC_CONVERSION_DONE|ADC_CONVERSION_BUSY|ADC_CONVERSION_DEFERRED|ADC_NO_CONVERSION_PENDING|SLEEP_INTERRUPTED|PHY_TX_UNDERFLOW|PHY_TX_INCOMPLETE|PHY_INVALID_CHANNEL|PHY_INVALID_POWER|PHY_TX_BUSY|PHY_TX_CCA_FAIL|PHY_OSCILLATOR_CHECK_FAILED|PHY_ACK_RECEIVED" + "|NETWORK_UP|NETWORK_DOWN|JOIN_FAILED|MOVE_FAILED|CANNOT_JOIN_AS_ROUTER|NODE_ID_CHANGED|PAN_ID_CHANGED|NO_BEACONS|RECEIVED_KEY_IN_THE_CLEAR|NO_NETWORK_KEY_RECEIVED|NO_LINK_KEY_RECEIVED|PRECONFIGURED_KEY_REQUIRED" + "|NOT_JOINED|INVALID_SECURITY_LEVEL|NETWORK_BUSY|INVALID_ENDPOINT|BINDING_HAS_CHANGED|INSUFFICIENT_RANDOM_DATA|APS_ENCRYPTION_ERROR|SECURITY_STATE_NOT_SET" + "|KEY_TABLE_INVALID_ADDRESS|SECURITY_CONFIGURATION_INVALID|TOO_SOON_FOR_SWITCH_KEY|KEY_NOT_AUTHORIZED|SECURITY_DATA_INVALID|SOURCE_ROUTE_FAILURE|MANY_TO_ONE_ROUTE_FAILURE" + "|STACK_AND_HARDWARE_MISMATCH|INDEX_OUT_OF_RANGE|TABLE_FULL|TABLE_ENTRY_ERASED|LIBRARY_NOT_PRESENT|OPERATION_IN_PROGRESS" + ; + static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, + 0x18, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x39, 0x3A, 0x3D, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x40, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, + 0x58, 0x59, 0x5A, 0x66, 0x69, 0x6A, 0x6C, + 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, + 0x80, 0x81, 0x82, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x94, 0x96, 0x98, 0x99, 0x9A, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0x93, 0x95, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA8, + 0xB3, 0xB7, 0xB8, 0xBB, 0xBD, 0xA9, 0xAA, + 0xB0, 0xB1, 0xB4, 0xB6, 0xB5, 0xBA }; + + char msg[32]; + int32_t idx = -1; + for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { + if (status == pgm_read_byte(&StatusIdx[i])) { + idx = i; + break; + } + } + if (idx >= 0) { + GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); + } else { + *msg = 0x00; + } + return String(msg); +} + + + +String getZigbeeStatusMessage(uint8_t status) { + static const char StatusMsg[] PROGMEM = "SUCCESS|FAILURE|NOT_AUTHORIZED|RESERVED_FIELD_NOT_ZERO|MALFORMED_COMMAND|UNSUP_CLUSTER_COMMAND|UNSUP_GENERAL_COMMAND" + "|UNSUP_MANUF_CLUSTER_COMMAND|UNSUP_MANUF_GENERAL_COMMAND|INVALID_FIELD|UNSUPPORTED_ATTRIBUTE|INVALID_VALE|READ_ONLY" + "|INSUFFICIENT_SPACE|DUPLICATE_EXISTS|NOT_FOUND|UNREPORTABLE_ATTRIBUTE|INVALID_DATA_TYPE|INVALID_SELECTOR|WRITE_ONLY" + "|INCONSISTENT_STARTUP_STATE|DEFINED_OUT_OF_BAND|INCONSISTENT|ACTION_DENIED|TIMEOUT|ABORT|INVALID_IMAGE|WAIT_FOR_DATA" + "|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER|NO_ROUTE" + "|CHANNEL_ACCESS_FAILURE|NO_ACK|NO_APP_ACK|NO_ROUTE" + ; + static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x7E, 0x7F, 0x80, 0x81, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, 0xCD, + 0xE1, 0xE9, 0xA7, 0xD0}; + + char msg[32]; + int32_t idx = -1; + for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { + if (status == pgm_read_byte(&StatusIdx[i])) { + idx = i; + break; + } + } + if (idx >= 0) { + GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); + } else { + *msg = 0x00; + } + return String(msg); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +#ifdef USE_ZIGBEE + + + + + + +class ZigbeeZCLSendMessage { +public: + uint16_t shortaddr; + uint16_t groupaddr; + uint16_t cluster; + uint8_t endpoint; + uint8_t cmd; + uint16_t manuf; + bool clusterSpecific; + bool needResponse; + bool direct; + uint8_t transacId; + const uint8_t *msg; + size_t len; +}; + +typedef int32_t (*ZB_Func)(uint8_t value); +typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); + + +const uint8_t ZIGBEE_LABEL_RESTART = 1; +const uint8_t ZIGBEE_LABEL_INIT_COORD = 10; +const uint8_t ZIGBEE_LABEL_START_COORD = 11; +const uint8_t ZIGBEE_LABEL_INIT_ROUTER = 12; +const uint8_t ZIGBEE_LABEL_START_ROUTER = 13; +const uint8_t ZIGBEE_LABEL_INIT_DEVICE = 14; +const uint8_t ZIGBEE_LABEL_START_DEVICE = 15; +const uint8_t ZIGBEE_LABEL_START_ROUTER_DEVICE = 16; +const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; +const uint8_t ZIGBEE_LABEL_READY = 20; +const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; +const uint8_t ZIGBEE_LABEL_NETWORK_CONFIGURED = 22; +const uint8_t ZIGBEE_LABEL_BAD_CONFIG = 23; +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_FACT_RESET_COORD = 50; +const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER = 51; +const uint8_t ZIGBEE_LABEL_FACT_RESET_DEVICE = 52; +const uint8_t ZIGBEE_LABEL_CONFIGURE_EZSP = 53; + +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; + bool init_phase = true; + bool recv_until = false; + + uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; + uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; + uint8_t *recv_filter = nullptr; + uint8_t recv_filter_len = 0; + int16_t pc = 0; + uint32_t next_timeout = 0; + + ZB_RecvMsgFunc recv_func = nullptr; + ZB_RecvMsgFunc recv_unexpected = nullptr; + + uint32_t permit_end_time = 0; +}; +struct ZigbeeStatus zigbee; +SBuffer *zigbee_buffer = nullptr; + +void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl); +bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok = false); + + +uint32_t parseHex(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(**data); + if (v < 0) { break; } + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" +#ifdef USE_ZIGBEE + + + + + + + +int strcmp_PP(const char *p1, const char *p2) { + if (p1 == p2) { return 0; } + if (!p1) { return -1; } + if (!p2) { return 1; } + const unsigned char *s1 = (const unsigned char *) p1; + const unsigned char *s2 = (const unsigned char *) p2; + unsigned char c1, c2; + do { + c1 = (unsigned char) pgm_read_byte(s1); + s1++; + c2 = (unsigned char) pgm_read_byte(s2); + s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + return c1 - c2; +} + + + + + + + +typedef struct Z_LastMessageVars { + uint16_t device; + uint16_t groupaddr; + uint16_t cluster; + uint8_t endpoint; +} Z_LastMessageVars; + +Z_LastMessageVars gZbLastMessage; + +uint16_t Z_GetLastDevice(void) { return gZbLastMessage.device; } +uint16_t Z_GetLastGroup(void) { return gZbLastMessage.groupaddr; } +uint16_t Z_GetLastCluster(void) { return gZbLastMessage.cluster; } +uint8_t Z_GetLastEndpoint(void) { return gZbLastMessage.endpoint; } +# 74 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" +class Z_json_array { +public: + + Z_json_array(): val("[]") {} + void add(uint32_t uval32) { + + val.remove(val.length()-1); + if (val.length() > 1) { + val += ','; + } + val += uval32; + val += ']'; + } + void addStrRaw(const char * sval) { + + val.remove(val.length()-1); + if (val.length() > 1) { + val += ','; + } + val += sval; + val += ']'; + } + void addStr(const char * sval) { + addStrRaw(EscapeJSONString(sval).c_str()); + } + String &toString(void) { + return val; + } + +private : + String val; +}; + + + + + + + +enum class Za_type : uint8_t { + Za_none, + + Za_bool, + Za_uint, + Za_int, + Za_float, + + Za_raw, + Za_str, + + Za_obj, + Za_arr, +}; + +class Z_attribute { +public: + + + union { + struct { + uint16_t cluster; + uint16_t attr_id; + } id; + char * key; + } key; + + union { + uint32_t uval32; + int32_t ival32; + float fval; + SBuffer* bval; + char* sval; + class Z_attribute_list * objval; + class Z_json_array * arrval; + } val; + Za_type type; + bool key_is_str; + bool key_is_pmem; + bool val_str_raw; + uint8_t key_suffix; + uint8_t attr_type; + uint8_t attr_multiplier; + + + Z_attribute(): + key{ .id = { 0x0000, 0x0000 } }, + val{ .uval32 = 0x0000 }, + type(Za_type::Za_none), + key_is_str(false), + key_is_pmem(false), + val_str_raw(false), + key_suffix(1), + attr_type(0xFF), + attr_multiplier(1) + {}; + + Z_attribute(const Z_attribute & rhs) { + deepCopy(rhs); + } + + Z_attribute & operator = (const Z_attribute & rhs) { + freeKey(); + freeVal(); + deepCopy(rhs); + } + + + ~Z_attribute() { + freeKey(); + freeVal(); + } + + + void freeVal(void); + + + void freeKey(void); + + + void setKeyName(const char * _key, bool pmem = false); + + void setKeyName(const char * _key, const char * _key2); + + void setKeyId(uint16_t cluster, uint16_t attr_id); + + + void setNone(void); + void setUInt(uint32_t _val); + void setBool(bool _val); + void setInt(int32_t _val); + void setFloat(float _val); + + void setBuf(const SBuffer &buf, size_t index, size_t len); + + + + + + + void setStr(const char * _val); + inline void setStrRaw(const char * _val) { + setStr(_val); + val_str_raw = true; + } + + Z_attribute_list & newAttrList(void); + Z_json_array & newJsonArray(void); + + inline bool isNum(void) const { return (type >= Za_type::Za_bool) && (type <= Za_type::Za_float); } + inline bool isNone(void) const { return (type == Za_type::Za_none);} + + float getFloat(void) const; + int32_t getInt(void) const; + uint32_t getUInt(void) const; + bool getBool(void) const; + const SBuffer * getRaw(void) const; + + + + const char * getStr(void) const; + + bool equalsKey(const Z_attribute & attr2, bool ignore_key_suffix = false) const; + bool equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; + bool equalsKey(const char * name, uint8_t suffix = 0) const; + bool equalsVal(const Z_attribute & attr2) const; + bool equals(const Z_attribute & attr2) const; + + String toString(bool prefix_comma = false) const; + + + void copyVal(const Z_attribute & rhs); + +protected: + void deepCopy(const Z_attribute & rhs); +}; +# 261 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" +class Z_attribute_list : public LList { +public: + uint8_t src_ep; + uint8_t lqi; + uint16_t group_id; + + Z_attribute_list(): + LList(), + src_ep(0xFF), + lqi(0xFF), + group_id(0xFFFF) + {}; + + + + + + void reset(void) { + LList::reset(); + src_ep = 0xFF; + lqi = 0xFF; + group_id = 0xFFFF; + } + + inline bool isValidSrcEp(void) const { return 0xFF != src_ep; } + inline bool isValidLQI(void) const { return 0xFF != lqi; } + inline bool isValidGroupId(void) const { return 0xFFFF != group_id; } + + + + Z_attribute & addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); + + + Z_attribute & addAttribute(const char * name, bool pmem = false, uint8_t suffix = 0); + Z_attribute & addAttribute(const char * name, const char * name2, uint8_t suffix = 0); + inline Z_attribute & addAttribute(const __FlashStringHelper * name, uint8_t suffix = 0) { + return addAttribute((const char*) name, true, suffix); + } + + + inline void removeAttribute(const Z_attribute * attr) { remove(attr); } + + + + + String toString(bool enclose_brackets = false) const; + + + const Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; + const Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) const; + const Z_attribute * findAttribute(const Z_attribute &attr) const; + + inline Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) { + return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(cluster, attr_id, suffix); + } + inline Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) { + return (Z_attribute*) (((const Z_attribute_list*)this)->findAttribute(name, suffix)); + } + inline Z_attribute * findAttribute(const Z_attribute &attr) { + return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(attr); + } + + + size_t countAttribute(uint16_t cluster, uint16_t attr_id) const ; + size_t countAttribute(const char * name) const ; + + + Z_attribute & findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); + Z_attribute & findOrCreateAttribute(const char * name, uint8_t suffix = 0); + + Z_attribute & findOrCreateAttribute(const Z_attribute &attr); + + Z_attribute & replaceOrCreate(const Z_attribute &attr); + + + bool mergeList(const Z_attribute_list &list2); +}; +# 346 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" +void Z_attribute::freeKey(void) { + if (key_is_str && key.key && !key_is_pmem) { delete[] key.key; } + key.key = nullptr; +} + + +void Z_attribute::setKeyName(const char * _key, bool pmem) { + freeKey(); + key_is_str = true; + key_is_pmem = pmem; + if (pmem) { + key.key = (char*) _key; + } else { + setKeyName(_key, nullptr); + } +} + +void Z_attribute::setKeyName(const char * _key, const char * _key2) { + freeKey(); + key_is_str = true; + key_is_pmem = false; + if (_key) { + size_t key_len = strlen_P(_key); + if (_key2) { + key_len += strlen_P(_key2); + } + key.key = new char[key_len+1]; + strcpy_P(key.key, _key); + if (_key2) { + strcat_P(key.key, _key2); + } + } +} + +void Z_attribute::setKeyId(uint16_t cluster, uint16_t attr_id) { + freeKey(); + key_is_str = false; + key.id.cluster = cluster; + key.id.attr_id = attr_id; +} + + +void Z_attribute::setNone(void) { + freeVal(); + val.uval32 = 0; + type = Za_type::Za_none; +} +void Z_attribute::setUInt(uint32_t _val) { + freeVal(); + val.uval32 = _val; + type = Za_type::Za_uint; +} +void Z_attribute::setBool(bool _val) { + freeVal(); + val.uval32 = _val; + type = Za_type::Za_bool; +} +void Z_attribute::setInt(int32_t _val) { + freeVal(); + val.ival32 = _val; + type = Za_type::Za_int; +} +void Z_attribute::setFloat(float _val) { + freeVal(); + val.fval = _val; + type = Za_type::Za_float; +} + +void Z_attribute::setBuf(const SBuffer &buf, size_t index, size_t len) { + freeVal(); + if (len) { + val.bval = new SBuffer(len); + val.bval->addBuffer(buf.buf(index), len); + } + type = Za_type::Za_raw; +} + + + + + + +void Z_attribute::setStr(const char * _val) { + freeVal(); + val_str_raw = false; + + if (_val) { + size_t len = strlen_P(_val); + if (len) { + val.sval = new char[len+1]; + strcpy_P(val.sval, _val); + } + } + type = Za_type::Za_str; +} + +Z_attribute_list & Z_attribute::newAttrList(void) { + freeVal(); + val.objval = new Z_attribute_list(); + type = Za_type::Za_obj; + return *val.objval; +} + +Z_json_array & Z_attribute::newJsonArray(void) { + freeVal(); + val.arrval = new Z_json_array(); + type = Za_type::Za_arr; + return *val.arrval; +} + + +float Z_attribute::getFloat(void) const { + switch (type) { + case Za_type::Za_bool: + case Za_type::Za_uint: return (float) val.uval32; + case Za_type::Za_int: return (float) val.ival32; + case Za_type::Za_float: return val.fval; + default: return 0.0f; + } +} + +int32_t Z_attribute::getInt(void) const { + switch (type) { + case Za_type::Za_bool: + case Za_type::Za_uint: return (int32_t) val.uval32; + case Za_type::Za_int: return val.ival32; + case Za_type::Za_float: return (int32_t) val.fval; + default: return 0; + } +} + +uint32_t Z_attribute::getUInt(void) const { + switch (type) { + case Za_type::Za_bool: + case Za_type::Za_uint: return val.uval32; + case Za_type::Za_int: return (uint32_t) val.ival32; + case Za_type::Za_float: return (uint32_t) val.fval; + default: return 0; + } +} + +bool Z_attribute::getBool(void) const { + switch (type) { + case Za_type::Za_bool: + case Za_type::Za_uint: return val.uval32 ? true : false; + case Za_type::Za_int: return val.ival32 ? true : false; + case Za_type::Za_float: return val.fval ? true : false; + default: return false; + } +} + +const SBuffer * Z_attribute::getRaw(void) const { + if (Za_type::Za_raw == type) { return val.bval; } + return nullptr; +} + + + +const char * Z_attribute::getStr(void) const { + if (Za_type::Za_str == type) { return val.sval; } + return ""; +} + +bool Z_attribute::equalsKey(const Z_attribute & attr2, bool ignore_key_suffix) const { + + if (key_is_str != attr2.key_is_str) { return false; } + if (key_is_str) { + if (strcmp_PP(key.key, attr2.key.key)) { return false; } + } else { + if ((key.id.cluster != attr2.key.id.cluster) || + (key.id.attr_id != attr2.key.id.attr_id)) { return false; } + } + if (!ignore_key_suffix) { + if (key_suffix != attr2.key_suffix) { return false; } + } + return true; +} + +bool Z_attribute::equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { + if (!key_is_str) { + if ((key.id.cluster == cluster) && (key.id.attr_id == attr_id)) { + if (suffix) { + if (key_suffix == suffix) { return true; } + } else { + return true; + } + } + } + return false; +} + +bool Z_attribute::equalsKey(const char * name, uint8_t suffix) const { + if (key_is_str) { + if (0 == strcmp_PP(key.key, name)) { + if (suffix) { + if (key_suffix == suffix) { return true; } + } else { + return true; + } + } + } + return false; +} + +bool Z_attribute::equalsVal(const Z_attribute & attr2) const { + if (type != attr2.type) { return false; } + if ((type >= Za_type::Za_bool) && (type <= Za_type::Za_float)) { + + if (val.uval32 != attr2.val.uval32) { return false; } + } else if (type == Za_type::Za_raw) { + + return equalsSBuffer(val.bval, attr2.val.bval); + } else if (type == Za_type::Za_str) { + + if (strcmp_PP(val.sval, attr2.val.sval)) { return false; } + } else if (type == Za_type::Za_obj) { + return false; + } else if (type == Za_type::Za_arr) { + return false; + } + return true; +} + +bool Z_attribute::equals(const Z_attribute & attr2) const { + return equalsKey(attr2) && equalsVal(attr2); +} + +String Z_attribute::toString(bool prefix_comma) const { + String res(""); + if (prefix_comma) { res += ','; } + res += '"'; + + if (key_is_str) { + if (key.key) { res += EscapeJSONString(key.key); } + else { res += F("null"); } + if (key_suffix > 1) { + res += key_suffix; + } + } else { + char attr_name[12]; + snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X/%04X"), key.id.cluster, key.id.attr_id); + res += attr_name; + if (key_suffix > 1) { + res += '+'; + res += key_suffix; + } + } + res += F("\":"); + + switch (type) { + case Za_type::Za_none: + res += "null"; + break; + case Za_type::Za_bool: + res += val.uval32 ? F("true") : F("false"); + break; + case Za_type::Za_uint: + res += val.uval32; + break; + case Za_type::Za_int: + res += val.ival32; + break; + case Za_type::Za_float: + { + String fstr(val.fval, 2); + size_t last = fstr.length() - 1; + + while (fstr[last] == '0') { + fstr.remove(last--); + } + + if (fstr[last] == '.') { + fstr.remove(last); + } + res += fstr; + } + break; + case Za_type::Za_raw: + res += '"'; + if (val.bval) { + size_t blen = val.bval->len(); + + char hex[2*blen+1]; + ToHex_P(val.bval->getBuffer(), blen, hex, sizeof(hex)); + res += hex; + } + res += '"'; + break; + case Za_type::Za_str: + if (val_str_raw) { + if (val.sval) { res += val.sval; } + } else { + res += '"'; + if (val.sval) { + res += EscapeJSONString(val.sval); + } + res += '"'; + } + break; + case Za_type::Za_obj: + res += '{'; + if (val.objval) { + res += val.objval->toString(); + } + res += '}'; + break; + case Za_type::Za_arr: + if (val.arrval) { + res += val.arrval->toString(); + } else { + res += "[]"; + } + break; + } + + return res; +} + + +void Z_attribute::copyVal(const Z_attribute & rhs) { + freeVal(); + + val.uval32 = 0x00000000; + type = rhs.type; + if (rhs.isNum()) { + val.uval32 = rhs.val.uval32; + } else if (rhs.type == Za_type::Za_raw) { + if (rhs.val.bval) { + val.bval = new SBuffer(rhs.val.bval->len()); + val.bval->addBuffer(*(rhs.val.bval)); + } + } else if (rhs.type == Za_type::Za_str) { + if (rhs.val.sval) { + size_t s_len = strlen_P(rhs.val.sval); + val.sval = new char[s_len+1]; + strcpy_P(val.sval, rhs.val.sval); + } + } + val_str_raw = rhs.val_str_raw; +} + + +void Z_attribute::freeVal(void) { + switch (type) { + case Za_type::Za_raw: + if (val.bval) { delete val.bval; val.bval = nullptr; } + break; + case Za_type::Za_str: + if (val.sval) { delete[] val.sval; val.sval = nullptr; } + break; + case Za_type::Za_obj: + if (val.objval) { delete val.objval; val.objval = nullptr; } + break; + case Za_type::Za_arr: + if (val.arrval) { delete val.arrval; val.arrval = nullptr; } + break; + } +} + +void Z_attribute::deepCopy(const Z_attribute & rhs) { + + if (!rhs.key_is_str) { + key.id.cluster = rhs.key.id.cluster; + key.id.attr_id = rhs.key.id.attr_id; + } else { + if (rhs.key_is_pmem) { + key.key = rhs.key.key; + } else { + key.key = nullptr; + if (rhs.key.key) { + size_t key_len = strlen_P(rhs.key.key); + if (key_len) { + key.key = new char[key_len+1]; + strcpy_P(key.key, rhs.key.key); + } + } + } + } + key_is_str = rhs.key_is_str; + key_is_pmem = rhs.key_is_pmem; + key_suffix = rhs.key_suffix; + attr_type = rhs.attr_type; + attr_multiplier = rhs.attr_multiplier; + + copyVal(rhs); + +} + + + + + + + +Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { + Z_attribute & attr = addToLast(); + attr.key.id.cluster = cluster; + attr.key.id.attr_id = attr_id; + attr.key_is_str = false; + if (!suffix) { attr.key_suffix = countAttribute(attr.key.id.cluster, attr.key.id.attr_id); } + else { attr.key_suffix = suffix; } + return attr; +} + + +Z_attribute & Z_attribute_list::addAttribute(const char * name, bool pmem, uint8_t suffix) { + Z_attribute & attr = addToLast(); + attr.setKeyName(name, pmem); + if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } + else { attr.key_suffix = suffix; } + return attr; +} + +Z_attribute & Z_attribute_list::addAttribute(const char * name, const char * name2, uint8_t suffix) { + Z_attribute & attr = addToLast(); + attr.setKeyName(name, name2); + if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } + else { attr.key_suffix = suffix; } + return attr; +} + +String Z_attribute_list::toString(bool enclose_brackets) const { + String res = ""; + if (enclose_brackets) { res += '{'; } + bool prefix_comma = false; + for (const auto & attr : *this) { + res += attr.toString(prefix_comma); + prefix_comma = true; + } + + if (0xFF != src_ep) { + if (prefix_comma) { res += ','; } + prefix_comma = true; + res += F("\"" D_CMND_ZIGBEE_ENDPOINT "\":"); + res += src_ep; + } + + if (0xFFFF != group_id) { + if (prefix_comma) { res += ','; } + prefix_comma = true; + res += F("\"" D_CMND_ZIGBEE_GROUP "\":"); + res += group_id; + } + + if (0xFF != lqi) { + if (prefix_comma) { res += ','; } + prefix_comma = true; + res += F("\"" D_CMND_ZIGBEE_LINKQUALITY "\":"); + res += lqi; + } + if (enclose_brackets) { res += '}'; } + + return res; +} + + +const Z_attribute * Z_attribute_list::findAttribute(const Z_attribute &attr) const { + uint8_t suffix = attr.key_suffix; + if (attr.key_is_str) { + return findAttribute(attr.key.key, suffix); + } else { + return findAttribute(attr.key.id.cluster, attr.key.id.attr_id, suffix); + } +} + +const Z_attribute * Z_attribute_list::findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { + for (const auto & attr : *this) { + if (attr.equalsKey(cluster, attr_id, suffix)) { return &attr; } + } + return nullptr; +} +size_t Z_attribute_list::countAttribute(uint16_t cluster, uint16_t attr_id) const { + size_t count = 0; + for (const auto & attr : *this) { + if (attr.equalsKey(cluster, attr_id, 0)) { count++; } + } + return count; +} + + +Z_attribute & Z_attribute_list::findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { + Z_attribute * found = findAttribute(cluster, attr_id, suffix); + return found ? *found : addAttribute(cluster, attr_id, suffix); +} + +const Z_attribute * Z_attribute_list::findAttribute(const char * name, uint8_t suffix) const { + for (const auto & attr : *this) { + if (attr.equalsKey(name, suffix)) { return &attr; } + } + return nullptr; +} +size_t Z_attribute_list::countAttribute(const char * name) const { + size_t count = 0; + for (const auto & attr : *this) { + if (attr.equalsKey(name, 0)) { count++; } + } + return count; +} + +Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t suffix) { + Z_attribute * found = findAttribute(name, suffix); + return found ? *found : addAttribute(name, suffix); +} + + +Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) { + if (attr.key_is_str) { + return findOrCreateAttribute(attr.key.key, attr.key_suffix); + } else { + return findOrCreateAttribute(attr.key.id.cluster, attr.key.id.attr_id, attr.key_suffix); + } +} + +Z_attribute & Z_attribute_list::replaceOrCreate(const Z_attribute &attr) { + Z_attribute &new_attr = findOrCreateAttribute(attr); + new_attr.copyVal(attr); + return new_attr; +} + + +bool Z_attribute_list::mergeList(const Z_attribute_list &attr_list) { + + if (0xFF == src_ep) { + src_ep = attr_list.src_ep; + } else if (0xFF != attr_list.src_ep) { + if (src_ep != attr_list.src_ep) { return false; } + } + if (0xFF != attr_list.lqi) { + lqi = attr_list.lqi; + } + for (auto & attr : attr_list) { + replaceOrCreate(attr); + } + return true; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" +#ifdef USE_ZIGBEE + +#ifndef ZIGBEE_SAVE_DELAY_SECONDS +#define ZIGBEE_SAVE_DELAY_SECONDS 2 +#endif +const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; + +enum class Z_Data_Type : uint8_t { + Z_Unknown = 0x00, + Z_Light = 1, + Z_Plug = 2, + Z_PIR = 3, + Z_Alarm = 4, + Z_Thermo = 5, + Z_OnOff = 6, + Z_Ext = 0xF, + Z_Device = 0xFF +}; + +class Z_Data_Set; + + + +class Z_Data { +public: + Z_Data(Z_Data_Type type = Z_Data_Type::Z_Unknown, uint8_t endpoint = 0) : _type(type), _endpoint(endpoint), _config(-1), _power(0) {} + inline Z_Data_Type getType(void) const { return _type; } + inline int8_t getConfig(void) const { return _config; } + inline void setConfig(int8_t config) { _config = config; } + + inline uint8_t getEndpoint(void) const { return _endpoint; } + + void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; + + static const Z_Data_Type type = Z_Data_Type::Z_Unknown; + + friend class Z_Data_Set; +protected: + Z_Data_Type _type; + uint8_t _endpoint; + int8_t _config; + uint8_t _power; +}; + + + + + + + +class Z_Data_OnOff : public Z_Data { +public: + Z_Data_OnOff(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_OnOff, endpoint) + { + _config = 1; + } + + inline bool validPower(uint32_t relay = 0) const { return (_config > relay); } + inline bool getPower(uint32_t relay = 0) const { return bitRead(_power, relay); } + void setPower(bool val, uint32_t relay = 0); + + void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; + + static const Z_Data_Type type = Z_Data_Type::Z_OnOff; +}; + + +void Z_Data_OnOff::setPower(bool val, uint32_t relay) { + if (relay < 8) { + if (_config < relay) { _config = relay; } + bitWrite(_power, relay, val); + } +} + + + + +class Z_Data_Plug : public Z_Data { +public: + Z_Data_Plug(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_Plug, endpoint), + mains_voltage(0xFFFF), + mains_power(-0x8000) + {} + + inline bool validMainsVoltage(void) const { return 0xFFFF != mains_voltage; } + inline bool validMainsPower(void) const { return -0x8000 != mains_power; } + + inline uint16_t getMainsVoltage(void) const { return mains_voltage; } + inline int16_t getMainsPower(void) const { return mains_power; } + + inline void setMainsVoltage(uint16_t _mains_voltage) { mains_voltage = _mains_voltage; } + inline void setMainsPower(int16_t _mains_power) { mains_power = _mains_power; } + + static const Z_Data_Type type = Z_Data_Type::Z_Plug; + + uint16_t mains_voltage; + int16_t mains_power; +}; + + + + +class Z_Data_Light : public Z_Data { +public: + Z_Data_Light(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_Light, endpoint), + colormode(0xFF), + dimmer(0xFF), + sat(0xFF), + hue(0xFF), + ct(0xFFFF), + x(0xFFFF), + y(0xFFFF) + {} + + inline bool validColormode(void) const { return 0xFF != colormode; } + inline bool validDimmer(void) const { return 0xFF != dimmer; } + inline bool validSat(void) const { return 0xFF != sat; } + inline bool validHue(void) const { return 0xFFFF != hue; } + inline bool validCT(void) const { return 0xFFFF != ct; } + inline bool validX(void) const { return 0xFFFF != x; } + inline bool validY(void) const { return 0xFFFF != y; } + + inline uint8_t getColorMode(void) const { return colormode; } + inline uint8_t getDimmer(void) const { return dimmer; } + inline uint8_t getSat(void) const { return sat; } + inline uint16_t getHue(void) const { return changeUIntScale(hue, 0, 254, 0, 360); } + inline uint16_t getCT(void) const { return ct; } + inline uint16_t getX(void) const { return x; } + inline uint16_t getY(void) const { return y; } + + inline void setColorMode(uint8_t _colormode) { colormode = _colormode; } + inline void setDimmer(uint8_t _dimmer) { dimmer = _dimmer; } + inline void setSat(uint8_t _sat) { sat = _sat; } + inline void setHue(uint16_t _hue) { hue = changeUIntScale(_hue, 0, 360, 0, 254);; } + inline void setCT(uint16_t _ct) { ct = _ct; } + inline void setX(uint16_t _x) { x = _x; } + inline void setY(uint16_t _y) { y = _y; } + + void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; + + static const Z_Data_Type type = Z_Data_Type::Z_Light; + + uint8_t colormode; + uint8_t dimmer; + uint8_t sat; + uint8_t hue; + uint16_t ct; + uint16_t x, y; +}; + + + + +class Z_Data_Thermo : public Z_Data { +public: + Z_Data_Thermo(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_Thermo, endpoint), + temperature(-0x8000), + pressure(-0x8000), + humidity(0xFFFF), + th_setpoint(0xFF), + temperature_target(-0x8000) + {} + + inline bool validTemperature(void) const { return -0x8000 != temperature; } + inline bool validPressure(void) const { return -0x8000 != pressure; } + inline bool validHumidity(void) const { return 0xFFFF != humidity; } + inline bool validThSetpoint(void) const { return 0xFF != th_setpoint; } + inline bool validTempTarget(void) const { return -0x8000 != temperature_target; } + + inline int16_t getTemperature(void) const { return temperature; } + inline int16_t getPressure(void) const { return pressure; } + inline uint16_t getHumidity(void) const { return humidity; } + inline uint8_t getThSetpoint(void) const { return th_setpoint; } + inline int16_t getTempTarget(void) const { return temperature_target; } + + inline void setTemperature(int16_t _temperature) { temperature = _temperature; } + inline void setPressure(int16_t _pressure) { pressure = _pressure; } + inline void setHumidity(uint16_t _humidity) { humidity = _humidity; } + inline void setThSetpoint(uint8_t _th_setpoint) { th_setpoint = _th_setpoint; } + inline void setTempTarget(int16_t _temperature_target){ temperature_target = _temperature_target; } + + static const Z_Data_Type type = Z_Data_Type::Z_Thermo; + + + int16_t temperature; + int16_t pressure; + uint16_t humidity; + + uint8_t th_setpoint; + int16_t temperature_target; +}; + + + + +class Z_Data_Alarm : public Z_Data { +public: + Z_Data_Alarm(uint8_t endpoint = 0) : + Z_Data(Z_Data_Type::Z_Alarm, endpoint), + zone_type(0xFFFF) + {} + + static const Z_Data_Type type = Z_Data_Type::Z_Alarm; + + inline bool validZoneType(void) const { return 0xFFFF != zone_type; } + + inline uint16_t getZoneType(void) const { return zone_type; } + + inline void setZoneType(uint16_t _zone_type) { zone_type = _zone_type; } + + + uint16_t zone_type; +# 250 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" +}; + + + + + +class Z_Data_Set : public LList { +public: + + Z_Data & getByType(Z_Data_Type type, uint8_t ep = 0); + const Z_Data & find(Z_Data_Type type, uint8_t ep = 0) const; + + + + + + template + M & get(uint8_t ep = 0); + + template + const M & find(uint8_t ep = 0) const; + + + template + M & addIfNull(M & cur, uint8_t ep = 0); +}; + +Z_Data & Z_Data_Set::getByType(Z_Data_Type type, uint8_t ep) { + switch (type) { + case Z_Data_Type::Z_Light: + return get(ep); + case Z_Data_Type::Z_Plug: + return get(ep); + case Z_Data_Type::Z_Alarm: + return get(ep); + case Z_Data_Type::Z_Thermo: + return get(ep); + case Z_Data_Type::Z_OnOff: + return get(ep); + default: + return *(Z_Data*)nullptr; + } +} + +template +M & Z_Data_Set::get(uint8_t ep) { + M & m = (M&) find(M::type, ep); + return addIfNull(m, ep); +} + +template +const M & Z_Data_Set::find(uint8_t ep) const { + return (M&) find(M::type, ep); +} + + + +template +M & Z_Data_Set::addIfNull(M & cur, uint8_t ep) { + if (nullptr == &cur) { + LList_elt * elt = new LList_elt(); + elt->val()._endpoint = ep; + this->addToLast((LList_elt*)elt); + return elt->val(); + } else { + if (cur._endpoint == 0) { cur._endpoint = ep; } + return cur; + } +} + +const Z_Data & Z_Data_Set::find(Z_Data_Type type, uint8_t ep) const { + for (auto & elt : *this) { + if (elt._type == type) { + + + if ((ep == 0) || (elt._endpoint == 0) || (ep == elt._endpoint)) { + return elt; + } + } + } + return *(Z_Data*)nullptr; +} + + + + +void Z_Data_Light::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { + attr_list.addAttribute(PSTR(D_JSON_ZIGBEE_LIGHT)).setInt(getConfig()); + Z_Data::toAttributes(attr_list, type); +} + +void Z_Data_OnOff::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { + if (validPower()) { attr_list.addAttribute(PSTR("Power")).setUInt(getPower() ? 1 : 0); } +} + + + + + +const size_t endpoints_max = 8; + +class Z_Device { +public: + + uint64_t longaddr; + char * manufacturerId; + char * modelId; + char * friendlyName; + + + uint32_t defer_last_message_sent; + + uint8_t endpoints[endpoints_max]; + + Z_attribute_list attr_list; + + uint16_t shortaddr; + uint8_t seqNumber; + bool hidden; + bool reachable; + + + + Z_Data_Set data; + + uint8_t lqi; + uint8_t batterypercent; + + uint32_t last_seen; + + + Z_Device(uint16_t _shortaddr = BAD_SHORTADDR, uint64_t _longaddr = 0x00): + longaddr(_longaddr), + manufacturerId(nullptr), + modelId(nullptr), + friendlyName(nullptr), + defer_last_message_sent(0), + endpoints{ 0, 0, 0, 0, 0, 0, 0, 0 }, + attr_list(), + shortaddr(_shortaddr), + seqNumber(0), + hidden(false), + reachable(false), + + lqi(0xFF), + batterypercent(0xFF), + last_seen(0) + { }; + + inline bool valid(void) const { return BAD_SHORTADDR != shortaddr; } + + inline bool validLongaddr(void) const { return 0x0000 != longaddr; } + inline bool validManufacturerId(void) const { return nullptr != manufacturerId; } + inline bool validModelId(void) const { return nullptr != modelId; } + inline bool validFriendlyName(void) const { return nullptr != friendlyName; } + + inline bool validPower(uint8_t ep =0) const; + + inline bool validLqi(void) const { return 0xFF != lqi; } + inline bool validBatteryPercent(void) const { return 0xFF != batterypercent; } + inline bool validLastSeen(void) const { return 0x0 != last_seen; } + + inline void setReachable(bool _reachable) { reachable = _reachable; } + inline bool getReachable(void) const { return reachable; } + inline bool getPower(uint8_t ep =0) const; + + + void toAttributes(Z_attribute_list & attr_list) const; + + + void setPower(bool power_on, uint8_t ep = 0); + + + int8_t getLightChannels(void) const { + const Z_Data_Light & light = data.find(0); + if (&light != nullptr) { + return light.getConfig(); + } else { + return -1; + } + } + + + bool setLightChannels(int8_t channels) { + bool dirty = false; + if (channels >= 0) { + + Z_Data_Light & light = data.get(0); + if (channels != light.getConfig()) { + light.setConfig(channels); + dirty = true; + } + } else { + + for (auto & data_elt : data) { + if (data_elt.getType() == Z_Data_Type::Z_Light) { + + data.remove(&data_elt); + dirty = true; + } + } + } + return dirty; + } +}; + + + + + +typedef void (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); + + +typedef enum Z_Def_Category { + Z_CAT_ALWAYS = 0, + + Z_CLEAR_DEVICE = 0x01, + Z_CAT_READ_ATTR, + Z_CAT_VIRTUAL_OCCUPANCY, + Z_CAT_REACHABILITY, + Z_CAT_PERMIT_JOIN, + + Z_CLEAR_DEVICE_CLUSTER, + Z_CAT_READ_CLUSTER, + + Z_CLEAR_DEVICE_CLUSTER_ENDPOINT, + Z_CAT_EP_DESC, + Z_CAT_BIND, + Z_CAT_CONFIG_ATTR, + Z_CAT_READ_ATTRIBUTE, +} Z_Def_Category; + +const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 2000; + +typedef struct Z_Deferred { + + uint32_t timer; + uint16_t shortaddr; + uint16_t groupaddr; + uint16_t cluster; + uint8_t endpoint; + uint8_t category; + uint32_t value; + Z_DeviceTimer func; +} Z_Deferred; +# 505 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" +class Z_Devices { +public: + Z_Devices() : _deferred() {}; + + + + + + + uint16_t isKnownLongAddr(uint64_t longaddr) const; + uint16_t isKnownIndex(uint32_t index) const; + uint16_t isKnownFriendlyName(const char * name) const; + + Z_Device & findShortAddr(uint16_t shortaddr); + const Z_Device & findShortAddr(uint16_t shortaddr) const; + Z_Device & findLongAddr(uint64_t longaddr); + const Z_Device & findLongAddr(uint64_t longaddr) const; + Z_Device & getShortAddr(uint16_t shortaddr); + Z_Device & getLongAddr(uint64_t longaddr); + + inline bool foundDevice(const Z_Device & device) const { + return (&device != &device_unk); + } + + int32_t findFriendlyName(const char * name) const; + uint64_t getDeviceLongAddr(uint16_t shortaddr) const; + + uint8_t findFirstEndpoint(uint16_t shortaddr) const; + + + + void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); + + + void addEndpoint(uint16_t shortaddr, uint8_t endpoint); + void clearEndpoints(uint16_t shortaddr); + uint32_t countEndpoints(uint16_t shortaddr) const; + + void setManufId(uint16_t shortaddr, const char * str); + void setModelId(uint16_t shortaddr, const char * str); + void setFriendlyName(uint16_t shortaddr, const char * str); + inline const char * getFriendlyName(uint16_t shortaddr) const { + return findShortAddr(shortaddr).friendlyName; + } + inline const char * getModelId(uint16_t shortaddr) const { + return findShortAddr(shortaddr).modelId; + } + inline const char * getManufacturerId(uint16_t shortaddr) const{ + return findShortAddr(shortaddr).manufacturerId; + } + + void setReachable(uint16_t shortaddr, bool reachable); + void setLQI(uint16_t shortaddr, uint8_t lqi); + void setLastSeenNow(uint16_t shortaddr); + + void setBatteryPercent(uint16_t shortaddr, uint8_t bp); + uint8_t getBatteryPercent(uint16_t shortaddr) const; + + + uint8_t getNextSeqNumber(uint16_t shortaddr); + + + static void addLightState(Z_attribute_list & attr_list, const Z_Data_Light & light); + String dumpLightState(uint16_t shortaddr) const; + String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; + int32_t deviceRestore(JsonParserObject json); + + + void setLightProfile(uint16_t shortaddr, uint8_t light_profile); + uint8_t getLightProfile(uint16_t shortaddr) const ; + + + int8_t getHueBulbtype(uint16_t shortaddr) const ; + void hideHueBulb(uint16_t shortaddr, bool hidden); + bool isHueBulbHidden(uint16_t shortaddr) const ; + Z_Data_Light & getLight(uint16_t shortaddr); + + + void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster = 0xFFFF, uint8_t endpoint = 0xFF); + void setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); + void queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); + void runTimer(void); + + + void jsonAppend(uint16_t shortaddr, const Z_attribute_list &attr_list); + void jsonPublishFlush(uint16_t shortaddr); + bool jsonIsConflict(uint16_t shortaddr, const Z_attribute_list &attr_list) const; + void jsonPublishNow(uint16_t shortaddr, Z_attribute_list &attr_list); + + + size_t devicesSize(void) const { + return _devices.length(); + } + const Z_Device & devicesAt(size_t i) const { + const Z_Device * devp = _devices.at(i); + if (devp) { + return *devp; + } else { + return device_unk; + } + } + + + bool removeDevice(uint16_t shortaddr); + + + void dirty(void); + void clean(void); + void shrinkToFit(uint16_t shortaddr); + + + uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; + +private: + LList _devices; + LList _deferred; + uint32_t _saveTimer = 0; + uint8_t _seqNumber = 0; + + + + const Z_Device device_unk = Z_Device(BAD_SHORTADDR); + + + + Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); + void freeDeviceEntry(Z_Device *device); + + void setStringAttribute(char*& attr, const char * str); +}; + + + + +Z_Devices zigbee_devices = Z_Devices(); + + +uint64_t localIEEEAddr = 0; +uint16_t localShortAddr = 0; + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +#ifdef USE_ZIGBEE +# 30 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { + if ((BAD_SHORTADDR == shortaddr) && !longaddr) { return (Z_Device&) device_unk; } + Z_Device device(shortaddr, longaddr); + + dirty(); + return _devices.addHead(device); +} + +void Z_Devices::freeDeviceEntry(Z_Device *device) { + if (device->manufacturerId) { free(device->manufacturerId); } + if (device->modelId) { free(device->modelId); } + if (device->friendlyName) { free(device->friendlyName); } + free(device); +} +# 53 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) { + for (auto & elem : _devices) { + if (elem.shortaddr == shortaddr) { return elem; } + } + return (Z_Device&) device_unk; +} +const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const { + for (const auto & elem : _devices) { + if (elem.shortaddr == shortaddr) { return elem; } + } + return device_unk; +} +# 73 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) { + if (!longaddr) { return (Z_Device&) device_unk; } + for (auto &elem : _devices) { + if (elem.longaddr == longaddr) { return elem; } + } + return (Z_Device&) device_unk; +} +const Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) const { + if (!longaddr) { return device_unk; } + for (const auto &elem : _devices) { + if (elem.longaddr == longaddr) { return elem; } + } + return device_unk; +} +# 95 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +int32_t Z_Devices::findFriendlyName(const char * name) const { + if (!name) { return -1; } + size_t name_len = strlen(name); + int32_t found = 0; + if (name_len) { + for (auto &elem : _devices) { + if (elem.friendlyName) { + if (strcasecmp(elem.friendlyName, name) == 0) { return found; } + } + found++; + } + } + return -1; +} + +uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { + const Z_Device & device = findLongAddr(longaddr); + if (foundDevice(device)) { + return device.shortaddr; + } else { + return BAD_SHORTADDR; + } +} + +uint16_t Z_Devices::isKnownIndex(uint32_t index) const { + if (index < devicesSize()) { + const Z_Device & device = devicesAt(index); + return device.shortaddr; + } else { + return BAD_SHORTADDR; + } +} + +uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { + if ((!name) || (0 == strlen(name))) { return BAD_SHORTADDR; } + int32_t found = findFriendlyName(name); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; + } else { + return BAD_SHORTADDR; + } +} + +uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { + return findShortAddr(shortaddr).longaddr; +} + + + + +Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { + if (BAD_SHORTADDR == shortaddr) { return (Z_Device&) device_unk; } + Z_Device & device = findShortAddr(shortaddr); + if (foundDevice(device)) { + return device; + } + return createDeviceEntry(shortaddr, 0); +} + + +Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { + if (!longaddr) { return (Z_Device&) device_unk; } + Z_Device & device = findLongAddr(longaddr); + if (foundDevice(device)) { + return device; + } + return createDeviceEntry(0, longaddr); +} + + +bool Z_Devices::removeDevice(uint16_t shortaddr) { + Z_Device & device = findShortAddr(shortaddr); + if (foundDevice(device)) { + _devices.remove(&device); + dirty(); + return true; + } + return false; +} + + + + + + +void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { + Z_Device * s_found = &findShortAddr(shortaddr); + Z_Device * l_found = &findLongAddr(longaddr); + + if (foundDevice(*s_found) && foundDevice(*l_found)) { + if (s_found == l_found) { + } else { + + l_found->shortaddr = shortaddr; + + freeDeviceEntry(s_found); + _devices.remove(s_found); + dirty(); + } + } else if (foundDevice(*s_found)) { + + + s_found->longaddr = longaddr; + dirty(); + } else if (foundDevice(*l_found)) { + + l_found->shortaddr = shortaddr; + dirty(); + } else { + + if ((BAD_SHORTADDR != shortaddr) || longaddr) { + createDeviceEntry(shortaddr, longaddr); + } + } +} + + + + +void Z_Devices::clearEndpoints(uint16_t shortaddr) { + Z_Device &device = getShortAddr(shortaddr); + for (uint32_t i = 0; i < endpoints_max; i++) { + device.endpoints[i] = 0; + + } +} + + + + +void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) { + if (0x00 == endpoint) { return; } + Z_Device &device = getShortAddr(shortaddr); + + for (uint32_t i = 0; i < endpoints_max; i++) { + if (endpoint == device.endpoints[i]) { + return; + } + if (0 == device.endpoints[i]) { + device.endpoints[i] = endpoint; + dirty(); + return; + } + } +} + + + + +uint32_t Z_Devices::countEndpoints(uint16_t shortaddr) const { + uint32_t count_ep = 0; + const Z_Device & device =findShortAddr(shortaddr); + if (!foundDevice(device)) return 0; + + for (uint32_t i = 0; i < endpoints_max; i++) { + if (0 != device.endpoints[i]) { + count_ep++; + } + } + return count_ep; +} + + +uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const { + + if (0x0000 == shortaddr) { return 1; } + return findShortAddr(shortaddr).endpoints[0]; +} + +void Z_Devices::setStringAttribute(char*& attr, const char * str) { + if (nullptr == str) { return; } + size_t str_len = strlen(str); + + if ((nullptr == attr) && (0 == str_len)) { return; } + if (attr) { + + if (strcmp(attr, str) != 0) { + + free(attr); + attr = nullptr; + } else { + return; + } + } + if (str_len) { + attr = (char*) malloc(str_len + 1); + strlcpy(attr, str, str_len + 1); + } + dirty(); +} +# 296 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { + setStringAttribute(getShortAddr(shortaddr).manufacturerId, str); +} + +void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { + setStringAttribute(getShortAddr(shortaddr).modelId, str); +} + +void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { + setStringAttribute(getShortAddr(shortaddr).friendlyName, str); +} + + +void Z_Devices::setReachable(uint16_t shortaddr, bool reachable) { + getShortAddr(shortaddr).setReachable(reachable); +} + +void Z_Devices::setLQI(uint16_t shortaddr, uint8_t lqi) { + if (shortaddr == localShortAddr) { return; } + getShortAddr(shortaddr).lqi = lqi; +} + +void Z_Devices::setLastSeenNow(uint16_t shortaddr) { + if (shortaddr == localShortAddr) { return; } + + + + + if (Rtc.utc_time < 1577836800) { return; } + getShortAddr(shortaddr).last_seen = Rtc.utc_time; +} + + +void Z_Devices::setBatteryPercent(uint16_t shortaddr, uint8_t bp) { + getShortAddr(shortaddr).batterypercent = bp; +} + + +uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { + Z_Device & device = findShortAddr(shortaddr); + if (foundDevice(device)) { + device.seqNumber += 1; + return device.seqNumber; + } else { + _seqNumber += 1; + return _seqNumber; + } +} + + +void Z_Devices::setLightProfile(uint16_t shortaddr, uint8_t light_profile) { + Z_Device &device = getShortAddr(shortaddr); + if (device.setLightChannels(light_profile)) { + dirty(); + } +} + + +uint8_t Z_Devices::getLightProfile(uint16_t shortaddr) const { + const Z_Device &device = findShortAddr(shortaddr); + return device.getLightChannels(); +} + +int8_t Z_Devices::getHueBulbtype(uint16_t shortaddr) const { + int8_t light_profile = getLightProfile(shortaddr); + if (0x00 == (light_profile & 0xF0)) { + return (light_profile & 0x07); + } else { + + return -1; + } +} + +void Z_Devices::hideHueBulb(uint16_t shortaddr, bool hidden) { + Z_Device &device = getShortAddr(shortaddr); + if (device.hidden != hidden) { + device.hidden = hidden; + dirty(); + } +} + +bool Z_Devices::isHueBulbHidden(uint16_t shortaddr) const { + const Z_Device & device = findShortAddr(shortaddr); + if (foundDevice(device)) { + return device.hidden; + } + return true; +} + + + + +void Z_Devices::resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster, uint8_t endpoint) { + + for (auto & defer : _deferred) { + if ((defer.shortaddr == shortaddr) && (defer.groupaddr == groupaddr)) { + if ((0xFF == category) || (defer.category == category)) { + if ((0xFFFF == cluster) || (defer.cluster == cluster)) { + if ((0xFF == endpoint) || (defer.endpoint == endpoint)) { + _deferred.remove(&defer); + } + } + } + } + } +} + + +void Z_Devices::setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { + + if (category >= Z_CLEAR_DEVICE) { + resetTimersForDevice(shortaddr, groupaddr, category, category >= Z_CLEAR_DEVICE_CLUSTER ? cluster : 0xFFFF, category >= Z_CLEAR_DEVICE_CLUSTER_ENDPOINT ? endpoint : 0xFF); + } + + + Z_Deferred & deferred = _deferred.addHead(); + deferred = { wait_ms + millis(), + shortaddr, + groupaddr, + cluster, + endpoint, + category, + value, + func }; +} + + + +void Z_Devices::queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { + Z_Device & device = getShortAddr(shortaddr); + uint32_t now_millis = millis(); + if (TimeReached(device.defer_last_message_sent)) { + device.defer_last_message_sent = now_millis; + } + + device.defer_last_message_sent += wait_ms; + + + setTimer(shortaddr, groupaddr, (device.defer_last_message_sent - now_millis), cluster, endpoint, Z_CAT_ALWAYS, value, func); +} + + + +void Z_Devices::runTimer(void) { + + for (auto & defer : _deferred) { + uint32_t timer = defer.timer; + if (TimeReached(timer)) { + (*defer.func)(defer.shortaddr, defer.groupaddr, defer.cluster, defer.endpoint, defer.value); + _deferred.remove(&defer); + } + } + + + if ((_saveTimer) && TimeReached(_saveTimer)) { + saveZigbeeDevices(); + _saveTimer = 0; + } +} + + + + +bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const Z_attribute_list &attr_list) const { + const Z_Device & device = findShortAddr(shortaddr); + + if (!foundDevice(device)) { return false; } + if (attr_list.isEmpty()) { + return false; + } + + + if (device.attr_list.isValidGroupId() && attr_list.isValidGroupId()) { + if (device.attr_list.group_id != attr_list.group_id) { return true; } + } + + + if (device.attr_list.isValidSrcEp() && attr_list.isValidSrcEp()) { + if (device.attr_list.src_ep != attr_list.src_ep) { return true; } + } + + + + + for (const auto & attr : attr_list) { + const Z_attribute * curr_attr = device.attr_list.findAttribute(attr); + if (nullptr != curr_attr) { + if (!curr_attr->equalsVal(attr)) { + return true; + } + } + } + return false; +} + +void Z_Devices::jsonAppend(uint16_t shortaddr, const Z_attribute_list &attr_list) { + Z_Device & device = getShortAddr(shortaddr); + device.attr_list.mergeList(attr_list); +} + +void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (!device.valid()) { return; } + Z_attribute_list &attr_list = device.attr_list; + + if (!attr_list.isEmpty()) { + const char * fname = zigbee_devices.getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); + + + gZbLastMessage.device = shortaddr; + gZbLastMessage.groupaddr = attr_list.group_id; + gZbLastMessage.endpoint = attr_list.src_ep; + + mqtt_data[0] = 0; + + if (!Settings.flag4.remove_zbreceived) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":")); + } + + if (use_fname) { + Response_P(PSTR("%s{\"%s\":{"), mqtt_data, fname); + } else { + Response_P(PSTR("%s{\"0x%04X\":{"), mqtt_data, shortaddr); + } + + Response_P(PSTR("%s\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\","), mqtt_data, shortaddr); + + if (fname) { + Response_P(PSTR("%s\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), mqtt_data, EscapeJSONString(fname).c_str()); + } + + Response_P(PSTR("%s%s}}"), mqtt_data, attr_list.toString().c_str()); + + if (!Settings.flag4.remove_zbreceived) { + Response_P(PSTR("%s}"), mqtt_data); + } + attr_list.reset(); + + if (Settings.flag4.zigbee_distinct_topics) { + if (Settings.flag4.zb_topic_fname && fname) { + + char stemp[TOPSZ]; + strlcpy(stemp, (!strlen(fname)) ? MQTT_TOPIC : fname, sizeof(stemp)); + MakeValidMqtt(0, stemp); + + char frtopic[TOPSZ]; + snprintf_P(frtopic, sizeof(frtopic), PSTR("%s/%s/" D_RSLT_SENSOR), SettingsText(SET_MQTTPREFIX3), stemp); + MqttPublish(frtopic, Settings.flag.mqtt_sensor_retain); + } else { + char subtopic[16]; + snprintf_P(subtopic, sizeof(subtopic), PSTR("%04X/" D_RSLT_SENSOR), shortaddr); + MqttPublishPrefixTopic_P(TELE, subtopic, Settings.flag.mqtt_sensor_retain); + } + } else { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + } + XdrvRulesProcess(); + } +} + +void Z_Devices::jsonPublishNow(uint16_t shortaddr, Z_attribute_list &attr_list) { + jsonPublishFlush(shortaddr); + jsonAppend(shortaddr, attr_list); + jsonPublishFlush(shortaddr); +} + +void Z_Devices::dirty(void) { + _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); +} +void Z_Devices::clean(void) { + _saveTimer = 0; +} + + + + + + +uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { + if (nullptr == param) { return BAD_SHORTADDR; } + size_t param_len = strlen(param); + char dataBuf[param_len + 1]; + strcpy(dataBuf, param); + RemoveSpace(dataBuf); + uint16_t shortaddr = BAD_SHORTADDR; + + if (strlen(dataBuf) < 4) { + + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { + shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); + } + } else if ((dataBuf[0] == '0') && ((dataBuf[1] == 'x') || (dataBuf[1] == 'X'))) { + + if (strlen(dataBuf) < 18) { + + shortaddr = strtoull(dataBuf, nullptr, 0); + if (short_must_be_known) { + shortaddr = zigbee_devices.findShortAddr(shortaddr).shortaddr; + } + + } else { + + uint64_t longaddr = strtoull(dataBuf, nullptr, 0); + shortaddr = zigbee_devices.isKnownLongAddr(longaddr); + } + } else { + + shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); + } + + return shortaddr; +} + + +String Z_Devices::dumpLightState(uint16_t shortaddr) const { + Z_attribute_list attr_list; + char hex[8]; + + const Z_Device & device = findShortAddr(shortaddr); + const char * fname = getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + + attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex); + if (fname) { + attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(fname); + } + + if (foundDevice(device)) { + + attr_list.addAttribute(F("Reachable")).setBool(device.getReachable()); + if (device.validPower()) { attr_list.addAttribute(F("Power")).setUInt(device.getPower()); } + const Z_Data_Light & light = device.data.find(0); + if (&light != nullptr) { + light.toAttributes(attr_list, Z_Data_Light::type); + + if (light.validHue()) { + attr_list.findOrCreateAttribute(PSTR("Hue")).setUInt(light.getHue()); + } + } + + } + + Z_attribute_list attr_list_root; + Z_attribute * attr_root; + if (use_fname) { + attr_root = &attr_list_root.addAttribute(fname); + } else { + attr_root = &attr_list_root.addAttribute(hex); + } + attr_root->setStrRaw(attr_list.toString(true).c_str()); + return attr_list_root.toString(true); +} + + + + +String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { + Z_json_array json_arr; + + for (const auto & device : _devices) { + uint16_t shortaddr = device.shortaddr; + char hex[22]; + + + if ((BAD_SHORTADDR != status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } + + Z_attribute_list attr_list; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex); + + if (device.friendlyName > 0) { + attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(device.friendlyName); + } + + if (2 <= dump_mode) { + hex[0] = '0'; + hex[1] = 'x'; + Uint64toHex(device.longaddr, &hex[2], 64); + attr_list.addAttribute(F("IEEEAddr")).setStr(hex); + if (device.modelId) { + attr_list.addAttribute(F(D_JSON_MODEL D_JSON_ID)).setStr(device.modelId); + } + int8_t bulbtype = getHueBulbtype(shortaddr); + if (bulbtype >= 0) { + attr_list.addAttribute(F(D_JSON_ZIGBEE_LIGHT)).setInt(bulbtype); + } + if (device.manufacturerId) { + attr_list.addAttribute(F("Manufacturer")).setStr(device.manufacturerId); + } + Z_json_array arr_ep; + for (uint32_t i = 0; i < endpoints_max; i++) { + uint8_t endpoint = device.endpoints[i]; + if (0x00 == endpoint) { break; } + arr_ep.add(endpoint); + } + attr_list.addAttribute(F("Endpoints")).setStrRaw(arr_ep.toString().c_str()); + } + json_arr.addStrRaw(attr_list.toString(true).c_str()); + } + return json_arr.toString(); +} +# 710 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" +int32_t Z_Devices::deviceRestore(JsonParserObject json) { + + + uint16_t device = 0x0000; + uint64_t ieeeaddr = 0x0000000000000000LL; + const char * modelid = nullptr; + const char * manufid = nullptr; + const char * friendlyname = nullptr; + int8_t bulbtype = -1; + size_t endpoints_len = 0; + + + JsonParserToken val_device = json[PSTR("Device")]; + if (val_device) { + device = (uint32_t) val_device.getUInt(device); + } else { + return -1; + } + + ieeeaddr = json.getULong(PSTR("IEEEAddr"), ieeeaddr); + friendlyname = json.getStr(PSTR("Name"), nullptr); + modelid = json.getStr(PSTR("ModelId"), nullptr); + manufid = json.getStr(PSTR("Manufacturer"), nullptr); + JsonParserToken tok_bulbtype = json[PSTR(D_JSON_ZIGBEE_LIGHT)]; + + + updateDevice(device, ieeeaddr); + if (modelid) { setModelId(device, modelid); } + if (manufid) { setManufId(device, manufid); } + if (friendlyname) { setFriendlyName(device, friendlyname); } + if (tok_bulbtype) { setLightProfile(device, tok_bulbtype.getInt()); } + + + JsonParserToken val_endpoints = json[PSTR("Endpoints")]; + if (val_endpoints.isArray()) { + JsonParserArray arr_ep = JsonParserArray(val_endpoints); + clearEndpoints(device); + for (auto ep_elt : arr_ep) { + uint8_t ep = ep_elt.getUInt(); + if (ep) { addEndpoint(device, ep); } + } + } + + return 0; +} + +Z_Data_Light & Z_Devices::getLight(uint16_t shortaddr) { + return getShortAddr(shortaddr).data.get(); +} + + + + +void Z_Device::toAttributes(Z_attribute_list & attr_list) const { + if (validLqi()) { attr_list.addAttribute(PSTR(D_CMND_ZIGBEE_LINKQUALITY)).setUInt(lqi); } + if (validBatteryPercent()) { attr_list.addAttribute(PSTR("BatteryPercentage")).setUInt(batterypercent); } + if (validLastSeen()) { attr_list.addAttribute(PSTR("LastSeen")).setUInt(last_seen); } +} + + + + +void Z_Device::setPower(bool power_on, uint8_t ep) { + data.get(ep).setPower(power_on); +} + +bool Z_Device::validPower(uint8_t ep) const { + const Z_Data_OnOff & onoff = data.find(ep); + return (&onoff != nullptr); +} + +bool Z_Device::getPower(uint8_t ep) const { + const Z_Data_OnOff & onoff = data.find(ep); + if (&onoff != nullptr) return onoff.getPower(); + return false; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_3_hue.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_3_hue.ino" +#ifdef USE_ZIGBEE +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + + + + +void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response) { + static const char HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE[] PROGMEM = + "%s\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":%s}"; + + bool power = false; + bool reachable = false; + uint8_t colormode = 0xFF; + uint8_t bri = 0xFF; + uint8_t sat = 0xFF; + uint16_t ct = 0xFFFF; + uint16_t hue = 0xFFFF; + uint16_t x = 0xFFFF, y = 0xFFFF; + String light_status = ""; + uint32_t echo_gen = findEchoGeneration(); + + const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); + const Z_Data_Light & light = device.data.find(); + if (&light != nullptr) { + bri = light.getDimmer(); + colormode = light.getColorMode(); + sat = light.getSat(); + ct = light.getCT(); + hue = light.getHue(); + x = light.getX(); + y = light.getY(); + } + power = device.getPower(); + reachable = device.getReachable(); + + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + if (sat > 254) sat = 254; + uint16_t hue16 = changeUIntScale(hue, 0, 360, 0, 65535); + + const size_t buf_size = 256; + char * buf = (char*) malloc(buf_size); + + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? "true" : "false"); + + if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { + snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); + } + if (LST_COLDWARM <= local_light_subtype) { + snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, (0 == colormode) ? "hs" : (1 == colormode) ? "xy" : "ct"); + } + if (LST_RGB <= local_light_subtype) { + if (prev_x_str[0] && prev_y_str[0]) { + snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, prev_x_str, prev_y_str); + } else { + float x_f = x / 65536.0f; + float y_f = y / 65536.0f; + snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, String(x, 5).c_str(), String(y, 5).c_str()); + } + snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue16, sat); + } + if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { + snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); + } + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? "true" : "false"); + + *response += buf; + free(buf); +} + +void HueLightStatus2Zigbee(uint16_t shortaddr, String *response) +{ + const size_t buf_size = 300; + char * buf = (char*) malloc(buf_size); + + const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); + const char * friendlyName = device.friendlyName; + const char * modelId = device.modelId; + const char * manufacturerId = device.manufacturerId; + char shortaddrname[8]; + snprintf_P(shortaddrname, sizeof(shortaddrname), PSTR("0x%04X"), shortaddr); + + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2, + (friendlyName) ? EscapeJSONString(friendlyName).c_str() : shortaddrname, + (modelId) ? EscapeJSONString(modelId).c_str() : PSTR("Unknown"), + (manufacturerId) ? EscapeJSONString(manufacturerId).c_str() : PSTR("Tasmota"), + GetHueDeviceId(shortaddr).c_str()); + + *response += buf; + free(buf); +} + +void ZigbeeHueStatus(String * response, uint16_t shortaddr) { + *response += F("{\"state\":"); + HueLightStatus1Zigbee(shortaddr, zigbee_devices.getHueBulbtype(shortaddr), response); + HueLightStatus2Zigbee(shortaddr, response); +} + +void ZigbeeCheckHue(String * response, bool &appending) { + uint32_t zigbee_num = zigbee_devices.devicesSize(); + for (uint32_t i = 0; i < zigbee_num; i++) { + uint16_t shortaddr = zigbee_devices.devicesAt(i).shortaddr; + int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); + + if (bulbtype >= 0) { + + if (appending) { *response += ","; } + *response += "\""; + *response += EncodeLightId(0, shortaddr); + *response += F("\":{\"state\":"); + HueLightStatus1Zigbee(shortaddr, bulbtype, response); + HueLightStatus2Zigbee(shortaddr, response); + appending = true; + } + } +} + +void ZigbeeHueGroups(String * lights) { + uint32_t zigbee_num = zigbee_devices.devicesSize(); + for (uint32_t i = 0; i < zigbee_num; i++) { + uint16_t shortaddr = zigbee_devices.devicesAt(i).shortaddr; + int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); + + if (bulbtype >= 0) { + *lights += ",\""; + *lights += EncodeLightId(i); + *lights += "\""; + } + } +} + + + +void ZigbeeHuePower(uint16_t shortaddr, bool power) { + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0006, power ? 1 : 0, ""); + zigbee_devices.getShortAddr(shortaddr).setPower(power, 0); +} + + +void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { + if (dimmer > 0xFE) { dimmer = 0xFE; } + char param[8]; + snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0008, 0x04, param); + zigbee_devices.getLight(shortaddr).setDimmer(dimmer); +} + + +void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { + if (ct > 0xFEFF) { ct = 0xFEFF; } + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeHueCT 0x%04X - %d"), shortaddr, ct); + char param[12]; + snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8); + uint8_t colormode = 2; + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x0A, param); + Z_Data_Light & light = zigbee_devices.getLight(shortaddr); + light.setColorMode(colormode); + light.setCT(ct); +} + + +void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { + char param[16]; + if (x > 0xFEFF) { x = 0xFEFF; } + if (y > 0xFEFF) { y = 0xFEFF; } + snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8); + uint8_t colormode = 1; + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x07, param); + Z_Data_Light & light = zigbee_devices.getLight(shortaddr); + light.setColorMode(colormode); + light.setX(x); + light.setY(y); +} + + +void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { + char param[16]; + uint8_t hue8 = changeUIntScale(hue, 0, 360, 0, 254); + if (sat > 0xFE) { sat = 0xFE; } + snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat); + uint8_t colormode = 0; + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x06, param); + Z_Data_Light & light = zigbee_devices.getLight(shortaddr); + light.setColorMode(colormode); + light.setSat(sat); + light.setHue(hue); +} + +void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { + uint8_t power, colormode, bri, sat; + uint16_t ct, hue; + float x, y; + int code = 200; + + bool resp = false; + bool on = false; + + uint8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); + + const size_t buf_size = 100; + char * buf = (char*) malloc(buf_size); + + if (Webserver->args()) { + response = "["; + + JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); + JsonParserObject root = parser.getRootObject(); + + JsonParserToken hue_on = root[PSTR("on")]; + if (hue_on) { + on = hue_on.getBool(); + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"), + device_id, on ? "true" : "false"); + + if (on) { + ZigbeeHuePower(shortaddr, 0x01); + } else { + ZigbeeHuePower(shortaddr, 0x00); + } + response += buf; + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_bri = root[PSTR("bri")]; + if (hue_bri) { + bri = hue_bri.getUInt(); + prev_bri = bri; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "bri", bri); + response += buf; + if (LST_SINGLE <= bulbtype) { + + if (254 <= bri) { bri = 255; } + ZigbeeHueDimmer(shortaddr, bri); + } + resp = true; + } + + + parser.setCurrent(); + JsonParserToken hue_xy = root[PSTR("xy")]; + if (hue_xy) { + JsonParserArray arr_xy = JsonParserArray(hue_xy); + JsonParserToken tok_x = arr_xy[0]; + JsonParserToken tok_y = arr_xy[1]; + float x = tok_x.getFloat(); + float y = tok_y.getFloat(); + strlcpy(prev_x_str, tok_x.getStr(), sizeof(prev_x_str)); + strlcpy(prev_y_str, tok_y.getStr(), sizeof(prev_y_str)); + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/xy\":[%s,%s]}}"), + device_id, prev_x_str, prev_y_str); + response += buf; + resp = true; + uint16_t xi = x * 65536.0f; + uint16_t yi = y * 65536.0f; + ZigbeeHueXY(shortaddr, xi, yi); + } + bool huesat_changed = false; + + parser.setCurrent(); + JsonParserToken hue_hue = root[PSTR("hue")]; + if (hue_hue) { + hue = hue_hue.getUInt(); + prev_hue = hue; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "hue", hue); + response += buf; + if (LST_RGB <= bulbtype) { + + hue = changeUIntScale(hue, 0, 65535, 0, 360); + huesat_changed = true; + } + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_sat = root[PSTR("sat")]; + if (hue_sat) { + sat = hue_sat.getUInt(); + prev_sat = sat; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "sat", sat); + response += buf; + if (LST_RGB <= bulbtype) { + + if (254 <= sat) { sat = 255; } + huesat_changed = true; + } + if (huesat_changed) { + ZigbeeHueHS(shortaddr, hue, sat); + } + resp = true; + } + + parser.setCurrent(); + JsonParserToken hue_ct = root[PSTR("ct")]; + if (hue_ct) { + ct = hue_ct.getUInt(); + prev_ct = ct; + if (resp) { response += ","; } + snprintf_P(buf, buf_size, + PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), + device_id, "ct", ct); + response += buf; + if ((LST_COLDWARM == bulbtype) || (LST_RGBW <= bulbtype)) { + ZigbeeHueCT(shortaddr, ct); + } + resp = true; + } + + response += "]"; + if (2 == response.length()) { + response = FPSTR(HUE_ERROR_JSON); + } + } + else { + response = FPSTR(HUE_ERROR_JSON); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); + + free(buf); +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +#ifdef USE_ZIGBEE +# 52 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +#ifdef ESP8266 +const static uint16_t z_spi_start_sector = 0xFF; +const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; +const static uint8_t* z_dev_start = z_spi_start + 0x0800; +const static size_t z_spi_len = 0x1000; +const static size_t z_block_offset = 0x0800; +const static size_t z_block_len = 0x0800; +#else +uint8_t* z_dev_start; +const static size_t z_spi_len = 0x1000; +const static size_t z_block_offset = 0x0000; +const static size_t z_block_len = 0x1000; +#endif + +class z_flashdata_t { +public: + uint32_t name; + uint16_t len; + uint16_t reserved; +}; + +const static uint32_t ZIGB_NAME = 0x3167697A; +const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); + + +class SBuffer hibernateDevice(const struct Z_Device &device) { + SBuffer buf(128); + + buf.add8(0x00); + buf.add16(device.shortaddr); + buf.add64(device.longaddr); + + uint32_t endpoints_count = 0; + for (endpoints_count = 0; endpoints_count < endpoints_max; endpoints_count++) { + if (0x00 == device.endpoints[endpoints_count]) { break; } + } + + buf.add8(endpoints_count); + + for (uint32_t i = 0; i < endpoints_max; i++) { + uint8_t endpoint = device.endpoints[i]; + if (0x00 == endpoint) { break; } + + buf.add8(endpoint); + buf.add16(0x0000); + + + buf.add8(0xFF); + + + buf.add8(0xFF); + } + + + if (device.modelId) { + size_t model_len = strlen(device.modelId); + if (model_len > 32) { model_len = 32; } + buf.addBuffer(device.modelId, model_len); + } + buf.add8(0x00); + + + if (device.manufacturerId) { + size_t manuf_len = strlen(device.manufacturerId); + if (manuf_len > 32) { manuf_len = 32; } + buf.addBuffer(device.manufacturerId, manuf_len); + } + buf.add8(0x00); + + + if (device.friendlyName) { + size_t frname_len = strlen(device.friendlyName); + if (frname_len > 32) {frname_len = 32; } + buf.addBuffer(device.friendlyName, frname_len); + } + buf.add8(0x00); + + + buf.add8(device.getLightChannels()); + + + buf.set8(0, buf.len()); + + return buf; +} + +class SBuffer hibernateDevices(void) { + SBuffer buf(2048); + + size_t devices_size = zigbee_devices.devicesSize(); + if (devices_size > 32) { devices_size = 32; } + buf.add8(devices_size); + + for (uint32_t i = 0; i < devices_size; i++) { + const Z_Device & device = zigbee_devices.devicesAt(i); + const SBuffer buf_device = hibernateDevice(device); + buf.addBuffer(buf_device); + } + + size_t buf_len = buf.len(); + if (buf_len > 2040) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); + } + + + char *hex_char = (char*) malloc((buf_len * 2) + 2); + if (hex_char) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), + ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); + free(hex_char); + } + + return buf; +} + +void hydrateDevices(const SBuffer &buf) { + uint32_t buf_len = buf.len(); + if (buf_len <= 10) { return; } + + uint32_t k = 0; + uint32_t num_devices = buf.get8(k++); + for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { + uint32_t dev_record_len = buf.get8(k); + + SBuffer buf_d = buf.subBuffer(k, dev_record_len); + + uint32_t d = 1; + uint16_t shortaddr = buf_d.get16(d); d += 2; + uint64_t longaddr = buf_d.get64(d); d += 8; + zigbee_devices.updateDevice(shortaddr, longaddr); + + uint32_t endpoints = buf_d.get8(d++); + for (uint32_t j = 0; j < endpoints; j++) { + uint8_t ep = buf_d.get8(d++); + uint16_t ep_profile = buf_d.get16(d); d += 2; + zigbee_devices.addEndpoint(shortaddr, ep); + + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + + } + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + + } + } + + + char empty[] = ""; + + + uint32_t s_len = buf_d.strlen_s(d); + char *ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setModelId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setManufId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setFriendlyName(shortaddr, ptr); + d += s_len + 1; + + + if (d < dev_record_len) { + zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d)); + d++; + } + + + k += dev_record_len; + } +} + +void loadZigbeeDevices(void) { +#ifdef ESP32 + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + ZigbeeRead(&spi_buffer, z_spi_len); + z_dev_start = spi_buffer; +#endif + z_flashdata_t flashdata; + memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); + + + if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { + uint16_t buf_len = flashdata.len; + + SBuffer buf(buf_len); + buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); + hydrateDevices(buf); + zigbee_devices.clean(); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); + } + +#ifdef ESP32 + free(spi_buffer); +#endif +} + +void saveZigbeeDevices(void) { + SBuffer buf = hibernateDevices(); + size_t buf_len = buf.len(); + if (buf_len > Z_MAX_FLASH) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); + return; + } + + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + +#ifdef ESP8266 + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); +#else + ZigbeeRead(&spi_buffer, z_spi_len); +#endif + + z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); + flashdata->name = ZIGB_NAME; + flashdata->len = buf_len; + flashdata->reserved = 0; + + memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); + + +#ifdef ESP8266 + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); +#else + ZigbeeWrite(&spi_buffer, z_spi_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data saved (%d bytes)"), buf_len); +#endif + free(spi_buffer); +} + + +void eraseZigbeeDevices(void) { + zigbee_devices.clean(); +#ifdef ESP8266 + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + + memset(spi_buffer + z_block_offset, 0xFF, z_block_len); + + + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); +#else + ZigbeeErase(); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (%d bytes)"), z_block_len); +#endif +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" +#ifdef USE_ZIGBEE +# 76 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" +const char Z_strings[] PROGMEM = + "\x00" + "ZCLVersion" "\x00" + "AppVersion" "\x00" + "StackVersion" "\x00" + "HWVersion" "\x00" + "Manufacturer" "\x00" + "ModelId" "\x00" + "DateCode" "\x00" + "PowerSource" "\x00" + "GenericDeviceClass" "\x00" + "GenericDeviceType" "\x00" + "ProductCode" "\x00" + "ProductURL" "\x00" + "SWBuildID" "\x00" + "MainsVoltage" "\x00" + "MainsFrequency" "\x00" + "BatteryVoltage" "\x00" + "BatteryPercentage" "\x00" + "CurrentTemperature" "\x00" + "MinTempExperienced" "\x00" + "MaxTempExperienced" "\x00" + "OverTempTotalDwell" "\x00" + "IdentifyTime" "\x00" + "GroupNameSupport" "\x00" + "SceneCount" "\x00" + "CurrentScene" "\x00" + "CurrentGroup" "\x00" + "SceneValid" "\x00" + "Power" "\x00" + "StartUpOnOff" "\x00" + "SwitchType" "\x00" + "Dimmer" "\x00" + "DimmerOptions" "\x00" + "DimmerRemainingTime" "\x00" + "OnOffTransitionTime" "\x00" + "AlarmCount" "\x00" + "Time" "\x00" + "TimeStatus" "\x00" + "TimeZone" "\x00" + "DstStart" "\x00" + "DstEnd" "\x00" + "DstShift" "\x00" + "StandardTime" "\x00" + "LocalTime" "\x00" + "LastSetTime" "\x00" + "ValidUntilTime" "\x00" + "TimeEpoch" "\x00" + "LocationType" "\x00" + "LocationMethod" "\x00" + "LocationAge" "\x00" + "QualityMeasure" "\x00" + "NumberOfDevices" "\x00" + "AnalogInDescription" "\x00" + "AnalogInMaxValue" "\x00" + "AnalogInMinValue" "\x00" + "AnalogInOutOfService" "\x00" + "AqaraRotate" "\x00" + "AnalogInReliability" "\x00" + "AnalogInResolution" "\x00" + "AnalogInStatusFlags" "\x00" + "AnalogInEngineeringUnits" "\x00" + "AnalogInApplicationType" "\x00" + "Aqara_FF05" "\x00" + "AnalogOutDescription" "\x00" + "AnalogOutMaxValue" "\x00" + "AnalogOutMinValue" "\x00" + "AnalogOutOutOfService" "\x00" + "AnalogOutValue" "\x00" + "AnalogOutReliability" "\x00" + "AnalogOutRelinquishDefault" "\x00" + "AnalogOutResolution" "\x00" + "AnalogOutStatusFlags" "\x00" + "AnalogOutEngineeringUnits" "\x00" + "AnalogOutApplicationType" "\x00" + "AnalogDescription" "\x00" + "AnalogOutOfService" "\x00" + "AnalogValue" "\x00" + "AnalogPriorityArray" "\x00" + "AnalogReliability" "\x00" + "AnalogRelinquishDefault" "\x00" + "AnalogStatusFlags" "\x00" + "AnalogEngineeringUnits" "\x00" + "AnalogApplicationType" "\x00" + "BinaryInActiveText" "\x00" + "BinaryInDescription" "\x00" + "BinaryInInactiveText" "\x00" + "BinaryInOutOfService" "\x00" + "BinaryInPolarity" "\x00" + "BinaryInValue" "\x00" + "BinaryInReliability" "\x00" + "BinaryInStatusFlags" "\x00" + "BinaryInApplicationType" "\x00" + "BinaryOutActiveText" "\x00" + "BinaryOutDescription" "\x00" + "BinaryOutInactiveText" "\x00" + "BinaryOutMinimumOffTime" "\x00" + "BinaryOutMinimumOnTime" "\x00" + "BinaryOutOutOfService" "\x00" + "BinaryOutPolarity" "\x00" + "BinaryOutValue" "\x00" + "BinaryOutReliability" "\x00" + "BinaryOutRelinquishDefault" "\x00" + "BinaryOutStatusFlags" "\x00" + "BinaryOutApplicationType" "\x00" + "BinaryActiveText" "\x00" + "BinaryDescription" "\x00" + "BinaryInactiveText" "\x00" + "BinaryMinimumOffTime" "\x00" + "BinaryMinimumOnTime" "\x00" + "BinaryOutOfService" "\x00" + "BinaryValue" "\x00" + "BinaryReliability" "\x00" + "BinaryRelinquishDefault" "\x00" + "BinaryStatusFlags" "\x00" + "BinaryApplicationType" "\x00" + "MultiInDescription" "\x00" + "MultiInNumberOfStates" "\x00" + "MultiInOutOfService" "\x00" + "MultiInValue" "\x00" + "MultiInReliability" "\x00" + "MultiInStatusFlags" "\x00" + "MultiInApplicationType" "\x00" + "MultiOutDescription" "\x00" + "MultiOutNumberOfStates" "\x00" + "MultiOutOutOfService" "\x00" + "MultiOutValue" "\x00" + "MultiOutReliability" "\x00" + "MultiOutRelinquishDefault" "\x00" + "MultiOutStatusFlags" "\x00" + "MultiOutApplicationType" "\x00" + "MultiDescription" "\x00" + "MultiNumberOfStates" "\x00" + "MultiOutOfService" "\x00" + "MultiValue" "\x00" + "MultiReliability" "\x00" + "MultiRelinquishDefault" "\x00" + "MultiStatusFlags" "\x00" + "MultiApplicationType" "\x00" + "TotalProfileNum" "\x00" + "MultipleScheduling" "\x00" + "EnergyFormatting" "\x00" + "EnergyRemote" "\x00" + "ScheduleMode" "\x00" + "CheckinInterval" "\x00" + "LongPollInterval" "\x00" + "ShortPollInterval" "\x00" + "FastPollTimeout" "\x00" + "CheckinIntervalMin" "\x00" + "LongPollIntervalMin" "\x00" + "FastPollTimeoutMax" "\x00" + "PhysicalClosedLimit" "\x00" + "MotorStepSize" "\x00" + "Status" "\x00" + "ClosedLimit" "\x00" + "Mode" "\x00" + "LockState" "\x00" + "LockType" "\x00" + "ActuatorEnabled" "\x00" + "DoorState" "\x00" + "DoorOpenEvents" "\x00" + "DoorClosedEvents" "\x00" + "OpenPeriod" "\x00" + "AqaraVibrationMode" "\x00" + "AqaraVibrationsOrAngle" "\x00" + "AqaraVibration505" "\x00" + "AqaraAccelerometer" "\x00" + "WindowCoveringType" "\x00" + "PhysicalClosedLimitLift" "\x00" + "PhysicalClosedLimitTilt" "\x00" + "CurrentPositionLift" "\x00" + "CurrentPositionTilt" "\x00" + "NumberofActuationsLift" "\x00" + "NumberofActuationsTilt" "\x00" + "ConfigStatus" "\x00" + "CurrentPositionLiftPercentage" "\x00" + "CurrentPositionTiltPercentage" "\x00" + "InstalledOpenLimitLift" "\x00" + "InstalledClosedLimitLift" "\x00" + "InstalledOpenLimitTilt" "\x00" + "InstalledClosedLimitTilt" "\x00" + "VelocityLift" "\x00" + "AccelerationTimeLift" "\x00" + "DecelerationTimeLift" "\x00" + "IntermediateSetpointsLift" "\x00" + "IntermediateSetpointsTilt" "\x00" + "LocalTemperature" "\x00" + "OutdoorTemperature" "\x00" + "PICoolingDemand" "\x00" + "PIHeatingDemand" "\x00" + "LocalTemperatureCalibration" "\x00" + "OccupiedCoolingSetpoint" "\x00" + "OccupiedHeatingSetpoint" "\x00" + "UnoccupiedCoolingSetpoint" "\x00" + "UnoccupiedHeatingSetpoint" "\x00" + "RemoteSensing" "\x00" + "ControlSequenceOfOperation" "\x00" + "SystemMode" "\x00" + "TRVMode" "\x00" + "ValvePosition" "\x00" + "EurotronicErrors" "\x00" + "CurrentTemperatureSetPoint" "\x00" + "ThSetpoint" "\x00" + "TempTarget" "\x00" + "Hue" "\x00" + "Sat" "\x00" + "RemainingTime" "\x00" + "X" "\x00" + "Y" "\x00" + "DriftCompensation" "\x00" + "CompensationText" "\x00" + "CT" "\x00" + "ColorMode" "\x00" + "NumberOfPrimaries" "\x00" + "Primary1X" "\x00" + "Primary1Y" "\x00" + "Primary1Intensity" "\x00" + "Primary2X" "\x00" + "Primary2Y" "\x00" + "Primary2Intensity" "\x00" + "Primary3X" "\x00" + "Primary3Y" "\x00" + "Primary3Intensity" "\x00" + "WhitePointX" "\x00" + "WhitePointY" "\x00" + "ColorPointRX" "\x00" + "ColorPointRY" "\x00" + "ColorPointRIntensity" "\x00" + "ColorPointGX" "\x00" + "ColorPointGY" "\x00" + "ColorPointGIntensity" "\x00" + "ColorPointBX" "\x00" + "ColorPointBY" "\x00" + "ColorPointBIntensity" "\x00" + "Illuminance" "\x00" + "IlluminanceMinMeasuredValue" "\x00" + "IlluminanceMaxMeasuredValue" "\x00" + "IlluminanceTolerance" "\x00" + "IlluminanceLightSensorType" "\x00" + "IlluminanceLevelStatus" "\x00" + "IlluminanceTargetLevel" "\x00" + "Temperature" "\x00" + "TemperatureMinMeasuredValue" "\x00" + "TemperatureMaxMeasuredValue" "\x00" + "TemperatureTolerance" "\x00" + "Pressure" "\x00" + "PressureMinMeasuredValue" "\x00" + "PressureMaxMeasuredValue" "\x00" + "PressureTolerance" "\x00" + "PressureScaledValue" "\x00" + "PressureMinScaledValue" "\x00" + "PressureMaxScaledValue" "\x00" + "PressureScaledTolerance" "\x00" + "PressureScale" "\x00" + "SeaPressure" "\x00" + "FlowRate" "\x00" + "FlowMinMeasuredValue" "\x00" + "FlowMaxMeasuredValue" "\x00" + "FlowTolerance" "\x00" + "Humidity" "\x00" + "HumidityMinMeasuredValue" "\x00" + "HumidityMaxMeasuredValue" "\x00" + "HumidityTolerance" "\x00" + "Occupancy" "\x00" + "OccupancySensorType" "\x00" + "ZoneState" "\x00" + "ZoneType" "\x00" + "ZoneStatus" "\x00" + "CurrentSummDelivered" "\x00" + "CompanyName" "\x00" + "MeterTypeID" "\x00" + "DataQualityID" "\x00" + "CustomerName" "\x00" + "Model" "\x00" + "PartNumber" "\x00" + "ProductRevision" "\x00" + "SoftwareRevision" "\x00" + "UtilityName" "\x00" + "POD" "\x00" + "AvailablePower" "\x00" + "PowerThreshold" "\x00" + "RMSVoltage" "\x00" + "RMSCurrent" "\x00" + "ActivePower" "\x00" + "NumberOfResets" "\x00" + "PersistentMemoryWrites" "\x00" + "LastMessageLQI" "\x00" + "LastMessageRSSI" "\x00" + "TuyaScheduleWorkdays" "\x00" + "TuyaScheduleHolidays" "\x00" + "TuyaChildLock" "\x00" + "TuyaWindowDetection" "\x00" + "TuyaValveDetection" "\x00" + "TuyaAutoLock" "\x00" + "TuyaTempTarget" "\x00" + "TuyaBattery" "\x00" + "TuyaMinTemp" "\x00" + "TuyaMaxTemp" "\x00" + "TuyaBoostTime" "\x00" + "TuyaComfortTemp" "\x00" + "TuyaEcoTemp" "\x00" + "TuyaValvePosition" "\x00" + "TuyaAwayTemp" "\x00" + "TuyaAwayDays" "\x00" + "TuyaPreset" "\x00" + "TuyaFanMode" "\x00" + "TuyaForceMode" "\x00" + "TuyaWeekSelect" "\x00" + "TerncyRotate" "\x00" + "TerncyDuration" "\x00" + "Identify" "\x00" + "xxxx" "\x00" + "IdentifyQuery" "\x00" + "AddGroup" "\x00" + "xxxx00" "\x00" + "ViewGroup" "\x00" + "GetGroup" "\x00" + "01xxxx" "\x00" + "GetAllGroups" "\x00" + "00" "\x00" + "RemoveGroup" "\x00" + "RemoveAllGroups" "\x00" + "ViewScene" "\x00" + "xxxxyy" "\x00" + "RemoveScene" "\x00" + "RemoveAllScenes" "\x00" + "RecallScene" "\x00" + "GetSceneMembership" "\x00" + "PowerOffEffect" "\x00" + "xxyy" "\x00" + "PowerOnRecall" "\x00" + "PowerOnTimer" "\x00" + "xxyyyyzzzz" "\x00" + "xx0A00" "\x00" + "DimmerUp" "\x00" + "00190200" "\x00" + "DimmerDown" "\x00" + "01190200" "\x00" + "DimmerStop" "\x00" + "ResetAlarm" "\x00" + "xxyyyy" "\x00" + "ResetAllAlarms" "\x00" + "xx000A00" "\x00" + "HueSat" "\x00" + "xxyy0A00" "\x00" + "Color" "\x00" + "xxxxyyyy0A00" "\x00" + "xxxx0A00" "\x00" + "ShutterOpen" "\x00" + "ShutterClose" "\x00" + "ShutterStop" "\x00" + "ShutterLift" "\x00" + "xx" "\x00" + "ShutterTilt" "\x00" + "Shutter" "\x00" + "DimmerMove" "\x00" + "xx0A" "\x00" + "DimmerStepUp" "\x00" + "00xx0A00" "\x00" + "DimmerStepDown" "\x00" + "01xx0A00" "\x00" + "DimmerStep" "\x00" + "xx190A00" "\x00" + "01" "\x00" + "HueMove" "\x00" + "xx19" "\x00" + "HueStepUp" "\x00" + "HueStepDown" "\x00" + "03xx0A00" "\x00" + "HueStep" "\x00" + "SatMove" "\x00" + "SatStep" "\x00" + "xx190A" "\x00" + "ColorMove" "\x00" + "xxxxyyyy" "\x00" + "ColorStep" "\x00" + "ColorTempMoveUp" "\x00" + "01xxxx000000000000" "\x00" + "ColorTempMoveDown" "\x00" + "03xxxx000000000000" "\x00" + "ColorTempMoveStop" "\x00" + "00xxxx000000000000" "\x00" + "ColorTempMove" "\x00" + "xxyyyy000000000000" "\x00" + "ColorTempStepUp" "\x00" + "01xxxx0A0000000000" "\x00" + "ColorTempStepDown" "\x00" + "03xxxx0A0000000000" "\x00" + "ColorTempStep" "\x00" + "xxyyyy0A0000000000" "\x00" + "ArrowClick" "\x00" + "ArrowHold" "\x00" + "ArrowRelease" "\x00" + "ZoneStatusChange" "\x00" + "xxxxyyzz" "\x00" + "xxyyzzzz" "\x00" + "AddScene" "\x00" + "xxyyyyzz" "\x00" + "StoreScene" "\x00" + ; + +enum Z_offsets { + Zo_ = 0, + Zo_ZCLVersion = 1, + Zo_AppVersion = 12, + Zo_StackVersion = 23, + Zo_HWVersion = 36, + Zo_Manufacturer = 46, + Zo_ModelId = 59, + Zo_DateCode = 67, + Zo_PowerSource = 76, + Zo_GenericDeviceClass = 88, + Zo_GenericDeviceType = 107, + Zo_ProductCode = 125, + Zo_ProductURL = 137, + Zo_SWBuildID = 148, + Zo_MainsVoltage = 158, + Zo_MainsFrequency = 171, + Zo_BatteryVoltage = 186, + Zo_BatteryPercentage = 201, + Zo_CurrentTemperature = 219, + Zo_MinTempExperienced = 238, + Zo_MaxTempExperienced = 257, + Zo_OverTempTotalDwell = 276, + Zo_IdentifyTime = 295, + Zo_GroupNameSupport = 308, + Zo_SceneCount = 325, + Zo_CurrentScene = 336, + Zo_CurrentGroup = 349, + Zo_SceneValid = 362, + Zo_Power = 373, + Zo_StartUpOnOff = 379, + Zo_SwitchType = 392, + Zo_Dimmer = 403, + Zo_DimmerOptions = 410, + Zo_DimmerRemainingTime = 424, + Zo_OnOffTransitionTime = 444, + Zo_AlarmCount = 464, + Zo_Time = 475, + Zo_TimeStatus = 480, + Zo_TimeZone = 491, + Zo_DstStart = 500, + Zo_DstEnd = 509, + Zo_DstShift = 516, + Zo_StandardTime = 525, + Zo_LocalTime = 538, + Zo_LastSetTime = 548, + Zo_ValidUntilTime = 560, + Zo_TimeEpoch = 575, + Zo_LocationType = 585, + Zo_LocationMethod = 598, + Zo_LocationAge = 613, + Zo_QualityMeasure = 625, + Zo_NumberOfDevices = 640, + Zo_AnalogInDescription = 656, + Zo_AnalogInMaxValue = 676, + Zo_AnalogInMinValue = 693, + Zo_AnalogInOutOfService = 710, + Zo_AqaraRotate = 731, + Zo_AnalogInReliability = 743, + Zo_AnalogInResolution = 763, + Zo_AnalogInStatusFlags = 782, + Zo_AnalogInEngineeringUnits = 802, + Zo_AnalogInApplicationType = 827, + Zo_Aqara_FF05 = 851, + Zo_AnalogOutDescription = 862, + Zo_AnalogOutMaxValue = 883, + Zo_AnalogOutMinValue = 901, + Zo_AnalogOutOutOfService = 919, + Zo_AnalogOutValue = 941, + Zo_AnalogOutReliability = 956, + Zo_AnalogOutRelinquishDefault = 977, + Zo_AnalogOutResolution = 1004, + Zo_AnalogOutStatusFlags = 1024, + Zo_AnalogOutEngineeringUnits = 1045, + Zo_AnalogOutApplicationType = 1071, + Zo_AnalogDescription = 1096, + Zo_AnalogOutOfService = 1114, + Zo_AnalogValue = 1133, + Zo_AnalogPriorityArray = 1145, + Zo_AnalogReliability = 1165, + Zo_AnalogRelinquishDefault = 1183, + Zo_AnalogStatusFlags = 1207, + Zo_AnalogEngineeringUnits = 1225, + Zo_AnalogApplicationType = 1248, + Zo_BinaryInActiveText = 1270, + Zo_BinaryInDescription = 1289, + Zo_BinaryInInactiveText = 1309, + Zo_BinaryInOutOfService = 1330, + Zo_BinaryInPolarity = 1351, + Zo_BinaryInValue = 1368, + Zo_BinaryInReliability = 1382, + Zo_BinaryInStatusFlags = 1402, + Zo_BinaryInApplicationType = 1422, + Zo_BinaryOutActiveText = 1446, + Zo_BinaryOutDescription = 1466, + Zo_BinaryOutInactiveText = 1487, + Zo_BinaryOutMinimumOffTime = 1509, + Zo_BinaryOutMinimumOnTime = 1533, + Zo_BinaryOutOutOfService = 1556, + Zo_BinaryOutPolarity = 1578, + Zo_BinaryOutValue = 1596, + Zo_BinaryOutReliability = 1611, + Zo_BinaryOutRelinquishDefault = 1632, + Zo_BinaryOutStatusFlags = 1659, + Zo_BinaryOutApplicationType = 1680, + Zo_BinaryActiveText = 1705, + Zo_BinaryDescription = 1722, + Zo_BinaryInactiveText = 1740, + Zo_BinaryMinimumOffTime = 1759, + Zo_BinaryMinimumOnTime = 1780, + Zo_BinaryOutOfService = 1800, + Zo_BinaryValue = 1819, + Zo_BinaryReliability = 1831, + Zo_BinaryRelinquishDefault = 1849, + Zo_BinaryStatusFlags = 1873, + Zo_BinaryApplicationType = 1891, + Zo_MultiInDescription = 1913, + Zo_MultiInNumberOfStates = 1932, + Zo_MultiInOutOfService = 1954, + Zo_MultiInValue = 1974, + Zo_MultiInReliability = 1987, + Zo_MultiInStatusFlags = 2006, + Zo_MultiInApplicationType = 2025, + Zo_MultiOutDescription = 2048, + Zo_MultiOutNumberOfStates = 2068, + Zo_MultiOutOutOfService = 2091, + Zo_MultiOutValue = 2112, + Zo_MultiOutReliability = 2126, + Zo_MultiOutRelinquishDefault = 2146, + Zo_MultiOutStatusFlags = 2172, + Zo_MultiOutApplicationType = 2192, + Zo_MultiDescription = 2216, + Zo_MultiNumberOfStates = 2233, + Zo_MultiOutOfService = 2253, + Zo_MultiValue = 2271, + Zo_MultiReliability = 2282, + Zo_MultiRelinquishDefault = 2299, + Zo_MultiStatusFlags = 2322, + Zo_MultiApplicationType = 2339, + Zo_TotalProfileNum = 2360, + Zo_MultipleScheduling = 2376, + Zo_EnergyFormatting = 2395, + Zo_EnergyRemote = 2412, + Zo_ScheduleMode = 2425, + Zo_CheckinInterval = 2438, + Zo_LongPollInterval = 2454, + Zo_ShortPollInterval = 2471, + Zo_FastPollTimeout = 2489, + Zo_CheckinIntervalMin = 2505, + Zo_LongPollIntervalMin = 2524, + Zo_FastPollTimeoutMax = 2544, + Zo_PhysicalClosedLimit = 2563, + Zo_MotorStepSize = 2583, + Zo_Status = 2597, + Zo_ClosedLimit = 2604, + Zo_Mode = 2616, + Zo_LockState = 2621, + Zo_LockType = 2631, + Zo_ActuatorEnabled = 2640, + Zo_DoorState = 2656, + Zo_DoorOpenEvents = 2666, + Zo_DoorClosedEvents = 2681, + Zo_OpenPeriod = 2698, + Zo_AqaraVibrationMode = 2709, + Zo_AqaraVibrationsOrAngle = 2728, + Zo_AqaraVibration505 = 2751, + Zo_AqaraAccelerometer = 2769, + Zo_WindowCoveringType = 2788, + Zo_PhysicalClosedLimitLift = 2807, + Zo_PhysicalClosedLimitTilt = 2831, + Zo_CurrentPositionLift = 2855, + Zo_CurrentPositionTilt = 2875, + Zo_NumberofActuationsLift = 2895, + Zo_NumberofActuationsTilt = 2918, + Zo_ConfigStatus = 2941, + Zo_CurrentPositionLiftPercentage = 2954, + Zo_CurrentPositionTiltPercentage = 2984, + Zo_InstalledOpenLimitLift = 3014, + Zo_InstalledClosedLimitLift = 3037, + Zo_InstalledOpenLimitTilt = 3062, + Zo_InstalledClosedLimitTilt = 3085, + Zo_VelocityLift = 3110, + Zo_AccelerationTimeLift = 3123, + Zo_DecelerationTimeLift = 3144, + Zo_IntermediateSetpointsLift = 3165, + Zo_IntermediateSetpointsTilt = 3191, + Zo_LocalTemperature = 3217, + Zo_OutdoorTemperature = 3234, + Zo_PICoolingDemand = 3253, + Zo_PIHeatingDemand = 3269, + Zo_LocalTemperatureCalibration = 3285, + Zo_OccupiedCoolingSetpoint = 3313, + Zo_OccupiedHeatingSetpoint = 3337, + Zo_UnoccupiedCoolingSetpoint = 3361, + Zo_UnoccupiedHeatingSetpoint = 3387, + Zo_RemoteSensing = 3413, + Zo_ControlSequenceOfOperation = 3427, + Zo_SystemMode = 3454, + Zo_TRVMode = 3465, + Zo_ValvePosition = 3473, + Zo_EurotronicErrors = 3487, + Zo_CurrentTemperatureSetPoint = 3504, + Zo_ThSetpoint = 3531, + Zo_TempTarget = 3542, + Zo_Hue = 3553, + Zo_Sat = 3557, + Zo_RemainingTime = 3561, + Zo_X = 3575, + Zo_Y = 3577, + Zo_DriftCompensation = 3579, + Zo_CompensationText = 3597, + Zo_CT = 3614, + Zo_ColorMode = 3617, + Zo_NumberOfPrimaries = 3627, + Zo_Primary1X = 3645, + Zo_Primary1Y = 3655, + Zo_Primary1Intensity = 3665, + Zo_Primary2X = 3683, + Zo_Primary2Y = 3693, + Zo_Primary2Intensity = 3703, + Zo_Primary3X = 3721, + Zo_Primary3Y = 3731, + Zo_Primary3Intensity = 3741, + Zo_WhitePointX = 3759, + Zo_WhitePointY = 3771, + Zo_ColorPointRX = 3783, + Zo_ColorPointRY = 3796, + Zo_ColorPointRIntensity = 3809, + Zo_ColorPointGX = 3830, + Zo_ColorPointGY = 3843, + Zo_ColorPointGIntensity = 3856, + Zo_ColorPointBX = 3877, + Zo_ColorPointBY = 3890, + Zo_ColorPointBIntensity = 3903, + Zo_Illuminance = 3924, + Zo_IlluminanceMinMeasuredValue = 3936, + Zo_IlluminanceMaxMeasuredValue = 3964, + Zo_IlluminanceTolerance = 3992, + Zo_IlluminanceLightSensorType = 4013, + Zo_IlluminanceLevelStatus = 4040, + Zo_IlluminanceTargetLevel = 4063, + Zo_Temperature = 4086, + Zo_TemperatureMinMeasuredValue = 4098, + Zo_TemperatureMaxMeasuredValue = 4126, + Zo_TemperatureTolerance = 4154, + Zo_Pressure = 4175, + Zo_PressureMinMeasuredValue = 4184, + Zo_PressureMaxMeasuredValue = 4209, + Zo_PressureTolerance = 4234, + Zo_PressureScaledValue = 4252, + Zo_PressureMinScaledValue = 4272, + Zo_PressureMaxScaledValue = 4295, + Zo_PressureScaledTolerance = 4318, + Zo_PressureScale = 4342, + Zo_SeaPressure = 4356, + Zo_FlowRate = 4368, + Zo_FlowMinMeasuredValue = 4377, + Zo_FlowMaxMeasuredValue = 4398, + Zo_FlowTolerance = 4419, + Zo_Humidity = 4433, + Zo_HumidityMinMeasuredValue = 4442, + Zo_HumidityMaxMeasuredValue = 4467, + Zo_HumidityTolerance = 4492, + Zo_Occupancy = 4510, + Zo_OccupancySensorType = 4520, + Zo_ZoneState = 4540, + Zo_ZoneType = 4550, + Zo_ZoneStatus = 4559, + Zo_CurrentSummDelivered = 4570, + Zo_CompanyName = 4591, + Zo_MeterTypeID = 4603, + Zo_DataQualityID = 4615, + Zo_CustomerName = 4629, + Zo_Model = 4642, + Zo_PartNumber = 4648, + Zo_ProductRevision = 4659, + Zo_SoftwareRevision = 4675, + Zo_UtilityName = 4692, + Zo_POD = 4704, + Zo_AvailablePower = 4708, + Zo_PowerThreshold = 4723, + Zo_RMSVoltage = 4738, + Zo_RMSCurrent = 4749, + Zo_ActivePower = 4760, + Zo_NumberOfResets = 4772, + Zo_PersistentMemoryWrites = 4787, + Zo_LastMessageLQI = 4810, + Zo_LastMessageRSSI = 4825, + Zo_TuyaScheduleWorkdays = 4841, + Zo_TuyaScheduleHolidays = 4862, + Zo_TuyaChildLock = 4883, + Zo_TuyaWindowDetection = 4897, + Zo_TuyaValveDetection = 4917, + Zo_TuyaAutoLock = 4936, + Zo_TuyaTempTarget = 4949, + Zo_TuyaBattery = 4964, + Zo_TuyaMinTemp = 4976, + Zo_TuyaMaxTemp = 4988, + Zo_TuyaBoostTime = 5000, + Zo_TuyaComfortTemp = 5014, + Zo_TuyaEcoTemp = 5030, + Zo_TuyaValvePosition = 5042, + Zo_TuyaAwayTemp = 5060, + Zo_TuyaAwayDays = 5073, + Zo_TuyaPreset = 5086, + Zo_TuyaFanMode = 5097, + Zo_TuyaForceMode = 5109, + Zo_TuyaWeekSelect = 5123, + Zo_TerncyRotate = 5138, + Zo_TerncyDuration = 5151, + Zo_Identify = 5166, + Zo_xxxx = 5175, + Zo_IdentifyQuery = 5180, + Zo_AddGroup = 5194, + Zo_xxxx00 = 5203, + Zo_ViewGroup = 5210, + Zo_GetGroup = 5220, + Zo_01xxxx = 5229, + Zo_GetAllGroups = 5236, + Zo_00 = 5249, + Zo_RemoveGroup = 5252, + Zo_RemoveAllGroups = 5264, + Zo_ViewScene = 5280, + Zo_xxxxyy = 5290, + Zo_RemoveScene = 5297, + Zo_RemoveAllScenes = 5309, + Zo_RecallScene = 5325, + Zo_GetSceneMembership = 5337, + Zo_PowerOffEffect = 5356, + Zo_xxyy = 5371, + Zo_PowerOnRecall = 5376, + Zo_PowerOnTimer = 5390, + Zo_xxyyyyzzzz = 5403, + Zo_xx0A00 = 5414, + Zo_DimmerUp = 5421, + Zo_00190200 = 5430, + Zo_DimmerDown = 5439, + Zo_01190200 = 5450, + Zo_DimmerStop = 5459, + Zo_ResetAlarm = 5470, + Zo_xxyyyy = 5481, + Zo_ResetAllAlarms = 5488, + Zo_xx000A00 = 5503, + Zo_HueSat = 5512, + Zo_xxyy0A00 = 5519, + Zo_Color = 5528, + Zo_xxxxyyyy0A00 = 5534, + Zo_xxxx0A00 = 5547, + Zo_ShutterOpen = 5556, + Zo_ShutterClose = 5568, + Zo_ShutterStop = 5581, + Zo_ShutterLift = 5593, + Zo_xx = 5605, + Zo_ShutterTilt = 5608, + Zo_Shutter = 5620, + Zo_DimmerMove = 5628, + Zo_xx0A = 5639, + Zo_DimmerStepUp = 5644, + Zo_00xx0A00 = 5657, + Zo_DimmerStepDown = 5666, + Zo_01xx0A00 = 5681, + Zo_DimmerStep = 5690, + Zo_xx190A00 = 5701, + Zo_01 = 5710, + Zo_HueMove = 5713, + Zo_xx19 = 5721, + Zo_HueStepUp = 5726, + Zo_HueStepDown = 5736, + Zo_03xx0A00 = 5748, + Zo_HueStep = 5757, + Zo_SatMove = 5765, + Zo_SatStep = 5773, + Zo_xx190A = 5781, + Zo_ColorMove = 5788, + Zo_xxxxyyyy = 5798, + Zo_ColorStep = 5807, + Zo_ColorTempMoveUp = 5817, + Zo_01xxxx000000000000 = 5833, + Zo_ColorTempMoveDown = 5852, + Zo_03xxxx000000000000 = 5870, + Zo_ColorTempMoveStop = 5889, + Zo_00xxxx000000000000 = 5907, + Zo_ColorTempMove = 5926, + Zo_xxyyyy000000000000 = 5940, + Zo_ColorTempStepUp = 5959, + Zo_01xxxx0A0000000000 = 5975, + Zo_ColorTempStepDown = 5994, + Zo_03xxxx0A0000000000 = 6012, + Zo_ColorTempStep = 6031, + Zo_xxyyyy0A0000000000 = 6045, + Zo_ArrowClick = 6064, + Zo_ArrowHold = 6075, + Zo_ArrowRelease = 6085, + Zo_ZoneStatusChange = 6098, + Zo_xxxxyyzz = 6115, + Zo_xxyyzzzz = 6124, + Zo_AddScene = 6133, + Zo_xxyyyyzz = 6142, + Zo_StoreScene = 6151, +}; + + + + + + + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +#ifdef USE_ZIGBEE + + + + + + +enum Z_DataTypes { + Znodata = 0x00, + Zdata8 = 0x08, Zdata16, Zdata24, Zdata32, Zdata40, Zdata48, Zdata56, Zdata64, + Zbool = 0x10, + Zmap8 = 0x18, Zmap16, Zmap24, Zmap32, Zmap40, Zmap48, Zmap56, Zmap64, + Zuint8 = 0x20, Zuint16, Zuint24, Zuint32, Zuint40, Zuint48, Zuint56, Zuint64, + Zint8 = 0x28, Zint16, Zint24, Zint32, Zint40, Zint48, Zint56, Zint64, + Zenum8 = 0x30, Zenum16 = 0x31, + Zsemi = 0x38, Zsingle = 0x39, Zdouble = 0x3A, + Zoctstr = 0x41, Zstring = 0x42, Zoctstr16 = 0x43, Zstring16 = 0x44, + Arrray = 0x48, + Zstruct = 0x4C, + Zset = 0x50, Zbag = 0x51, + ZToD = 0xE0, Zdate = 0xE1, ZUTC = 0xE2, + ZclusterId = 0xE8, ZattribId = 0xE9, ZbacOID = 0xEA, + ZEUI64 = 0xF0, Zkey128 = 0xF1, + Zunk = 0xFF, + + Ztuya1 = 0x80, + Ztuya2 = 0x81, + Ztuya4 = 0x82, +}; + + + + + + +uint8_t Z_getDatatypeLen(uint8_t t) { + if ( ((t >= 0x08) && (t <= 0x0F)) || + ((t >= 0x18) && (t <= 0x2F)) ) { + return (t & 0x07) + 1; + } + switch (t) { + case Zbool: + case Zenum8: + return 1; + case Zenum16: + case Zsemi: + case ZclusterId: + case ZattribId: + case Ztuya1: + return 2; + case Ztuya2: + return 3; + case Zsingle: + case ZToD: + case Zdate: + case ZUTC: + case ZbacOID: + return 4; + case Ztuya4: + return 5; + case Zdouble: + case ZEUI64: + return 8; + case Zkey128: + return 16; + case Znodata: + default: + return 0; + } +} + + +bool Z_isDiscreteDataType(uint8_t t) { + if ( ((t >= 0x20) && (t <= 0x2F)) || + ((t >= 0x38) && (t <= 0x3A)) || + ((t >= 0xE0) && (t <= 0xE2)) ) { + return false; + } else { + return true; + } +} + +typedef struct Z_AttributeConverter { + uint8_t type; + uint8_t cluster_short; + uint16_t attribute; + uint16_t name_offset; + uint8_t multiplier_idx; + + + uint8_t mapping; + +} Z_AttributeConverter; + + +#define Z_OFFSET(c,a) (offsetof(class c, a) - sizeof(Z_Data)) +#define Z_CLASS(c) c +#define Z_MAPPING(c,a) (((((uint8_t)Z_CLASS(c)::type) & 0x0F) << 4) | Z_OFFSET(c,a)) + + + +const uint8_t Z_EXPORT_DATA = 0x80; + + + + +enum Cx_cluster_short { + Cx0000, Cx0001, Cx0002, Cx0003, Cx0004, Cx0005, Cx0006, Cx0007, + Cx0008, Cx0009, Cx000A, Cx000B, Cx000C, Cx000D, Cx000E, Cx000F, + Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100, + Cx0101, Cx0102, Cx0201, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403, + Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05, + CxEF00, CxFCCC, +}; + +const uint16_t Cx_cluster[] PROGMEM = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100, + 0x0101, 0x0102, 0x0201, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403, + 0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05, + 0xEF00, 0xFCCC, +}; + +uint16_t CxToCluster(uint8_t cx) { + if (cx < ARRAY_SIZE(Cx_cluster)) { + return pgm_read_word(&Cx_cluster[cx]); + } + return 0xFFFF; +} + +uint8_t ClusterToCx(uint16_t cluster) { + for (uint32_t i=0; iname_offset)) { continue; } + if (0 == strcasecmp_P(command, Z_strings + pgm_read_word(&converter->name_offset))) { + if (cluster) { *cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); } + if (attribute) { *attribute = pgm_read_word(&converter->attribute); } + if (multiplier) { *multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); } + if (zigbee_type) { *zigbee_type = pgm_read_byte(&converter->type); } + uint8_t conv_mapping = pgm_read_byte(&converter->mapping); + if (data_type) { *data_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4); } + if (map_offset) { *map_offset = (conv_mapping & 0x0F); } + return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&converter->name_offset)); + } + } + return nullptr; +} + + + + +const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t attr_id, + uint8_t *attr_type, int8_t *multiplier) { + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint16_t conv_attr_id = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && (conv_attr_id == attr_id)) { + if (multiplier) { *multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); } + if (attr_type) { *attr_type = pgm_read_byte(&converter->type); } + return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&converter->name_offset)); + } + } + return nullptr; +} + +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, uint16_t groupaddr, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber): + _manuf_code(manuf_code), _transact_seq(transact_seq), _cmd_id(cmd_id), + _payload(buf_len ? buf_len : 250), + _cluster_id(clusterid), _groupaddr(groupaddr), + _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), + _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber) + { + _frame_control.d8 = frame_control; + _payload.addBuffer(buf, buf_len); + }; + + + void log(void) { + 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_ZIGBEEZCL_RECEIVED "\":{" + "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," + "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," + "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," + "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), + _groupaddr, _cluster_id, _srcaddr, + _srcendpoint, _dstendpoint, _wasbroadcast, + _linkquality, _securityuse, _seqnumber, + _frame_control, _manuf_code, _transact_seq, _cmd_id, + hex_char); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + } + + static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber) { + 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, + srcaddr, srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber); + return zcl_frame; + } + + bool isClusterSpecificCommand(void) { + return _frame_control.b.frame_type & 1; + } + + void parseReportAttributes(Z_attribute_list& attr_list); + void generateSyntheticAttributes(Z_attribute_list& attr_list); + void computeSyntheticAttributes(Z_attribute_list& attr_list); + void generateCallBacks(Z_attribute_list& attr_list); + void parseReadAttributes(Z_attribute_list& attr_list); + void parseReadAttributesResponse(Z_attribute_list& attr_list); + void parseReadConfigAttributes(Z_attribute_list& attr_list); + void parseConfigAttributes(Z_attribute_list& attr_list); + void parseResponse(void); + void parseResponseOld(void); + void parseClusterSpecificCommand(Z_attribute_list& attr_list); + void postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list); + + + void syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr); + void syntheticAqaraSensor2(Z_attribute_list &attr_list, class Z_attribute &attr); + void syntheticAqaraCubeOrButton(Z_attribute_list &attr_list, class Z_attribute &attr); + void syntheticAqaraVibration(Z_attribute_list &attr_list, class Z_attribute &attr); + + + void autoResponder(const uint16_t *attr_list_ids, size_t attr_len); + + inline void setGroupId(uint16_t groupid) { + _groupaddr = groupid; + } + + inline void setClusterId(uint16_t clusterid) { + _cluster_id = clusterid; + } + + inline uint16_t getSrcAddr(void) const { return _srcaddr; } + inline uint16_t getGroupAddr(void) const { return _groupaddr; } + inline uint16_t getClusterId(void) const { return _cluster_id; } + inline uint8_t getLinkQuality(void) const { return _linkquality; } + inline uint8_t getCmdId(void) const { return _cmd_id; } + inline uint16_t getSrcEndpoint(void) const { return _srcendpoint; } + + const SBuffer &getPayload(void) const { + return _payload; + } + + uint16_t getManufCode(void) const { + return _manuf_code; + } + + +private: + ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; + uint16_t _manuf_code = 0; + uint8_t _transact_seq = 0; + uint8_t _cmd_id = 0; + SBuffer _payload; + uint16_t _cluster_id = 0; + uint16_t _groupaddr = 0; + + uint16_t _srcaddr; + uint8_t _srcendpoint; + uint8_t _dstendpoint; + uint8_t _wasbroadcast; + uint8_t _linkquality; + uint8_t _securityuse; + uint8_t _seqnumber; +}; + + + + + + +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; +} + + + + + + +int32_t encodeSingleAttribute(class SBuffer &buf, double val_d, const char *val_str, uint8_t attrtype) { + uint32_t len = Z_getDatatypeLen(attrtype); + uint32_t u32 = val_d; + int32_t i32 = val_d; + float f32 = val_d; + + switch (attrtype) { + + case Zbool: + case Zuint8: + case Zenum8: + case Zdata8: + case Zmap8: + buf.add8(u32); + break; + case Ztuya1: + buf.add8(1); + buf.add8(u32); + break; + + case Zuint16: + case Zenum16: + case Zdata16: + case Zmap16: + buf.add16(u32); + break; + case Ztuya2: + buf.add8(2); + buf.add16BigEndian(u32); + + case Zuint32: + case Zdata32: + case Zmap32: + case ZUTC: + buf.add32(u32); + break; + + + case Zint8: + buf.add8(i32); + break; + case Zint16: + buf.add16(i32); + break; + case Zint32: + buf.add32(i32); + break; + case Ztuya4: + buf.add8(4); + buf.add32BigEndian(i32); + break; + + case Zsingle: + uint32_t *f_ptr; + buf.add32( *((uint32_t*)&f32) ); + break; + + case Zstring: + case Zstring16: + { + if (nullptr == val_str) { return -2; } + size_t val_len = strlen(val_str); + if (val_len > 32) { val_len = 32; } + len = val_len + 1; + buf.add8(val_len); + if (Zstring16 == attrtype) { + buf.add8(0); + len++; + } + for (uint32_t i = 0; i < val_len; i++) { + buf.add8(val_str[i]); + } + } + break; + + default: + return -1; + } + return len; +} +# 924 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf, + uint32_t offset, int32_t attrtype = -1) { + + uint32_t i = offset; + if (attrtype < 0) { + attrtype = buf.get8(i++); + } + + + attr.setNone(); + + uint32_t len = Z_getDatatypeLen(attrtype); + + + switch (attrtype) { + + + + case Zbool: + case Zuint8: + case Zenum8: + { + uint8_t uint8_val = buf.get8(i); + + if (0xFF != uint8_val) { + attr.setUInt(uint8_val); + } + } + break; + case Zuint16: + case Zenum16: + { + uint16_t uint16_val = buf.get16(i); + + if (0xFFFF != uint16_val) { + attr.setUInt(uint16_val); + } + } + break; + case Zuint32: + case ZUTC: + { + uint32_t uint32_val = buf.get32(i); + + if (0xFFFFFFFF != uint32_val) { + attr.setUInt(uint32_val); + } + } + break; + case Ztuya1: + attr.setUInt(buf.get8(i+1)); + break; + case Ztuya2: + attr.setUInt(buf.get16BigEndian(i+1)); + break; + case Ztuya4: + attr.setInt(buf.get32IBigEndian(i+1)); + break; + + + case Zuint40: + case Zuint48: + case Zuint56: + case Zuint64: + case Zint40: + case Zint48: + case Zint56: + case Zint64: + { + + + char hex[2*len+3]; + snprintf_P(hex, sizeof(hex), PSTR("0x")); + for (uint32_t j=0; j buf.len()) { + len = buf.len() - i; + } + + + if ((Zoctstr == attrtype) || (Zoctstr16 == attrtype)) { parse_as_string = false; } + + if (parse_as_string) { + char str[len+1]; + strncpy(str, buf.charptr(i), len); + str[len] = 0x00; + attr.setStr(str); + } else { + attr.setBuf(buf, i, len); + } + + + + } + + break; + + case Zstruct: + { + uint16_t struct_size = buf.get16(i); + len = 2; + if (0xFFFF != struct_size) { + if (struct_size > 16) { struct_size = 16; } + + for (uint32_t j = 0; j < struct_size; j++) { + uint8_t attr_type = buf.get8(i+len); + len += Z_getDatatypeLen(attr_type) + 1; + } + attr.setBuf(buf, i, len); + } + } + break; + + case Zdata8: + case Zmap8: + { + uint8_t uint8_val = buf.get8(i); + + attr.setUInt(uint8_val); + } + break; + case Zdata16: + case Zmap16: + { + uint16_t uint16_val = buf.get16(i); + + attr.setUInt(uint16_val); + } + break; + case Zdata32: + case Zmap32: + { + uint32_t uint32_val = buf.get32(i); + + attr.setUInt(uint32_val); + } + break; + + case Zsingle: + { + uint32_t uint32_val = buf.get32(i); + float * float_val = (float*) &uint32_val; + + attr.setFloat(*float_val); + } + break; + + + case ZToD: + case Zdate: + case ZclusterId: + case ZattribId: + case ZbacOID: + case ZEUI64: + case Zkey128: + case Zsemi: + break; + + + case Zdata24: + case Zdata40: + case Zdata48: + case Zdata56: + case Zdata64: + break; + + case Zmap24: + case Zmap40: + case Zmap48: + case Zmap56: + case Zmap64: + break; + case Zdouble: + { + uint64_t uint64_val = buf.get64(i); + double * double_val = (double*) &uint64_val; + + attr.setFloat((float) *double_val); + } + break; + } + i += len; + + return i - offset; +} + + +void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) { + uint32_t i = 0; + uint32_t len = _payload.len(); + + while (len >= i + 3) { + uint16_t attrid = _payload.get16(i); + i += 2; + + + if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { + if (0x42 == _payload.get8(i)) { + _payload.set8(i, 0x41); + } + } + + + Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid); + + i += parseSingleAttribute(attr, _payload, i); + } + + + + if (0 == _frame_control.b.disable_def_resp) { + + SBuffer buf(2); + buf.add8(_cmd_id); + buf.add8(0x00); + + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + _srcaddr, + 0x0000, + _cluster_id, + _srcendpoint, + ZCL_DEFAULT_RESPONSE, + _manuf_code, + false , + false , + true , + _transact_seq, + buf.getBuffer(), buf.len() + })); + } +} + + + + +void ZCLFrame::generateSyntheticAttributes(Z_attribute_list& attr_list) { + + for (auto &attr : attr_list) { + if (attr.key_is_str) { continue; } + uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + + switch (ccccaaaa) { + case 0x0000FF01: + syntheticAqaraSensor(attr_list, attr); + break; + case 0x0000FF02: + syntheticAqaraSensor2(attr_list, attr); + break; + case 0x00120055: + syntheticAqaraCubeOrButton(attr_list, attr); + break; + case 0x01010055: + case 0x01010508: + syntheticAqaraVibration(attr_list, attr); + break; + } + } +} + + + + + +void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { + + for (auto &attr : attr_list) { + if (attr.key_is_str) { continue; } + uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + + switch (ccccaaaa) { + case 0x00010020: + if (attr_list.countAttribute(0x0001,0x0021) == 0) { + uint32_t mv = attr.getUInt()*100; + attr_list.addAttribute(0x0001, 0x0021).setUInt(toPercentageCR2032(mv) * 2); + } + break; + case 0x02010008: + { + const char * manufacturer_c = zigbee_devices.getManufacturerId(_srcaddr); + String manufacturerId((char*) manufacturer_c); + if (manufacturerId.equals(F("Eurotronic"))) { + + uint8_t valve = attr.getUInt(); + if (attr.isNone()) { valve = 255; } + uint8_t valve_100 = changeUIntScale(valve, 0, 255, 0, 100); + attr.setUInt(valve_100); + } + } + break; + case 0x04030000: + { + int16_t pressure = attr.getInt(); + int16_t pressure_sealevel = (pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0f), 5.255f)) - 21.6f; + attr_list.addAttribute(0x0403, 0xFFF0).setInt(pressure_sealevel); + + } + break; + } + } +} + + + +void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) { + static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; + + for (auto &attr : attr_list) { + if (attr.key_is_str) { continue; } + uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + + switch (ccccaaaa) { + case 0x04060000: + uint32_t occupancy = attr.getUInt(); + if (occupancy) { + zigbee_devices.setTimer(_srcaddr, 0 , OCCUPANCY_TIMEOUT, _cluster_id, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback); + } else { + zigbee_devices.resetTimersForDevice(_srcaddr, 0 , Z_CAT_VIRTUAL_OCCUPANCY); + } + break; + } + } +} + + + + + +void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint = 0) { + uint32_t wait_ms = 0xFFFF; + + switch (cluster) { + case 0x0006: + wait_ms = 200; + break; + case 0x0008: + wait_ms = 1050; + break; + case 0x0102: + wait_ms = 10000; + break; + case 0x0300: + wait_ms = 1050; + break; + default: + break; + } + if (0xFFFF != wait_ms) { + if ((BAD_SHORTADDR != shortaddr) && (0 == endpoint)) { + endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + } + if ((BAD_SHORTADDR == shortaddr) || (endpoint)) { + zigbee_devices.queueTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); + if (BAD_SHORTADDR != shortaddr) { + zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 , &Z_Unreachable); + } + + } + } +} + + +void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { + uint32_t i = 0; + uint32_t len = _payload.len(); + + uint16_t read_attr_ids[len/2]; + + attr_list.addAttribute(F(D_CMND_ZIGBEE_CLUSTER)).setUInt(_cluster_id); + + Z_json_array attr_numbers; + Z_attribute_list attr_names; + while (len >= 2 + i) { + uint16_t attrid = _payload.get16(i); + attr_numbers.add(attrid); + read_attr_ids[i/2] = attrid; + + + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) { + attr_names.addAttribute(Z_strings + pgm_read_word(&converter->name_offset), true).setBool(true); + break; + } + } + i += 2; + } + attr_list.addAttribute(F("Read")).setStrRaw(attr_numbers.toString().c_str()); + attr_list.addAttribute(F("ReadNames")).setStrRaw(attr_names.toString(true).c_str()); + + + autoResponder(read_attr_ids, len/2); +} + + +void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) { + uint32_t len = _payload.len(); + + Z_attribute_list attr_config_list; + for (uint32_t i=0; len >= i+4; i+=4) { + uint8_t status = _payload.get8(i); + uint16_t attr_id = _payload.get8(i+2); + + Z_attribute_list attr_config_response; + attr_config_response.addAttribute(F("Status")).setUInt(status); + attr_config_response.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); + + const __FlashStringHelper* attr_name = zigbeeFindAttributeById(_cluster_id, attr_id, nullptr, nullptr); + if (attr_name) { + attr_config_list.addAttribute(attr_name).setStrRaw(attr_config_response.toString(true).c_str()); + } else { + attr_config_list.addAttribute(_cluster_id, attr_id).setStrRaw(attr_config_response.toString(true).c_str()); + } + } + + Z_attribute &attr_1 = attr_list.addAttribute(F("ConfigResponse")); + attr_1.setStrRaw(attr_config_list.toString(true).c_str()); +} + + +void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) { + uint32_t i = 0; + uint32_t len = _payload.len(); + + Z_attribute &attr_root = attr_list.addAttribute(F("ReadConfig")); + Z_attribute_list attr_1; + + while (len >= i + 4) { + uint8_t status = _payload.get8(i); + uint8_t direction = _payload.get8(i+1); + uint16_t attrid = _payload.get16(i+2); + + Z_attribute_list attr_2; + if (direction) { + attr_2.addAttribute(F("DirectionReceived")).setBool(true); + } + + + int8_t multiplier = 1; + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) { + const char * attr_name = Z_strings + pgm_read_word(&converter->name_offset); + attr_2.addAttribute(attr_name, true).setBool(true); + multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); + break; + } + } + i += 4; + if (0 != status) { + attr_2.addAttribute(F("Status")).setUInt(status); + attr_2.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); + } else { + + if (direction) { + + uint16_t attr_timeout = _payload.get16(i); + i += 2; + attr_2.addAttribute(F("TimeoutPeriod")).setUInt((0xFFFF == attr_timeout) ? -1 : attr_timeout); + } else { + + uint8_t attr_type = _payload.get8(i); + bool attr_discrete = Z_isDiscreteDataType(attr_type); + uint16_t attr_min_interval = _payload.get16(i+1); + uint16_t attr_max_interval = _payload.get16(i+3); + i += 5; + attr_2.addAttribute(F("MinInterval")).setUInt((0xFFFF == attr_min_interval) ? -1 : attr_min_interval); + attr_2.addAttribute(F("MaxInterval")).setUInt((0xFFFF == attr_max_interval) ? -1 : attr_max_interval); + if (!attr_discrete) { + + Z_attribute &attr_change = attr_2.addAttribute(F("ReportableChange")); + i += parseSingleAttribute(attr_change, _payload, i, attr_type); + if ((1 != multiplier) && (0 != multiplier)) { + float fval = attr_change.getFloat(); + if (multiplier > 0) { fval = fval * multiplier; } + else { fval = fval / (-multiplier); } + attr_change.setFloat(fval); + } + } + } + } + attr_1.addAttribute(_cluster_id, attrid).setStrRaw(attr_2.toString(true).c_str()); + } + attr_root.setStrRaw(attr_1.toString(true).c_str()); +} + + +void ZCLFrame::parseReadAttributesResponse(Z_attribute_list& attr_list) { + uint32_t i = 0; + uint32_t len = _payload.len(); + + while (len >= i + 4) { + uint16_t attrid = _payload.get16(i); + i += 2; + uint8_t status = _payload.get8(i++); + + if (0 == status) { + Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid); + i += parseSingleAttribute(attr, _payload, i); + } + } +} + + +void ZCLFrame::parseResponse(void) { + if (_payload.len() < 2) { return; } + uint8_t cmd = _payload.get8(0); + uint8_t status = _payload.get8(1); + + Z_attribute_list attr_list; + + + char s[12]; + snprintf_P(s, sizeof(s), PSTR("0x%04X"), _srcaddr); + attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(s); + + const char * friendlyName = zigbee_devices.getFriendlyName(_srcaddr); + if (friendlyName) { + attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(friendlyName); + } + + snprintf_P(s, sizeof(s), PSTR("%04X!%02X"), _cluster_id, cmd); + attr_list.addAttribute(F(D_JSON_ZIGBEE_CMD)).setStr(s); + + attr_list.addAttribute(F(D_JSON_ZIGBEE_STATUS)).setUInt(status); + + attr_list.addAttribute(F(D_JSON_ZIGBEE_STATUS_MSG)).setStr(getZigbeeStatusMessage(status).c_str()); + + attr_list.addAttribute(F(D_CMND_ZIGBEE_ENDPOINT)).setUInt(_srcendpoint); + + if (_groupaddr) { + attr_list.group_id = _groupaddr; + } + + attr_list.lqi = _linkquality; + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RESPONSE "\":%s}"), attr_list.toString(true).c_str()); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); +} + + +void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) { + convertClusterSpecific(attr_list, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload); +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES + if (!_frame_control.b.direction) { + if (_wasbroadcast) { + sendHueUpdate(BAD_SHORTADDR, _groupaddr, _cluster_id); + } + } +#endif +} + + + +void ZCLFrame::syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr) { + const SBuffer * buf = attr.getRaw(); + if (buf) { + const SBuffer & buf2 = *buf; + uint32_t i = 0; + uint32_t len = buf2.len(); + + const char * modelId_c = zigbee_devices.getModelId(_srcaddr); + String modelId((char*) modelId_c); + + while (len >= 2 + i) { + uint8_t attrid = buf2.get8(i++); + + Z_attribute attr; + i += parseSingleAttribute(attr, buf2, i); + int32_t ival32 = attr.getInt(); + uint32_t uval32 = attr.getUInt(); + bool translated = false; + if (0x01 == attrid) { + float batteryvoltage = attr.getFloat() / 100; + attr_list.addAttribute(0x0001, 0x0020).setFloat(batteryvoltage); + uint8_t batterypercentage = toPercentageCR2032(uval32); + attr_list.addAttribute(0x0001, 0x0021).setUInt(batterypercentage * 2); + } else if ((nullptr != modelId) && (0 == getManufCode())) { + translated = true; + if (modelId.startsWith(F("lumi.sensor_ht")) || + modelId.equals(F("lumi.sens")) || + modelId.startsWith(F("lumi.weather"))) { + + + if (0x64 == attrid) { + attr_list.addAttribute(0x0402, 0x0000).setInt(ival32); + } else if (0x65 == attrid) { + attr_list.addAttribute(0x0405, 0x0000).setUInt(uval32); + } else if (0x66 == attrid) { + attr_list.addAttribute(0x0403, 0x0000).setUInt((ival32 + 50) / 100); + } + } else if (modelId.startsWith(F("lumi.sensor_smoke"))) { + if (0x64 == attrid) { + attr_list.addAttribute(F("SmokeDensity")).copyVal(attr); + } + } else if (modelId.startsWith(F("lumi.sensor_natgas"))) { + if (0x64 == attrid) { + attr_list.addAttribute(F("GasDensity")).copyVal(attr); + } + } else { + translated = false; + } + + } + if (!translated) { + if (attrid >= 100) { + char attr_name[12]; + snprintf_P(attr_name, sizeof(attr_name), PSTR("Xiaomi_%02X"), attrid); + attr_list.addAttribute(attr_name).copyVal(attr); + } + } + } + } +} + +void ZCLFrame::syntheticAqaraSensor2(class Z_attribute_list &attr_list, class Z_attribute &attr) { + const SBuffer * buf = attr.getRaw(); + if (buf) { + const SBuffer & buf2 = *buf; + uint32_t len = buf2.len(); + + + uint16_t struct_size = buf2.get16(0); + size_t struct_len = 2; + if (0xFFFF != struct_size) { + if (struct_size > 16) { struct_size = 16; } + for (uint32_t j = 0; (j < struct_size) && (struct_len < len); j++) { + uint8_t attr_type = buf2.get8(struct_len); + if (0x21 == attr_type) { + uint16_t val = buf2.get16(struct_len+1); + float batteryvoltage = (float)val / 100; + attr_list.addAttribute(0x0001, 0x0020).setFloat(batteryvoltage); + uint8_t batterypercentage = toPercentageCR2032(val); + attr_list.addAttribute(0x0001, 0x0021).setUInt(batterypercentage * 2); + break; + } + struct_len += Z_getDatatypeLen(attr_type) + 1; + } + } + } + attr_list.removeAttribute(&attr); +} + + +void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, class Z_attribute &attr) { + const char * modelId_c = zigbee_devices.findShortAddr(_srcaddr).modelId; + String modelId((char*) modelId_c); + + if (modelId.startsWith(F("lumi.sensor_cube"))) { + int32_t val = attr.getInt(); + const __FlashStringHelper *aqara_cube = F("AqaraCube"); + const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); + const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); + + switch (val) { + case 0: + attr_list.addAttribute(aqara_cube).setStr(PSTR("shake")); + break; + case 2: + attr_list.addAttribute(aqara_cube).setStr(PSTR("wakeup")); + break; + case 3: + attr_list.addAttribute(aqara_cube).setStr(PSTR("fall")); + break; + case 64 ... 127: + attr_list.addAttribute(aqara_cube).setStr(PSTR("flip90")); + attr_list.addAttribute(aqara_cube_side).setInt(val % 8); + attr_list.addAttribute(aqara_cube_from_side).setInt((val - 64) / 8); + break; + case 128 ... 132: + attr_list.addAttribute(aqara_cube).setStr(PSTR("flip180")); + attr_list.addAttribute(aqara_cube_side).setInt(val - 128); + break; + case 256 ... 261: + attr_list.addAttribute(aqara_cube).setStr(PSTR("slide")); + attr_list.addAttribute(aqara_cube_side).setInt(val - 256); + break; + case 512 ... 517: + attr_list.addAttribute(aqara_cube).setStr(PSTR("tap")); + attr_list.addAttribute(aqara_cube_side).setInt(val - 512); + break; + } + attr_list.removeAttribute(&attr); +# 1672 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + } else if (modelId.startsWith(F("lumi.remote")) || modelId.startsWith(F("lumi.sensor_switch"))) { + int32_t val = attr.getInt(); + const __FlashStringHelper *aqara_click = F("click"); + const __FlashStringHelper *aqara_action = F("action"); + + switch (val) { + case 0: + attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); + break; + case 1: + attr_list.addAttribute(aqara_click).setStr(PSTR("single")); + break; + case 2: + attr_list.addAttribute(aqara_click).setStr(PSTR("double")); + break; + case 16: + attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); + break; + case 17: + attr_list.addAttribute(aqara_action).setStr(PSTR("release")); + break; + case 18: + attr_list.addAttribute(aqara_action).setStr(PSTR("shake")); + break; + case 255: + attr_list.addAttribute(aqara_action).setStr(PSTR("release")); + break; + default: + attr_list.addAttribute(aqara_click).setUInt(val); + break; + } + } +} + + +void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class Z_attribute &attr) { + switch (attr.key.id.attr_id) { + case 0x0055: + { + int32_t ivalue = attr.getInt(); + const __FlashStringHelper * svalue; + switch (ivalue) { + case 1: svalue = F("vibrate"); break; + case 2: svalue = F("tilt"); break; + case 3: svalue = F("drop"); break; + default: svalue = F("unknown"); break; + } + attr.setStr((const char*)svalue); + } + break; + case 0x0503: + break; + case 0x0505: + break; + case 0x0508: + { + + + const SBuffer * buf = attr.getRaw(); + if (buf) { + const SBuffer & buf2 = *buf; + int16_t x, y, z; + z = buf2.get16(0); + y = buf2.get16(2); + x = buf2.get16(4); + char temp[32]; + snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", x, y, z); + attr.setStrRaw(temp); + + float X = x; + float Y = y; + float Z = z; + int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; + int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; + int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; + snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", Angle_X, Angle_Y, Angle_Z); + attr_list.addAttribute(F("AqaraAngles")).setStrRaw(temp); + } + } + break; + } +} + + +void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + Z_attribute_list attr_list; + attr_list.addAttribute(F(OCCUPANCY)).setUInt(0); + zigbee_devices.jsonPublishNow(shortaddr, attr_list); +} + + +void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list) { + + uint8_t src_ep = _srcendpoint; + + for (auto &attr : attr_list) { + + if (!attr.key_is_str) { + uint16_t cluster = attr.key.id.cluster; + uint16_t attribute = attr.key.id.attr_id; + uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; + Z_Device & device = zigbee_devices.getShortAddr(shortaddr); + + + bool found = false; + const char * conv_name; + Z_Data_Type map_type; + uint8_t map_offset; + uint8_t zigbee_type; + int8_t conv_multiplier; + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && + ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { + conv_multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); + zigbee_type = pgm_read_byte(&converter->type); + uint8_t mapping = pgm_read_byte(&converter->mapping); + map_type = (Z_Data_Type) ((mapping & 0xF0)>>4); + map_offset = (mapping & 0x0F); + conv_name = Z_strings + pgm_read_word(&converter->name_offset); + found = true; + break; + } + } + + float fval = attr.getFloat(); + if (found && (map_type != Z_Data_Type::Z_Unknown)) { + + + + + + Z_Data & data = device.data.getByType(map_type, src_ep); + uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + map_offset; + uint32_t uval32 = attr.getUInt(); + int32_t ival32 = attr.getInt(); + + switch (zigbee_type) { + case Zenum8: + case Zuint8: *(uint8_t*)attr_address = uval32; break; + case Zenum16: + case Zuint16: *(uint16_t*)attr_address = uval32; break; + case Zuint32: *(uint32_t*)attr_address = uval32; break; + case Zint8: *(int8_t*)attr_address = ival32; break; + case Zint16: *(int16_t*)attr_address = ival32; break; + case Zint32: *(int32_t*)attr_address = ival32; break; + } + } + + uint16_t uval16 = attr.getUInt(); + int16_t ival16 = attr.getInt(); + Z_Data_Set & data = device.data; + + switch (ccccaaaa) { + case 0x00000004: zigbee_devices.setManufId(shortaddr, attr.getStr()); break; + case 0x00000005: zigbee_devices.setModelId(shortaddr, attr.getStr()); break; + case 0x00010021: zigbee_devices.setBatteryPercent(shortaddr, uval16 / 2); break; + case 0x00060000: + case 0x00068000: device.setPower(attr.getBool(), src_ep); break; + } + + + if (found) { + if (0 == conv_multiplier) { attr_list.removeAttribute(&attr); continue; } + if (1 != conv_multiplier) { + if (conv_multiplier > 0) { fval = fval * conv_multiplier; } + else { fval = fval / (-conv_multiplier); } + attr.setFloat(fval); + } + } + + + if (found) { + if (0x00 != pgm_read_byte(conv_name)) { + attr.setKeyName(conv_name, true); + } + } + } + } +} +# 1872 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +bool Z_parseAttributeKey(class Z_attribute & attr) { + + + if (attr.key_is_str) { + const char * key = attr.key.key; + char * delimiter = strchr(key, '/'); + char * delimiter2 = strchr(key, '%'); + if (delimiter) { + uint16_t attr_id = 0xFFFF; + uint16_t cluster_id = 0xFFFF; + uint8_t type_id = Zunk; + + cluster_id = strtoul(key, &delimiter, 16); + if (!delimiter2) { + attr_id = strtoul(delimiter+1, nullptr, 16); + } else { + attr_id = strtoul(delimiter+1, &delimiter2, 16); + type_id = strtoul(delimiter2+1, nullptr, 16); + } + attr.setKeyId(cluster_id, attr_id); + attr.attr_type = type_id; + } + } + + + + if (Zunk == attr.attr_type) { + + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + bool match = false; + uint16_t local_attr_id = pgm_read_word(&converter->attribute); + uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); + uint8_t local_type_id = pgm_read_byte(&converter->type); + int8_t local_multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); + + + if (!attr.key_is_str) { + if ((attr.key.id.cluster == local_cluster_id) && (attr.key.id.attr_id == local_attr_id)) { + attr.attr_type = local_type_id; + break; + } + } else if (pgm_read_word(&converter->name_offset)) { + const char * key = attr.key.key; + + if (0 == strcasecmp_P(key, Z_strings + pgm_read_word(&converter->name_offset))) { + + attr.setKeyId(local_cluster_id, local_attr_id); + attr.attr_type = local_type_id; + attr.attr_multiplier = local_multiplier; + break; + } + } + } + } + return (Zunk != attr.attr_type) ? true : false; +} + + + + + + +void Z_Data::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { + + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint8_t conv_export = pgm_read_byte(&converter->multiplier_idx) & Z_EXPORT_DATA; + uint8_t conv_mapping = pgm_read_byte(&converter->mapping); + Z_Data_Type map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4); + uint8_t map_offset = (conv_mapping & 0x0F); + + if ((conv_export != 0) && (map_type == type)) { + + const char * conv_name = Z_strings + pgm_read_word(&converter->name_offset); + uint8_t zigbee_type = pgm_read_byte(&converter->type); + uint8_t *attr_address = ((uint8_t*)this) + sizeof(Z_Data) + map_offset; + + int32_t data_size = 0; + int32_t ival32; + uint32_t uval32; + switch (zigbee_type) { + case Zenum8: + case Zuint8: uval32 = *(uint8_t*)attr_address; if (uval32 != 0xFF) data_size = 8; break; + case Zenum16: + case Zuint16: uval32 = *(uint16_t*)attr_address; if (uval32 != 0xFFFF) data_size = 16; break; + case Zuint32: uval32 = *(uint32_t*)attr_address; if (uval32 != 0xFFFFFFFF) data_size = 32; break; + case Zint8: ival32 = *(int8_t*)attr_address; if (ival32 != -0x80) data_size = -8; break; + case Zint16: ival32 = *(int16_t*)attr_address; if (ival32 != -0x8000) data_size = -16; break; + case Zint32: ival32 = *(int32_t*)attr_address; if (ival32 != -0x80000000) data_size = -32; break; + } + if (data_size != 0) { + Z_attribute & attr = attr_list.addAttribute(conv_name); + + if (data_size > 0) { attr.setUInt(uval32); } + else { attr.setInt(ival32); } + } + } + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +#ifdef USE_ZIGBEE + + + + + +typedef struct Z_CommandConverter { + uint16_t tasmota_cmd_offset; + uint16_t cluster; + uint8_t cmd; + uint8_t direction; + uint16_t param_offset; +} Z_CommandConverter; + +typedef struct Z_XYZ_Var { + uint32_t x = 0; + uint32_t y = 0; + uint32_t z = 0; + uint8_t x_type = 0; + uint8_t y_type = 0; + uint8_t z_type = 0; +} Z_XYZ_Var; +# 50 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +const Z_CommandConverter Z_Commands[] PROGMEM = { + + { Z_(Identify), 0x0003, 0x00, 0x01, Z_(xxxx) }, + { Z_(IdentifyQuery), 0x0003, 0x01, 0x01, Z_() }, + + { Z_(AddGroup), 0x0004, 0x00, 0x01, Z_(xxxx00) }, + { Z_(ViewGroup), 0x0004, 0x01, 0x01, Z_(xxxx) }, + { Z_(GetGroup), 0x0004, 0x02, 0x01, Z_(01xxxx) }, + { Z_(GetAllGroups), 0x0004, 0x02, 0x01, Z_(00) }, + { Z_(RemoveGroup), 0x0004, 0x03, 0x01, Z_(xxxx) }, + { Z_(RemoveAllGroups),0x0004, 0x04, 0x01, Z_() }, + + + { Z_(ViewScene), 0x0005, 0x01, 0x01, Z_(xxxxyy) }, + { Z_(RemoveScene), 0x0005, 0x02, 0x01, Z_(xxxxyy) }, + { Z_(RemoveAllScenes),0x0005, 0x03, 0x01, Z_(xxxx) }, + { Z_(RecallScene), 0x0005, 0x05, 0x01, Z_(xxxxyy) }, + { Z_(GetSceneMembership),0x0005, 0x06, 0x01, Z_(xxxx) }, + + { Z_(PowerOffEffect), 0x0006, 0x40, 0x81, Z_(xxyy) }, + { Z_(PowerOnRecall), 0x0006, 0x41, 0x81, Z_() }, + { Z_(PowerOnTimer), 0x0006, 0x42, 0x81, Z_(xxyyyyzzzz) }, + { Z_(Power), 0x0006, 0xFF, 0x01, Z_() }, + { Z_(Dimmer), 0x0008, 0x04, 0x01, Z_(xx0A00) }, + { Z_(DimmerUp), 0x0008, 0x06, 0x01, Z_(00190200) }, + { Z_(DimmerDown), 0x0008, 0x06, 0x01, Z_(01190200) }, + { Z_(DimmerStop), 0x0008, 0x03, 0x01, Z_() }, + { Z_(ResetAlarm), 0x0009, 0x00, 0x01, Z_(xxyyyy) }, + { Z_(ResetAllAlarms), 0x0009, 0x01, 0x01, Z_() }, + { Z_(Hue), 0x0300, 0x00, 0x01, Z_(xx000A00) }, + { Z_(Sat), 0x0300, 0x03, 0x01, Z_(xx0A00) }, + { Z_(HueSat), 0x0300, 0x06, 0x01, Z_(xxyy0A00) }, + { Z_(Color), 0x0300, 0x07, 0x01, Z_(xxxxyyyy0A00) }, + { Z_(CT), 0x0300, 0x0A, 0x01, Z_(xxxx0A00) }, + { Z_(ShutterOpen), 0x0102, 0x00, 0x01, Z_() }, + { Z_(ShutterClose), 0x0102, 0x01, 0x01, Z_() }, + { Z_(ShutterStop), 0x0102, 0x02, 0x01, Z_() }, + { Z_(ShutterLift), 0x0102, 0x05, 0x01, Z_(xx) }, + { Z_(ShutterTilt), 0x0102, 0x08, 0x01, Z_(xx) }, + { Z_(Shutter), 0x0102, 0xFF, 0x01, Z_() }, + + { Z_(Occupancy), 0xEF00, 0x01, 0x82, Z_()}, + + { Z_(Dimmer), 0x0008, 0x00, 0x01, Z_(xx) }, + { Z_(DimmerMove), 0x0008, 0x01, 0x01, Z_(xx0A) }, + { Z_(DimmerStepUp), 0x0008, 0x02, 0x01, Z_(00xx0A00) }, + { Z_(DimmerStepDown), 0x0008, 0x02, 0x01, Z_(01xx0A00) }, + { Z_(DimmerStep), 0x0008, 0x02, 0x01, Z_(xx190A00) }, + { Z_(DimmerMove), 0x0008, 0x05, 0x01, Z_(xx0A) }, + { Z_(DimmerUp), 0x0008, 0x06, 0x01, Z_(00) }, + { Z_(DimmerDown), 0x0008, 0x06, 0x01, Z_(01) }, + { Z_(DimmerStop), 0x0008, 0x07, 0x01, Z_() }, + { Z_(HueMove), 0x0300, 0x01, 0x01, Z_(xx19) }, + { Z_(HueStepUp), 0x0300, 0x02, 0x01, Z_(01xx0A00) }, + { Z_(HueStepDown), 0x0300, 0x02, 0x01, Z_(03xx0A00) }, + { Z_(HueStep), 0x0300, 0x02, 0x01, Z_(xx190A00) }, + { Z_(SatMove), 0x0300, 0x04, 0x01, Z_(xx19) }, + { Z_(SatStep), 0x0300, 0x05, 0x01, Z_(xx190A) }, + { Z_(ColorMove), 0x0300, 0x08, 0x01, Z_(xxxxyyyy) }, + { Z_(ColorStep), 0x0300, 0x09, 0x01, Z_(xxxxyyyy0A00) }, + { Z_(ColorTempMoveUp), 0x0300, 0x4B, 0x01, Z_(01xxxx000000000000) }, + { Z_(ColorTempMoveDown),0x0300, 0x4B, 0x01, Z_(03xxxx000000000000) }, + { Z_(ColorTempMoveStop),0x0300, 0x4B, 0x01, Z_(00xxxx000000000000) }, + { Z_(ColorTempMove), 0x0300, 0x4B, 0x01, Z_(xxyyyy000000000000) }, + { Z_(ColorTempStepUp), 0x0300, 0x4C, 0x01, Z_(01xxxx0A0000000000) }, + { Z_(ColorTempStepDown),0x0300, 0x4C, 0x01, Z_(03xxxx0A0000000000) }, + { Z_(ColorTempStep), 0x0300, 0x4C, 0x01, Z_(xxyyyy0A0000000000) }, + + { Z_(ArrowClick), 0x0005, 0x07, 0x01, Z_(xx) }, + { Z_(ArrowHold), 0x0005, 0x08, 0x01, Z_(xx) }, + { Z_(ArrowRelease), 0x0005, 0x09, 0x01, Z_() }, + + { Z_(IdentifyQuery), 0x0003, 0x00, 0x02, Z_(xxxx) }, + + { Z_(ZoneStatusChange),0x0500, 0x00, 0x82, Z_(xxxxyyzz) }, + + { Z_(AddGroup), 0x0004, 0x00, 0x82, Z_(xxyyyy) }, + { Z_(ViewGroup), 0x0004, 0x01, 0x82, Z_(xxyyyy) }, + { Z_(GetGroup), 0x0004, 0x02, 0x82, Z_(xxyyzzzz) }, + { Z_(RemoveGroup), 0x0004, 0x03, 0x82, Z_(xxyyyy) }, + + { Z_(AddScene), 0x0005, 0x00, 0x82, Z_(xxyyyyzz) }, + { Z_(ViewScene), 0x0005, 0x01, 0x82, Z_(xxyyyyzz) }, + { Z_(RemoveScene), 0x0005, 0x02, 0x82, Z_(xxyyyyzz) }, + { Z_(RemoveAllScenes),0x0005, 0x03, 0x82, Z_(xxyyyy) }, + { Z_(StoreScene), 0x0005, 0x04, 0x82, Z_(xxyyyyzz) }, + { Z_(GetSceneMembership),0x0005, 0x06, 0x82,Z_(xxyyzzzz) }, + + { Z_(), 0xEF00, 0xFF, 0x83, Z_() }, + + { Z_(), 0xFCCC, 0x00, 0x82, Z_(xxyy) }, +}; + + + + +#define ZLE(x) ((x) & 0xFF), ((x) >> 8) + + +const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007), ZLE(0x0008) }; + + +void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + size_t attrs_len = 0; + const uint8_t* attrs = nullptr; + + switch (cluster) { + case 0x0006: + attrs = CLUSTER_0006; + attrs_len = sizeof(CLUSTER_0006); + break; + case 0x0008: + attrs = CLUSTER_0008; + attrs_len = sizeof(CLUSTER_0008); + break; + case 0x0009: + attrs = CLUSTER_0009; + attrs_len = sizeof(CLUSTER_0009); + break; + case 0x0300: + attrs = CLUSTER_0300; + attrs_len = sizeof(CLUSTER_0300); + break; + } + if (attrs) { + if (groupaddr) { + shortaddr = BAD_SHORTADDR; + } + uint8_t seq = zigbee_devices.getNextSeqNumber(shortaddr); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + groupaddr, + cluster , + endpoint, + ZCL_READ_ATTRIBUTES, + 0, + false , + true , + false , + seq, + attrs, attrs_len + })); + } +} + + + +void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + if (BAD_SHORTADDR != shortaddr) { + zigbee_devices.setReachable(shortaddr, false); + } +} + + +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + + + + +inline int8_t hexValue(char c) { + if ((c >= '0') && (c <= '9')) { + return c - '0'; + } + if ((c >= 'A') && (c <= 'F')) { + return 10 + c - 'A'; + } + if ((c >= 'a') && (c <= 'f')) { + return 10 + c - 'a'; + } + return -1; +} + + +uint32_t parseHex_P(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(pgm_read_byte(*data)); + if (v < 0) { break; } + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + + + + + +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { + const char *p = model; + uint32_t v = 0; + char c = pgm_read_byte(p); + while (c) { + char c1 = pgm_read_byte(p+1); + if (!c1) { break; } + if (isXYZ(c) && (c == c1) && (v < payload.len())) { + uint8_t val = payload.get8(v); + switch (c) { + case 'x': + xyz->x = xyz->x | (val << (xyz->x_type * 8)); + xyz->x_type++; + break; + case 'y': + xyz->y = xyz->y | (val << (xyz->y_type * 8)); + xyz->y_type++; + break; + case 'z': + xyz->z = xyz->z | (val << (xyz->z_type * 8)); + xyz->z_type++; + break; + } + } + p += 2; + v++; + c = pgm_read_byte(p); + } +} + + + +void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload) { + const char * command_name = nullptr; + uint8_t conv_direction; + Z_XYZ_Var xyz; + + + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + uint16_t conv_cluster = pgm_read_word(&conv->cluster); + if (conv_cluster == cluster) { + + uint8_t conv_cmd = pgm_read_byte(&conv->cmd); + conv_direction = pgm_read_byte(&conv->direction); + if ((0xFF == conv_cmd) || (cmd == conv_cmd)) { + + if ((direction && (conv_direction & 0x02)) || (!direction && (conv_direction & 0x01))) { + + + + + const char * p = Z_strings + pgm_read_word(&conv->param_offset); + + bool match = true; + for (uint8_t i = 0; i < payload.len(); i++) { + const char c1 = pgm_read_byte(p); + const char c2 = pgm_read_byte(p+1); + + if ((0x00 == c1) || isXYZ(c1)) { + break; + } + const char * p2 = p; + uint32_t nextbyte = parseHex_P(&p2, 2); + + if (nextbyte != payload.get8(i)) { + match = false; + break; + } + p += 2; + } + if (match) { + command_name = Z_strings + pgm_read_word(&conv->tasmota_cmd_offset); + parseXYZ(Z_strings + pgm_read_word(&conv->param_offset), payload, &xyz); + if (0xFF == conv_cmd) { + + xyz.z = xyz.y; + xyz.z_type = xyz.y_type; + xyz.y = xyz.x; + xyz.y_type = xyz.x_type; + xyz.x = cmd; + xyz.x_type = 1; + } + break; + } + } + } + } + } + + + + + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); + Z_attribute & attr_raw = attr_list.addAttribute(attrid_str); + attr_raw.setBuf(payload, 0, payload.len()); + + if (command_name) { + + + if (conv_direction & 0x80) { + uint32_t cccc00mm = (cluster << 16) | cmd; + + switch (cccc00mm) { + case 0x05000000: + attr_list.addAttribute(command_name, true).setUInt(xyz.x); + if (0 != xyz.y) { + attr_list.addAttribute(command_name, PSTR("Ext")).setUInt(xyz.y); + } + if ((0 != xyz.z) && (0xFF != xyz.z)) { + attr_list.addAttribute(command_name, PSTR("Zone")).setUInt(xyz.z); + } + + + + attr_list.addAttribute(0x0406, 0x0000).setUInt((xyz.x) & 0x01 ? 1 : 0); + break; + case 0x00040000: + case 0x00040001: + case 0x00040003: + attr_list.addAttribute(command_name, true).setUInt(xyz.y); + attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); + attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); + break; + case 0x00040002: + attr_list.addAttribute(command_name, PSTR("Capacity")).setUInt(xyz.x); + attr_list.addAttribute(command_name, PSTR("Count")).setUInt(xyz.y); + { + + Z_json_array group_list; + for (uint32_t i = 0; i < xyz.y; i++) { + group_list.add(payload.get16(2 + 2*i)); + } + attr_list.addAttribute(command_name, true).setStrRaw(group_list.toString().c_str()); + } + break; + case 0x00050000: + case 0x00050001: + case 0x00050002: + case 0x00050004: + attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); + attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); + attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.y); + attr_list.addAttribute(PSTR("SceneId"), true).setUInt(xyz.z); + if (0x00050001 == cccc00mm) { + attr_list.addAttribute(PSTR("ScenePayload"), true).setBuf(payload, 4, payload.len()-4); + } + break; + case 0x00050003: + attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); + attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); + attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.y); + break; + case 0x00050006: + attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); + attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); + attr_list.addAttribute(PSTR("Capacity"), true).setUInt(xyz.y); + attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.z); + attr_list.addAttribute(PSTR("ScenePayload"), true).setBuf(payload, 4, payload.len()-4); + break; + case 0x00060040: + attr_list.addAttribute(PSTR("Power"), true).setUInt(0); + attr_list.addAttribute(PSTR("PowerEffect"), true).setUInt(xyz.x); + attr_list.addAttribute(PSTR("PowerEffectVariant"), true).setUInt(xyz.y); + break; + case 0x00060041: + attr_list.addAttribute(PSTR("Power"), true).setUInt(1); + attr_list.addAttribute(PSTR("PowerRecallGlobalScene"), true).setBool(true); + break; + case 0x00060042: + attr_list.addAttribute(PSTR("Power"), true).setUInt(1); + attr_list.addAttribute(PSTR("PowerOnlyWhenOn"), true).setUInt(xyz.x); + attr_list.addAttribute(PSTR("PowerOnTime"), true).setFloat(xyz.y / 10.0f); + attr_list.addAttribute(PSTR("PowerOffWait"), true).setFloat(xyz.z / 10.0f); + break; + case 0xEF000000 ... 0xEF0000FF: + if (convertTuyaSpecificCluster(attr_list, cluster, cmd, direction, shortaddr, srcendpoint, payload)) { + attr_list.removeAttribute(&attr_raw); + } + break; + case 0xFCCC0000: + attr_list.addAttribute(PSTR("TerncyPress"), true).setUInt(xyz.y); + attr_list.addAttribute(PSTR("TerncyCount"), true).setUInt(xyz.x); + break; + } + } else { + + char command_suffix[4] = { 0x00 }; + + if (Settings.flag4.zb_index_ep) { + if (zigbee_devices.countEndpoints(shortaddr) > 0) { + snprintf_P(command_suffix, sizeof(command_suffix), PSTR("%d"), srcendpoint); + } + } + if (0 == xyz.x_type) { + attr_list.addAttribute(command_name, command_suffix).setBool(true); + } else if (0 == xyz.y_type) { + attr_list.addAttribute(command_name, command_suffix).setUInt(xyz.x); + } else { + + Z_json_array arr; + arr.add(xyz.x); + arr.add(xyz.y); + if (xyz.z_type) { + arr.add(xyz.z); + } + attr_list.addAttribute(command_name, command_suffix).setStrRaw(arr.toString().c_str()); + } + } + } +} + + + + + + +bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf) { + + + uint16_t dp = buf.get16(2); + + uint8_t len = buf.get8(5); + + if ((1 == cmd) || (2 == cmd)) { + + Z_attribute & attr = attr_list.addAttribute(cluster, dp); + uint8_t attr_type; + switch (len) { + case 1: attr_type = Ztuya1; break; + case 2: attr_type = Ztuya2; break; + case 4: attr_type = Ztuya4; break; + default: attr_type = Zoctstr; break; + } + parseSingleAttribute(attr, buf, 5, attr_type); + return true; + } + return false; +} + + + + + +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { + if (nullptr == command) { return nullptr; } + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + uint8_t conv_direction = pgm_read_byte(&conv->direction); + uint8_t conv_cmd = pgm_read_byte(&conv->cmd); + uint16_t conv_cluster = pgm_read_word(&conv->cluster); + if ((conv_direction & 0x01) && (0 == strcasecmp_P(command, Z_strings + pgm_read_word(&conv->tasmota_cmd_offset)))) { + *cluster = conv_cluster; + *cmd = conv_cmd; + return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&conv->param_offset)); + } + } + + return nullptr; +} + + +inline char hexDigit(uint32_t h) { + uint32_t nybble = h & 0x0F; + return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; +} + + +String zigbeeCmdAddParams(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); + + char *p = zcl_cmd; + while (*p) { + if (isXYZ(*p) && (*p == *(p+1))) { + 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); +} + +const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" + "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" + "TOGGLE|" D_TOGGLE "|" + "ALL" ; + +const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, + 1,1,1,1,1, + 2,2, + 255 }; + + +uint32_t ZigbeeAliasOrNumber(const char *state_text) { + char command[16]; + int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); + if (state_number >= 0) { + + return pgm_read_byte(kZ_Numbers + state_number); + } else { + + return strtoul(state_text, nullptr, 0); + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +#ifdef USE_ZIGBEE + + + +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_PERMITJOIN_ERROR = 23; +const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; +const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; +const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; +const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; +const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; +const uint8_t ZIGBEE_STATUS_SCANNING = 40; +const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; +const uint8_t ZIGBEE_STATUS_CC_INFO = 51; +const uint8_t ZIGBEE_STATUS_EZ_VERSION = 55; +const uint8_t ZIGBEE_STATUS_EZ_INFO = 56; +const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; +const uint8_t ZIGBEE_STATUS_ABORT = 99; + +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_STATE, + ZGB_INSTR_SEND, + ZGB_INSTR_WAIT_UNTIL, + ZGB_INSTR_WAIT_RECV, + ZGB_ON_RECV_UNEXPECTED, + + + ZGB_INSTR_12_BYTES = 0xF0, + ZGB_INSTR_WAIT_UNTIL_CALL, + 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_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (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_UNTIL_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_UNTIL_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, +#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) }, + + + + + +#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 ZBR(n,x...) uint8_t n[] = { x }; +#define ZBW(n,x...) { const uint8_t n ##t[] = { x }; memcpy(n, n ##t, sizeof(n)); } + +#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) + +const char kCheckingDeviceConfiguration[] PROGMEM = D_LOG_ZIGBEE "checking device configuration"; +const char kConfiguredCoord[] PROGMEM = "Configured, starting coordinator"; +const char kConfiguredRouter[] PROGMEM = "Configured, starting router"; +const char kConfiguredDevice[] PROGMEM = "Configured, starting device"; +const char kStarted[] PROGMEM = "Started"; +const char kZigbeeStarted[] PROGMEM = D_LOG_ZIGBEE "Zigbee started"; +const char kResetting[] PROGMEM = "Resetting configuration"; +const char kResettingDevice[] PROGMEM = D_LOG_ZIGBEE "Resetting EZSP device"; +const char kReconfiguringDevice[] PROGMEM = D_LOG_ZIGBEE "Factory reset EZSP device"; +const char kZNP12[] PROGMEM = "Only ZNP 1.2 is currently supported"; +const char kEZ8[] PROGMEM = "Only EZSP protocol v8 is currently supported"; +const char kAbort[] PROGMEM = "Abort"; +const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort"; +const char kZigbeeGroup0[] PROGMEM = D_LOG_ZIGBEE "Subscribe to group 0 'ZbListen0 0'"; + +#ifdef USE_ZIGBEE_ZNP + + + +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 ) +ZBR(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PANID, 0x02 , + 0x00, 0x00 ) + +ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) +ZBR(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_EXTENDED_PAN_ID, + 0x08 , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ) + +ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) +ZBR(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 ) +ZBR(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, + 0x10 , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + ) + +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(ZBS_LOGTYPE, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_LOGICAL_TYPE ) +ZBM(ZBS_LOGTYPE_COORD, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, + 0x01 , 0x00 ) +ZBM(ZBS_LOGTYPE_ROUTER, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, + 0x01 , 0x01 ) +ZBM(ZBS_LOGTYPE_DEVICE, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, + 0x01 , 0x02 ) + + + + +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 , 0x03 ) + +ZBR(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , 0x00, 0x00 ) + +ZBR(ZBS_W_ALL_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(0xFFFF), Z_B1(0xFFFF) ) + +ZBR(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ) + +ZBR(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), + ) + +const uint32_t ZB_ALL_CHANNELS = 0x07FFF800; +ZBR(ZBS_W_ALL_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , + Z_B0(ZB_ALL_CHANNELS), Z_B1(ZB_ALL_CHANNELS), Z_B2(ZB_ALL_CHANNELS), Z_B3(ZB_ALL_CHANNELS), + ) + +ZBM(ZBS_W_LOGTYP_COORD, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) + +ZBM(ZBS_W_LOGTYP_ROUTER, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x01 ) + +ZBM(ZBS_W_LOGTYP_DEVICE, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x02 ) + +ZBR(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ) + +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 ) +ZBM(AREQ_STARTUPFROMAPP_COORD, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) +ZBM(AREQ_STARTUPFROMAPP_ROUTER, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ROUTER ) +ZBM(AREQ_STARTUPFROMAPP_DEVICE, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_END_DEVICE ) + +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 ) +# 270 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.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_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) +# 288 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.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_AF_REGISTER_ALL, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x0E , + 0x00,0x00, 0x04,0x00, 0x05,0x00, 0x06,0x00, + 0x07,0x00, 0x08,0x00, 0x0A,0x00, 0x02,0x01, + 0x00,0x03, 0x00,0x04, 0x02,0x04, 0x03,0x04, + 0x05,0x04, 0x06,0x04, + 0x00 ) + + +ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , + 0x00, 0x00 , 0x00 , 0x00 ) +ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_SUCCESS) +ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_SUCCESS ) + + +void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) { + uint32_t zb_channel_mask = (1 << zb_channel); + + ZBW(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PANID, 0x02 , + Z_B0(zb_pan_id), Z_B1(zb_pan_id) ) + + ZBW(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_EXTENDED_PAN_ID, + 0x08 , + Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), + Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), + ) + + ZBW(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_CHANLIST, + 0x04 , + Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask), + ) + + ZBW(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, + 0x10 , + Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), + Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), + Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), + Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), + + ) + + ZBW(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(zb_pan_id), Z_B1(zb_pan_id) ) + + ZBW(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , + Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), + Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid) + ) + + ZBW(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , + Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask), + ) + + ZBW(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 , + Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), + Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), + Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), + Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), + ) +} + +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(&ZNP_Recv_Default) + ZI_WAIT(10500) + + + ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting CC2530 device") + + ZI_CALL(&ZNP_Reset_Device, 0) + ZI_WAIT(100) + ZI_CALL(&ZNP_Reset_Device, 1) + ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &ZNP_Reboot) + ZI_WAIT(100) + ZI_LOG(LOG_LEVEL_DEBUG, kCheckingDeviceConfiguration) + ZI_SEND(ZBS_VERSION) + ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &ZNP_ReceiveCheckVersion) + + + ZI_CALL(&Z_SwitchDeviceType, 0) + + + + + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_COORD) + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + + ZI_SEND(ZBS_LOGTYPE) + ZI_WAIT_RECV(1000, ZBS_LOGTYPE_COORD) + 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_COORD) + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + + ZI_SEND(ZBS_STARTUPFROMAPP) + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) + ZI_WAIT_UNTIL_FUNC(10000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) + ZI_SEND(ZBS_GETDEVICEINFO) + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo) + + ZI_SEND(ZBS_ZDO_NODEDESCREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) + ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) + 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_STATE(ZIGBEE_STATUS_OK, kStarted) + ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted) + ZI_CALL(&Z_State_Ready, 1) + ZI_CALL(&Z_Load_Devices, 0) + ZI_CALL(&Z_Query_Bulbs, 0) + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_COORD) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) + + 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_COORD) + 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, &ZNP_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + + ZI_GOTO(ZIGBEE_LABEL_START_COORD) + + + + + ZI_LABEL(ZIGBEE_LABEL_INIT_ROUTER) + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_ROUTER) + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_SEND(ZBS_LOGTYPE) + ZI_WAIT_RECV(1000, ZBS_LOGTYPE_ROUTER) + + + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredRouter) + ZI_LABEL(ZIGBEE_LABEL_START_ROUTER_DEVICE) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_SEND(ZBS_AF_REGISTER_ALL) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + ZI_SEND(ZBS_STARTUPFROMAPP) + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) + ZI_WAIT_UNTIL_FUNC(0xFFFF, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) + ZI_SEND(ZBS_GETDEVICEINFO) + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo) + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_ROUTER) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) + 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_LOGTYP_ROUTER) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST) + ZI_SEND(ZBS_W_ALL_PAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_ALL_CHANN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + + + ZI_SEND(ZBS_WNV_INITZNPHC) + ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &ZNP_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + ZI_GOTO(ZIGBEE_LABEL_START_ROUTER_DEVICE) + + + + + ZI_LABEL(ZIGBEE_LABEL_INIT_DEVICE) + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_DEVICE) + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_SEND(ZBS_LOGTYPE) + ZI_WAIT_RECV(1000, ZBS_LOGTYPE_DEVICE) + + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredDevice) + ZI_GOTO(ZIGBEE_LABEL_START_ROUTER_DEVICE) + + ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_DEVICE) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) + 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_LOGTYP_DEVICE) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_GOTO(ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST) + + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kZNP12) + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + + ZI_LABEL(ZIGBEE_LABEL_ABORT) + ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, kAbort) + ZI_LOG(LOG_LEVEL_ERROR, kZigbeeAbort) + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +#endif + +#ifdef USE_ZIGBEE_EZSP + + + + +ZBM(ZBR_RSTACK, Z_B0(EZSP_rstAck), Z_B1(EZSP_rstAck)) + + +ZBM(ZBS_VERSION, EZSP_version, 0x00, 0x08) +ZBM(ZBR_VERSION, EZSP_version, 0x00, 0x08, 0x02) + + + +ZBM(ZBS_SET_ADDR_TABLE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_KEY_TABLE_SIZE, 0x02, 0x00) +ZBM(ZBS_SET_MCAST_TABLE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_MULTICAST_TABLE_SIZE, 0x10, 0x00) +ZBM(ZBS_SET_STK_PROF, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_STACK_PROFILE, 0x02, 0x00) +ZBM(ZBS_SET_SEC_LEVEL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SECURITY_LEVEL, 0x05, 0x00) +ZBM(ZBS_SET_MAX_DEVICES, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_MAX_END_DEVICE_CHILDREN, 0x20, 0x00) +ZBM(ZBS_SET_INDIRECT_TMO, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT, 0x00, 0x1E) +ZBM(ZBS_SET_TC_CACHE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE, 0x02, 0x00) +ZBM(ZBS_SET_ROUTE_TBL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE, 0x10, 0x00) +ZBM(ZBS_SET_KEY_TBL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_KEY_TABLE_SIZE, 0x04, 0x00) +ZBM(ZBS_SET_PANID_CNFLCT, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD, 0x02, 0x00) +ZBM(ZBS_SET_ZDO_REQ, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_APPLICATION_ZDO_FLAGS, EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS | EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS, 0x00) +ZBM(ZBS_SET_NETWORKS, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SUPPORTED_NETWORKS, 0x01, 0x00) +ZBM(ZBS_SET_PACKET_BUF, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_PACKET_BUFFER_COUNT, 0xFF, 0x00) + +ZBM(ZBR_SET_OK, EZSP_setConfigurationValue, 0x00 , 0x00 ) + + +ZBR(ZBR_SET_OK2, EZSP_setConfigurationValue, 0x00 , 0x00 ) + + + + + + +ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 , 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , + 0x00 , + 0X00 , + + + + + ) +ZBM(ZBS_ADD_ENDPOINTB, EZSP_addEndpoint, 0x00 , 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , + 0x00 , + 0X00 , + + + + + ) +ZBM(ZBR_ADD_ENDPOINT, EZSP_addEndpoint, 0x00 , 0x00 ) + + +ZBM(ZBS_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 , 0x00 , 0xF9,0xFF , + 0x58,0x02 , 0x08,0x07 , 0x02 , 0x05 , 0x00 ) +ZBM(ZBR_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 , 0x00 ) + + +#define EZ_SECURITY_MODE EMBER_TRUST_CENTER_GLOBAL_LINK_KEY | EMBER_PRECONFIGURED_NETWORK_KEY_MODE | EMBER_HAVE_NETWORK_KEY | EMBER_HAVE_PRECONFIGURED_KEY +ZBR(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , + Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE), + + 0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + ) +ZBM(ZBR_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , 0x00 ) + + +ZBM(ZBS_SET_POLICY_00, EZSP_setPolicy, 0x00 , EZSP_TRUST_CENTER_POLICY, + EZSP_DECISION_ALLOW_JOINS | EZSP_DECISION_ALLOW_UNSECURED_REJOINS) +ZBM(ZBS_SET_POLICY_02, EZSP_setPolicy, 0x00 , EZSP_UNICAST_REPLIES_POLICY, + EZSP_HOST_WILL_NOT_SUPPLY_REPLY) +ZBM(ZBS_SET_POLICY_03, EZSP_setPolicy, 0x00 , EZSP_POLL_HANDLER_POLICY, + EZSP_POLL_HANDLER_IGNORE) +ZBM(ZBS_SET_POLICY_04, EZSP_setPolicy, 0x00 , EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY, + EZSP_MESSAGE_TAG_ONLY_IN_CALLBACK) +ZBM(ZBS_SET_POLICY_05, EZSP_setPolicy, 0x00 , EZSP_TC_KEY_REQUEST_POLICY, + EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY) +ZBM(ZBS_SET_POLICY_06, EZSP_setPolicy, 0x00 , EZSP_APP_KEY_REQUEST_POLICY, + EZSP_DENY_APP_KEY_REQUESTS) +ZBM(ZBR_SET_POLICY_XX, EZSP_setPolicy, 0x00 , 0x00 ) + + +ZBM(ZBS_NETWORK_INIT, EZSP_networkInit, 0x00 , 0x00, 0x00) +ZBM(ZBR_NETWORK_INIT, EZSP_networkInit, 0x00 , 0x00 ) + + +ZBR(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + USE_ZIGBEE_TXRADIO_DBM , + USE_ZIGBEE_CHANNEL , + EMBER_USE_MAC_ASSOCIATION, + 0xFF,0xFF, + 0x00, + 0x00,0x00,0x00,0x00, + ) +ZBM(ZBR_FORM_NETWORK, EZSP_formNetwork, 0x00 , 0x00 ) +ZBM(ZBR_NETWORK_UP, EZSP_stackStatusHandler, 0x00 , EMBER_NETWORK_UP) + + +ZBR(ZBS_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 ) +ZBM(ZBR_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 ) + + +ZBM(ZBS_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 ) +ZBM(ZBR_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 , 0x00 ) +ZBR(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 , + 0x00 , + EMBER_COORDINATOR , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + USE_ZIGBEE_TXRADIO_DBM , + USE_ZIGBEE_CHANNEL , + ) + +ZBM(ZBS_GET_EUI64, EZSP_getEui64, 0x00 ) +ZBM(ZBR_GET_EUI64, EZSP_getEui64, 0x00 ) +ZBM(ZBS_GET_NODEID, EZSP_getNodeId, 0x00 ) +ZBM(ZBR_GET_NODEID, EZSP_getNodeId, 0x00 ) + + +ZBM(ZBS_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 , + 0x00 , 0x00,0x00 , 0x01 , 0x00 ) +ZBM(ZBR_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 , 0x00 ) + + + + +ZBM(ZBS_GET_KEY_NWK, EZSP_getKey, 0x00 , EMBER_CURRENT_NETWORK_KEY) +ZBM(ZBR_GET_KEY_NWK, EZSP_getKey, 0x00 , 0x00 ) + + + + + +uint64_t ezsp_key_low, ezsp_key_high; + +void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, int8_t zb_txradio_dbm) { + int8_t txradio = zb_txradio_dbm; + + if (txradio < 0) { txradio = USE_ZIGBEE_TXRADIO_DBM; } + if (txradio > 20) { txradio = USE_ZIGBEE_TXRADIO_DBM; } + ezsp_key_low = zb_precfgkey_l; + ezsp_key_high = zb_precfgkey_h; + + ZBW(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , + Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE), + + 0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39, + + Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), + Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), + Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), + Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), + 0x00 , + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + ) + + ZBW(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 , + Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), + Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), + Z_B0(zb_pan_id), Z_B1(zb_pan_id), + (uint8_t)txradio , + zb_channel , + EMBER_USE_MAC_ASSOCIATION, + 0xFF,0xFF, + 0x00, + 0x00,0x00,0x00,0x00, + ) + + ZBW(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 , + 0x00 , + EMBER_COORDINATOR , + Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), + Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), + Z_B0(zb_pan_id), Z_B1(zb_pan_id), + (uint8_t)txradio , + zb_channel , + ) +} + +static const Zigbee_Instruction zb_prog[] PROGMEM = { + ZI_LABEL(0) + ZI_CALL(&EZ_Reset_Device, 0) + ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) + + ZI_LABEL(ZIGBEE_LABEL_RESTART) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_RECV_UNEXPECTED(&EZ_Recv_Default) + ZI_WAIT(10500) + + + ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) + ZI_CALL(&EZ_Reset_Device, 0) + ZI_WAIT(100) + ZI_CALL(&EZ_Reset_Device, 1) + + + ZI_WAIT_UNTIL(5000, ZBR_RSTACK) + + + ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &EZ_ReceiveCheckVersion) + + + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) + ZI_SEND(ZBS_SET_ADDR_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_MCAST_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_STK_PROF) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_SEC_LEVEL) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_MAX_DEVICES) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_INDIRECT_TMO) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_TC_CACHE) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_ROUTE_TBL) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_KEY_TBL) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_PANID_CNFLCT) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_ZDO_REQ) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_NETWORKS) ZI_WAIT_RECV(500, ZBR_SET_OK) + ZI_SEND(ZBS_SET_PACKET_BUF) ZI_WAIT_RECV(500, ZBR_SET_OK2) + + + + + + + ZI_SEND(ZBS_ADD_ENDPOINT1) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT) + ZI_SEND(ZBS_ADD_ENDPOINTB) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT) + + + ZI_SEND(ZBS_SET_CONCENTRATOR) ZI_WAIT_RECV(500, ZBR_SET_CONCENTRATOR) + + + ZI_SEND(ZBS_SET_POLICY_00) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) + ZI_SEND(ZBS_SET_POLICY_02) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) + ZI_SEND(ZBS_SET_POLICY_03) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) + + ZI_SEND(ZBS_SET_POLICY_05) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) + ZI_SEND(ZBS_SET_POLICY_06) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) + + + ZI_CALL(&EZ_GotoIfResetConfig, ZIGBEE_LABEL_CONFIGURE_EZSP) + + + + + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_BAD_CONFIG) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_BAD_CONFIG) + ZI_SEND(ZBS_NETWORK_INIT) ZI_WAIT_RECV(500, ZBR_NETWORK_INIT) + ZI_WAIT_RECV(1500, ZBR_NETWORK_UP) + + ZI_SEND(ZBS_GET_KEY_NWK) ZI_WAIT_RECV_FUNC(500, ZBR_GET_KEY_NWK, &EZ_CheckKeyNWK) + ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64) + ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV_FUNC(500, ZBR_CHECK_NETW_PARM, &EZ_NetworkParameters) + + + ZI_GOTO(ZIGBEE_LABEL_NETWORK_CONFIGURED) + + ZI_LABEL(ZIGBEE_LABEL_BAD_CONFIG) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) + ZI_CALL(EZ_Set_ResetConfig, 1) + ZI_GOTO(ZIGBEE_LABEL_RESTART) + + ZI_LABEL(ZIGBEE_LABEL_CONFIGURE_EZSP) + + ZI_LOG(LOG_LEVEL_INFO, kReconfiguringDevice) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY) + + ZI_SEND(ZBS_FORM_NETWORK) ZI_WAIT_RECV(500, ZBR_FORM_NETWORK) + ZI_WAIT_RECV(5000, ZBR_NETWORK_UP) + + ZI_LABEL(ZIGBEE_LABEL_NETWORK_CONFIGURED) + + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64) + ZI_SEND(ZBS_GET_NODEID) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NODEID, &EZ_GetNodeId) + + ZI_LOG(LOG_LEVEL_INFO, kZigbeeGroup0) + ZI_SEND(ZBS_SET_MCAST_ENTRY) ZI_WAIT_RECV(500, ZBR_SET_MCAST_ENTRY) + + + ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted) + ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted) + ZI_CALL(&Z_State_Ready, 1) + ZI_CALL(&Z_Load_Devices, 0) +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES + ZI_CALL(&Z_Query_Bulbs, 0) +#endif + + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kEZ8) + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + + ZI_LABEL(ZIGBEE_LABEL_ABORT) + ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, kAbort) + ZI_LOG(LOG_LEVEL_ERROR, kZigbeeAbort) + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +#endif + +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 < ARRAY_SIZE(zb_prog); 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(D_LOG_ZIGBEE "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(D_LOG_ZIGBEE "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(D_LOG_ZIGBEE "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 > ARRAY_SIZE(zb_prog)) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); + zigbee.pc = -1; + } + if (zigbee.pc < 0) { + zigbee.state_machine = false; + return; + } + + + 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(D_LOG_ZIGBEE "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_STATE: + { + const char *f_msg = (const char*) cur_ptr1; + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), + cur_d8, f_msg); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + } + break; + case ZGB_INSTR_SEND: +#ifdef USE_ZIGBEE_ZNP + ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); +#endif +#ifdef USE_ZIGBEE_EZSP + ZigbeeEZSPSendCmd((uint8_t*) cur_ptr1, cur_d8 ); +#endif + 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; + if (0xFFFF == cur_d16) { + zigbee.next_timeout = 0; + } else { + 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_UNTIL_CALL: + zigbee.recv_until = true; + 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; + if (0xFFFF == cur_d16) { + zigbee.next_timeout = 0; + } else { + 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; + } + } + } + + + 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); + } + } + + + if (0 == res) { + + zigbee.state_waiting = false; + } else if (res > 0) { + ZigbeeGotoLabel(res); + } else if (-1 == res) { + + + } else { + + ZigbeeGotoLabel(zigbee.on_error_goto); + } + return 0; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +#ifdef USE_ZIGBEE + +#ifdef USE_ZIGBEE_EZSP + + + + +uint8_t ZNP_RSSI2Lqi(int8_t rssi) { + if (rssi < -87) { rssi = -87; } + if (rssi > 10) { rssi = 10; } + return changeUIntScale(rssi + 87, 0, 87+10, 0, 254); +} + + + + + + +int32_t EZ_RSTACK(uint8_t reset_code) { + const char *reason_str; + + switch (reset_code) { + case 0x01: reason_str = PSTR("External"); break; + case 0x02: reason_str = PSTR("Power-on"); break; + case 0x03: reason_str = PSTR("Watchdog"); break; + case 0x06: reason_str = PSTR("Assert"); break; + case 0x09: reason_str = PSTR("Bootloader"); break; + case 0x0B: reason_str = PSTR("Software"); break; + case 0x00: + default: reason_str = PSTR("Unknown"); break; + } + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\"EFR32 booted\",\"RestartReason\":\"%s\"" + ",\"Code\":%d}}"), + ZIGBEE_STATUS_BOOT, reason_str, reset_code); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); +} + + +int32_t EZ_ERROR(uint8_t error_code) { + const char *reason_str; + + switch (error_code) { + case 0x51: reason_str = PSTR("ACK timeout"); break; + default: reason_str = PSTR("Unknown"); break; + } + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\"Failed state\",\"Error\":\"%s\"" + ",\"Code\":%d}}"), + ZIGBEE_STATUS_ABORT, reason_str, error_code); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); +} + +int32_t EZ_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) { + + + uint16_t value = buf.get16(2); + return res; +} +# 89 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +int32_t EZ_GetEUI64(int32_t res, class SBuffer &buf) { + localIEEEAddr = buf.get64(2); + return res; +} + + + + +int32_t EZ_GetNodeId(int32_t res, class SBuffer &buf) { + localShortAddr = buf.get8(2); + return res; +} + + + + +int32_t EZ_NetworkParameters(int32_t res, class SBuffer &buf) { + uint8_t node_type = buf.get8(3); +# 116 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" + char hex[20]; + Uint64toHex(localIEEEAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d}}"), + ZIGBEE_STATUS_EZ_INFO, hex, localShortAddr, node_type); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + return res; +} + + + + +int32_t EZ_CheckKeyNWK(int32_t res, class SBuffer &buf) { + uint8_t status = buf.get8(2); + uint16_t bitmask = buf.get16(3); + uint8_t key_type = buf.get8(5); + uint64_t key_low = buf.get64(6); + uint64_t key_high = buf.get64(14); + + if ( (key_type == EMBER_CURRENT_NETWORK_KEY) && + (key_low == ezsp_key_low) && + (key_high == ezsp_key_high) ) { + return 0; + } else { + return -2; + } +} + + + + +int32_t EZ_RouteError(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + uint16_t shortaddr = buf.get16(3); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_ROUTE_ERROR "\":{" + "\"ShortAddr\":\"0x%04X\",\"" D_JSON_ZIGBEE_STATUS "\":%d,\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"}}"), + shortaddr, status, getEmberStatus(status).c_str()); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + return -1; +} + + + + +int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + + if (status) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":23,\"Message\":\"Pairing mode error 0x%02X\"}}"), status); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + } + return -1; +} + + + + +void Z_PermitJoinDisable(void) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":20,\"Message\":\"Pairing mode disabled\"}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); +} + + + + + + + +int32_t EZ_MessageSent(int32_t res, const class SBuffer &buf) { + uint8_t message_type = buf.get8(2); + uint16_t dst_addr = buf.get16(3); + uint16_t group_addr = buf.get16(13); + + if ((EMBER_OUTGOING_MULTICAST == message_type) && (0xFFFD == dst_addr)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Sniffing group 0x%04X"), group_addr); + } + return -1; +} + +#endif +# 210 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +int32_t Z_EZSPGetEUI64(int32_t res, class SBuffer &buf) { + localIEEEAddr = buf.get64(2); + return res; +} + + + + +int32_t Z_EZSPGetNodeId(int32_t res, class SBuffer &buf) { + localShortAddr = buf.get8(2); + return res; +} + + + + +int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf) { + uint8_t node_type = buf.get8(3); +# 237 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" + char hex[20]; + Uint64toHex(localIEEEAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d}}"), + ZIGBEE_STATUS_EZ_INFO, hex, localShortAddr, node_type); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + return res; +} +# 256 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +int32_t ZNP_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); + + + localIEEEAddr = long_adr; + localShortAddr = short_adr; + + char hex[20]; + Uint64toHex(long_adr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%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("]")); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + return res; +} + +int32_t ZNP_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 ZNP_Reboot(int32_t res, class SBuffer &buf) { + + + + uint8_t reason = buf.get8(2); + uint8_t transport_rev = buf.get8(3); + uint8_t product_id = buf.get8(4); + uint8_t major_rel = buf.get8(5); + uint8_t minor_rel = buf.get8(6); + uint8_t hw_rev = buf.get8(7); + const char *reason_str; + + switch (reason) { + case 0: reason_str = PSTR("Power-up"); break; + case 1: reason_str = PSTR("External"); break; + case 2: reason_str = PSTR("Watchdog"); break; + default: reason_str = PSTR("Unknown"); break; + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\"CC2530 booted\",\"RestartReason\":\"%s\"" + ",\"MajorRel\":%d,\"MinorRel\":%d}}"), + ZIGBEE_STATUS_BOOT, reason_str, + major_rel, minor_rel); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +#ifdef USE_ZIGBEE_ZNP +int32_t ZNP_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { +# 357 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.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_STATE "\":{" + "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" + ",\"MaintRel\":%d,\"Revision\":%d}}"), + ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, + maint_rel, revision); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} +#endif + +#ifdef USE_ZIGBEE_EZSP +int32_t EZ_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { + uint8_t protocol_version = buf.get8(2); + uint8_t stack_type = buf.get8(3); + uint16_t stack_version = buf.get16(4); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Version\":\"%d.%d.%d.%d\",\"Protocol\":%d" + ",\"Stack\":%d}}"), + ZIGBEE_STATUS_EZ_VERSION, + (stack_version & 0xF000) >> 12, + (stack_version & 0x0F00) >> 8, + (stack_version & 0x00F0) >> 4, + stack_version & 0x000F, + protocol_version, + stack_type + ); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + + if (0x08 == protocol_version) { + if ((stack_version & 0xFF00) == 0x6700) { + + ZBW(ZBR_SET_OK2, 0x00, 0x00 , 0x00 ) + } + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +bool EZ_reset_config = false; + + +int32_t EZ_Set_ResetConfig(uint8_t value) { + EZ_reset_config = value ? true : false; + return 0; +} + + + +int32_t EZ_GotoIfResetConfig(uint8_t value) { + if (EZ_reset_config) { return ZIGBEE_LABEL_CONFIGURE_EZSP; } + else { return 0; } +} + +#endif + + + + + +int32_t Z_SwitchDeviceType(int32_t res, class SBuffer &buf) { + switch (Settings.zb_pan_id) { + case 0xFFFF: return ZIGBEE_LABEL_INIT_ROUTER; + case 0xFFFE: return ZIGBEE_LABEL_INIT_DEVICE; + default: return 0; + } +} + + + + +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 ZNP_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { + + 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_STATE "\":{" + "\"Status\":%d,\"Message\":\""), + status_code); + ResponseAppend_P(message, duration); + ResponseAppend_P(PSTR("\"}}")); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + return -1; +} + + + + +int32_t ZNP_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { + + 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; + const char * deviceTypeStr; + switch (deviceType) { + case 0: deviceTypeStr = PSTR("Coordinator"); break; + case 1: deviceTypeStr = PSTR("Router"); break; + case 2: deviceTypeStr = PSTR("Device"); break; + default: deviceTypeStr = PSTR("Unknown"); break; + } + bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), + ZIGBEE_STATUS_NODE_DESC, deviceTypeStr, + complexDescriptorAvailable ? PSTR("true") : PSTR("false") + ); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + } + + return -1; +} + + + + +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { + +#ifdef USE_ZIGBEE_ZNP + + 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); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t status = buf.get8(0); + Z_ShortAddress nwkAddr = buf.get16(1); + uint8_t activeEpCount = buf.get8(3); + uint8_t* activeEpList = (uint8_t*) buf.charptr(4); +#endif + + for (uint32_t i = 0; i < activeEpCount; i++) { + uint8_t ep = activeEpList[i]; + zigbee_devices.addEndpoint(nwkAddr, ep); + if ((i < 4) && (ep < 0x10)) { + zigbee_devices.queueTimer(nwkAddr, 0 , 1500, ep , ep, Z_CAT_EP_DESC, 0 , &Z_SendSimpleDescReq); + } + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"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("]}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + + Z_SendDeviceInfoRequest(nwkAddr); + + return -1; +} + + +const uint8_t Z_bindings[] PROGMEM = { + Cx0001, Cx0006, Cx0008, Cx0201, Cx0300, + Cx0400, Cx0402, Cx0403, Cx0405, Cx0406, + Cx0500, +}; + +int32_t Z_ClusterToCxBinding(uint16_t cluster) { + uint8_t cx = ClusterToCx(cluster); + for (uint32_t i=0; i= 0) { + bitSet(cluster_map, found_cx); + bitSet(cluster_in_map, found_cx); + } + } + + for (uint32_t i=0; i= 0) { + bitSet(cluster_map, found_cx); + } + } + + + if (bitRead(cluster_map, Z_ClusterToCxBinding(0x0500))) { + + zigbee_devices.queueTimer(shortaddr, 0 , 2000, 0x0500, endpoint, Z_CAT_READ_ATTRIBUTE, 0x0001, &Z_SendSingleAttributeRead); + } + + + for (uint32_t i=0; i 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(numInIndex + 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(numOutIndex + i*2)); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + + return -1; +} + + + + + +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + uint8_t status = buf.get8(2); + Z_IEEEAddress ieeeAddr = buf.get64(3); + Z_ShortAddress nwkAddr = buf.get16(11); + + +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t status = buf.get8(0); + Z_IEEEAddress ieeeAddr = buf.get64(1); + Z_ShortAddress nwkAddr = buf.get16(9); + + +#endif + + if (0 == status) { + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\""), nwkAddr, hex); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR("\"}}")); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + } + return -1; +} + + + + +int32_t ZNP_DataConfirm(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + uint8_t endpoint = buf.get8(3); + + + if (status) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), endpoint, status, getZigbeeStatusMessage(status).c_str()); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + } + + return -1; +} +# 761 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +int32_t ZNP_ReceiveStateChange(int32_t res, const class SBuffer &buf) { + uint8_t state = buf.get8(2); + const char * msg = nullptr; + + switch (state) { + case ZDO_DEV_NWK_DISC: + msg = PSTR("Scanning Zigbee network"); + break; + case ZDO_DEV_NWK_JOINING: + case ZDO_DEV_NWK_REJOIN: + msg = PSTR("Joining a PAN"); + break; + case ZDO_DEV_END_DEVICE_UNAUTH: + msg = PSTR("Joined, not yet authenticated"); + break; + case ZDO_DEV_END_DEVICE: + msg = PSTR("Started as device"); + break; + case ZDO_DEV_ROUTER: + msg = PSTR("Started as router"); + break; + case ZDO_DEV_ZB_COORD: + msg = PSTR("Started as coordinator"); + break; + case ZDO_DEV_NWK_ORPHAN: + msg = PSTR("Device has lost its parent"); + break; + }; + + if (msg) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"NewState\":%d,\"Message\":\"%s\"}}"), + ZIGBEE_STATUS_SCANNING, state, msg + ); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + } + + if ((ZDO_DEV_END_DEVICE == state) || (ZDO_DEV_ROUTER == state) || (ZDO_DEV_ZB_COORD == state)) { + return 0; + } else { + return -1; + } +} + + + + + + +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + + Z_ShortAddress nwkAddr = buf.get16(4); + Z_IEEEAddress ieeeAddr = buf.get64(6); + uint8_t capabilities = buf.get8(14); +#endif +#ifdef USE_ZIGBEE_EZSP + + Z_ShortAddress nwkAddr = buf.get16(0); + Z_IEEEAddress ieeeAddr = buf.get64(2); + uint8_t capabilities = buf.get8(10); +#endif + + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" + ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), + ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, + (capabilities & 0x04) ? PSTR("true") : PSTR("false"), + (capabilities & 0x08) ? PSTR("true") : PSTR("false"), + (capabilities & 0x40) ? PSTR("true") : PSTR("false") + ); + + uint32_t wait_ms = 2000; + Z_Query_Bulb(nwkAddr, wait_ms); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + Z_SendActiveEpReq(nwkAddr); + return -1; +} + + + + + +int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_IEEEAddress ieeeAddr = buf.get64(4); + Z_ShortAddress parentNw = buf.get16(12); + + zigbee_devices.updateDevice(srcAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" + ",\"ParentNetwork\":\"0x%04X\"}}"), + ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw + ); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + return -1; +} + + + + +int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + String msg = getZigbeeStatusMessage(status); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t status = buf.get8(0); + Z_ShortAddress nwkAddr = buf.get16(buf.len()-2); + String msg = getZDPStatusMessage(status); +#endif + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), status, msg.c_str()); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + + return -1; +} + + + + +int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + String msg = getZigbeeStatusMessage(status); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t status = buf.get8(0); + Z_ShortAddress nwkAddr = buf.get16(buf.len()-2); + String msg = getZDPStatusMessage(status); +#endif + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), status, msg.c_str()); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + + return -1; +} + + + +int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + uint16_t shortaddr = buf.get16(2); + uint8_t status = buf.get8(4); + uint8_t bind_total = buf.get8(5); + uint8_t bind_start = buf.get8(6); + uint8_t bind_len = buf.get8(7); + const size_t prefix_len = 8; +#endif +#ifdef USE_ZIGBEE_EZSP + uint16_t shortaddr = buf.get16(buf.len()-2); + uint8_t status = buf.get8(0); + uint8_t bind_total = buf.get8(1); + uint8_t bind_start = buf.get8(2); + uint8_t bind_len = buf.get8(3); + const size_t prefix_len = 4; +#endif + + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + ",\"BindingsTotal\":%d" + ",\"BindingsStart\":%d" + ",\"Bindings\":[" + ), status, getZigbeeStatusMessage(status).c_str(), bind_total, bind_start + 1); + + uint32_t idx = prefix_len; + for (uint32_t i = 0; i < bind_len; i++) { + if (idx + 14 > buf.len()) { break; } + + + uint8_t srcep = buf.get8(idx + 8); + uint16_t cluster = buf.get16(idx + 9); + uint8_t addrmode = buf.get8(idx + 11); + uint16_t group = 0x0000; + uint64_t dstaddr = 0; + uint8_t dstep = 0x00; + if (Z_Addr_Group == addrmode) { + group = buf.get16(idx + 12); + idx += 14; + } else if (Z_Addr_IEEEAddress == addrmode) { + dstaddr = buf.get64(idx + 12); + dstep = buf.get8(idx + 20); + idx += 21; + } else { + + break; + } + + if (i > 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep); + if (Z_Addr_Group == addrmode) { + ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group); + } else if (Z_Addr_IEEEAddress == addrmode) { + char hex[20]; + Uint64toHex(dstaddr, hex, 64); + ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep); + } + } + + ResponseAppend_P(PSTR("]}}")); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE)); + + return -1; +} + +#ifdef USE_ZIGBEE_EZSP + + + + +int32_t EZ_ParentAnnceRsp(int32_t res, const class SBuffer &buf, bool rsp) { + size_t prefix_len; + uint8_t status; + uint8_t num_children; + uint16_t shortaddr = buf.get16(buf.len()-2); + if (rsp) { + status = buf.get8(0); + num_children = buf.get8(1); + prefix_len = 2; + } else { + status = 0; + num_children = buf.get8(0); + prefix_len = 1; + } + + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PARENT "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + if (rsp) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + ), status, getZigbeeStatusMessage(status).c_str()); + } + ResponseAppend_P(PSTR(",\"Children\":%d" + ",\"ChildInfo\":[" + ), num_children); + + uint32_t idx = prefix_len; + for (uint32_t i = 0; i < num_children; i++) { + if (idx + 8 > buf.len()) { break; } + + uint64_t child_ieee = buf.get64(idx); + idx += 8; + + if (i > 0) { + ResponseAppend_P(PSTR(",")); + } + char hex[20]; + Uint64toHex(child_ieee, hex, 64); + ResponseAppend_P(PSTR("\"0x%s\""), hex); + } + + ResponseAppend_P(PSTR("]}}")); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE)); + + return -1; +} +#endif +# 1070 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +void Z_SendIEEEAddrReq(uint16_t shortaddr) { +#ifdef USE_ZIGBEE_ZNP + uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + + ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t IEEEAddrReq[] = { Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + EZ_SendZDO(shortaddr, ZDO_IEEE_addr_req, IEEEAddrReq, sizeof(IEEEAddrReq)); +#endif +} + + + + +void Z_SendActiveEpReq(uint16_t shortaddr) { +#ifdef USE_ZIGBEE_ZNP + uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t ActiveEpReq[] = { Z_B0(shortaddr), Z_B1(shortaddr) }; + EZ_SendZDO(shortaddr, ZDO_Active_EP_req, ActiveEpReq, sizeof(ActiveEpReq)); +#endif +} + + + + + +void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { +#ifdef USE_ZIGBEE_ZNP + uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), + endpoint }; + ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); +#endif +#ifdef USE_ZIGBEE_EZSP + uint8_t SimpleDescReq[] = { Z_B0(shortaddr), Z_B1(shortaddr), endpoint }; + EZ_SendZDO(shortaddr, ZDO_SIMPLE_DESC_REQ, SimpleDescReq, sizeof(SimpleDescReq)); +#endif +} +# 1121 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +void Z_SendDeviceInfoRequest(uint16_t shortaddr) { + uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + if (0x00 == endpoint) { endpoint = 0x01; } + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + + uint8_t InfoReq[] = { 0x04, 0x00, 0x05, 0x00 }; + + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, + 0x0000 , + endpoint, + ZCL_READ_ATTRIBUTES, + 0x0000, + false , + true , + false , + transacid, + InfoReq, sizeof(InfoReq) + })); +} + + + + +void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + uint8_t InfoReq[2] = { Z_B0(value), Z_B1(value) }; + + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, + cluster , + endpoint, + ZCL_READ_ATTRIBUTES, + 0x0000, + false , + true , + false , + transacid, + InfoReq, sizeof(InfoReq) + })); +} + + + + +void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(shortaddr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `ZbBind {\"Device\":\"0x%04X\",\"Endpoint\":%d,\"Cluster\":\"0x%04X\"}`"), + shortaddr, endpoint, cluster); +#ifdef USE_ZIGBEE_ZNP + SBuffer buf(34); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_BIND_REQ); + buf.add16(shortaddr); + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(Z_Addr_IEEEAddress); + buf.add64(localIEEEAddr); + buf.add8(0x01); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +#endif + +#ifdef USE_ZIGBEE_EZSP + SBuffer buf(24); + + + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(Z_Addr_IEEEAddress); + buf.add64(localIEEEAddr); + buf.add8(0x01); + + EZ_SendZDO(shortaddr, ZDO_BIND_REQ, buf.buf(), buf.len()); +#endif +} + + + + + + +typedef struct Z_autoAttributeReporting_t { + uint16_t cluster; + uint16_t attr_id; + uint16_t min_interval; + uint16_t max_interval; + float report_change; +} Z_autoAttributeReporting_t; + + +const Z_autoAttributeReporting_t Z_autoAttributeReporting[] PROGMEM = { + { 0x0001, 0x0020, 15*60, 15*60, 0.1 }, + { 0x0001, 0x0021, 15*60, 15*60, 1 }, + { 0x0006, 0x0000, 1, 60*60, 0 }, + { 0x0201, 0x0000, 60, 60*10, 0.5 }, + { 0x0201, 0x0008, 60, 60*10, 10 }, + { 0x0201, 0x0012, 60, 60*10, 0.5 }, + { 0x0008, 0x0000, 1, 60*60, 5 }, + { 0x0300, 0x0000, 1, 60*60, 5 }, + { 0x0300, 0x0001, 1, 60*60, 5 }, + { 0x0300, 0x0003, 1, 60*60, 100 }, + { 0x0300, 0x0004, 1, 60*60, 100 }, + { 0x0300, 0x0007, 1, 60*60, 5 }, + { 0x0300, 0x0008, 1, 60*60, 0 }, + { 0x0400, 0x0000, 10, 60*60, 5 }, + { 0x0402, 0x0000, 30, 60*60, 0.2 }, + { 0x0403, 0x0000, 30, 60*60, 1 }, + { 0x0405, 0x0000, 30, 60*60, 1.0 }, + { 0x0406, 0x0000, 10, 60*60, 0 }, + { 0x0500, 0x0002, 1, 60*60, 0 }, +}; + + + + + + +void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + + SBuffer buf(12*6); + + + Response_P(PSTR("ZbSend {\"Device\":\"0x%04X\",\"Config\":{"), shortaddr); + + boolean comma = false; + for (uint32_t i=0; i 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), mqtt_data); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + 0x0000, + cluster , + endpoint, + ZCL_CONFIGURE_REPORTING, + 0x0000, + false , + false , + false , + zigbee_devices.getNextSeqNumber(shortaddr), + buf.buf(), buf.len() + })); + } +} + + + + + +#ifdef USE_ZIGBEE_EZSP +int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf) { + uint16_t srcAddr = buf.get16(2); + uint64_t ieeeAddr = buf.get64(4); + uint8_t status = buf.get8(12); + uint8_t decision = buf.get8(13); + uint16_t parentNw = buf.get16(14); + + if (EMBER_DEVICE_LEFT != status) { + zigbee_devices.updateDevice(srcAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" + ",\"ParentNetwork\":\"0x%04X\"" + ",\"Status\":%d,\"Decision\":%d" + "}}"), + ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw, + status, decision + ); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + } + return -1; +} +#endif + + + + + +void Z_IncomingMessage(class ZCLFrame &zcl_received) { + uint16_t srcaddr = zcl_received.getSrcAddr(); + uint16_t groupid = zcl_received.getGroupAddr(); + uint16_t clusterid = zcl_received.getClusterId(); + uint8_t linkquality = zcl_received.getLinkQuality(); + uint8_t srcendpoint = zcl_received.getSrcEndpoint(); + linkquality = linkquality != 0xFF ? linkquality : 0xFE; + + bool defer_attributes = false; + + + zcl_received.log(); + + zigbee_devices.setLQI(srcaddr, linkquality != 0xFF ? linkquality : 0xFE); + zigbee_devices.setLastSeenNow(srcaddr); + + char shortaddr[8]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); + + Z_attribute_list attr_list; + attr_list.lqi = linkquality; + attr_list.src_ep = srcendpoint; + if (groupid) { + attr_list.group_id = groupid; + } + + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_DEFAULT_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseResponse(); + } else { + + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseReportAttributes(attr_list); + if (clusterid) { defer_attributes = true; } + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseReadAttributesResponse(attr_list); + if (clusterid) { defer_attributes = true; } + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseReadAttributes(attr_list); + + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_REPORTING_CONFIGURATION_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseReadConfigAttributes(attr_list); + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_CONFIGURE_REPORTING_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseConfigAttributes(attr_list); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(attr_list); + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":{%s}}"), srcaddr, attr_list.toString().c_str()); + + + if (srcaddr == localShortAddr) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "loopback message, ignoring")); + return; + } + + zcl_received.generateSyntheticAttributes(attr_list); + zcl_received.computeSyntheticAttributes(attr_list); + zcl_received.generateCallBacks(attr_list); + zcl_received.postProcessAttributes(srcaddr, attr_list); + + + zigbee_devices.resetTimersForDevice(srcaddr, 0 , Z_CAT_REACHABILITY); + zigbee_devices.setReachable(srcaddr, true); + + if (defer_attributes) { + + if (zigbee_devices.jsonIsConflict(srcaddr, attr_list)) { + + zigbee_devices.jsonPublishFlush(srcaddr); + } + zigbee_devices.jsonAppend(srcaddr, attr_list); + zigbee_devices.setTimer(srcaddr, 0 , USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, Z_CAT_READ_ATTR, 0, &Z_PublishAttributes); + } else { + + zigbee_devices.jsonPublishNow(srcaddr, attr_list); + } + } +} + + +#ifdef USE_ZIGBEE_EZSP + + + + + +void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len) { + SBuffer buf(payload_len + 22); + uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000); + + if (shortaddr < 0xFFFC) { + + buf.add16(EZSP_sendUnicast); + + buf.add8(EMBER_OUTGOING_DIRECT); + buf.add16(shortaddr); + + buf.add16(0x0000); + buf.add16(cmd); + buf.add8(0); + buf.add8(0); + buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); + buf.add16(0x0000); + buf.add8(seq); + + buf.add8(0x01); + buf.add8(payload_len + 1); + buf.add8(seq); + buf.addBuffer(payload, payload_len); + } else { + + buf.add16(EZSP_sendBroadcast); + buf.add16(shortaddr); + + buf.add16(0x0000); + buf.add16(cmd); + buf.add8(0); + buf.add8(0); + buf.add16(0x00); + buf.add16(0x0000); + buf.add8(seq); + + buf.add8(0x1E); + buf.add8(0x01); + buf.add8(payload_len + 1); + buf.add8(seq); + buf.addBuffer(payload, payload_len); + } + + ZigbeeEZSPSendCmd(buf.buf(), buf.len()); +} + + + + + +int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { + uint8_t msgtype = buf.get8(2); + bool wasbroadcast = (msgtype >= EMBER_INCOMING_MULTICAST) && (msgtype <= EMBER_INCOMING_BROADCAST_LOOPBACK); + uint16_t profileid = buf.get16(3); + uint16_t clusterid = buf.get16(5); + uint8_t srcendpoint = buf.get8(7); + uint8_t dstendpoint = buf.get8(8); + uint16_t apsoptions = buf.get16(9); + bool securityuse = (apsoptions & EMBER_APS_OPTION_ENCRYPTION) ? true : false; + uint16_t groupid = buf.get16(11); + uint8_t seqnumber = buf.get8(13); + int8_t linkrssi = buf.get8(15); + uint8_t linkquality = ZNP_RSSI2Lqi(linkrssi); + uint16_t srcaddr = buf.get16(16); + + + + + + if ((0x0000 == profileid) && (0x00 == srcendpoint)) { + + + zigbee_devices.setLQI(srcaddr, linkquality); + zigbee_devices.setLastSeenNow(srcaddr); + + + SBuffer zdo_buf(buf.get8(20) - 1 + 2); + zdo_buf.addBuffer(buf.buf(22), buf.get8(20) - 1); + zdo_buf.add16(srcaddr); + switch (clusterid) { + case ZDO_Device_annce: + return Z_ReceiveEndDeviceAnnonce(res, zdo_buf); + case ZDO_Active_EP_rsp: + return Z_ReceiveActiveEp(res, zdo_buf); + case ZDO_IEEE_addr_rsp: + return Z_ReceiveIEEEAddr(res, zdo_buf); + case ZDO_Simple_Desc_rsp: + return Z_ReceiveSimpleDesc(res, zdo_buf); + case ZDO_Bind_rsp: + return Z_BindRsp(res, zdo_buf); + case ZDO_Unbind_rsp: + return Z_UnbindRsp(res, zdo_buf); + case ZDO_Mgmt_Bind_rsp: + return Z_MgmtBindRsp(res, zdo_buf); + case ZDO_Parent_annce: + return EZ_ParentAnnceRsp(res, zdo_buf, false); + case ZDO_Parent_annce_rsp: + return EZ_ParentAnnceRsp(res, zdo_buf, true); + default: + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Internal ZDO message 0x%04X sent from 0x%04X %s"), clusterid, srcaddr, wasbroadcast ? PSTR("(broadcast)") : ""); + break; + } + } else { + bool defer_attributes = false; + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 21, buf.get8(20), clusterid, groupid, + srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber); + + Z_IncomingMessage(zcl_received); + } + return -1; +} + + + + + + +int32_t EZ_Reset_Device(uint8_t value) { + + + + + + if (PinUsed(GPIO_ZIGBEE_RST)) { + digitalWrite(Pin(GPIO_ZIGBEE_RST), value); + } else { + + if (value) { + uint8_t ezsp_reset[1] = { 0xC0 }; + ZigbeeEZSPSendRaw(ezsp_reset, sizeof(ezsp_reset), true); + } + } + return 0; +} + + + + + +int32_t EZ_Recv_Default(int32_t res, const class SBuffer &buf) { + + if (zigbee.init_phase) { + + return -1; + } else { + uint16_t ezsp_command_index = buf.get16(0); + + switch (ezsp_command_index) { + case EZSP_incomingMessageHandler: + return EZ_IncomingMessage(res, buf); + break; + case EZSP_trustCenterJoinHandler: + return EZ_ReceiveTCJoinHandler(res, buf); + break; + case EZSP_incomingRouteErrorHandler: + return EZ_RouteError(res, buf); + break; + case EZSP_permitJoining: + return EZ_PermitJoinRsp(res, buf); + break; + case EZSP_messageSentHandler: + return EZ_MessageSent(res, buf); + break; + } + return -1; + } +} + +#endif + + + + + + +void Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + zigbee_devices.jsonPublishFlush(shortaddr); +} + + + + + +#ifdef USE_ZIGBEE_ZNP + + + + + + +int32_t ZNP_Reset_Device(uint8_t value) { + + + + + + if (PinUsed(GPIO_ZIGBEE_RST)) { + digitalWrite(Pin(GPIO_ZIGBEE_RST), value); + } else { + + if (value) { + + ZigbeeZNPFlush(); + ZigbeeZNPSend(ZBS_RESET, sizeof(ZBS_RESET)); + } + } + return 0; +} + +int32_t ZNP_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { + uint16_t groupid = buf.get16(2); + uint16_t clusterid = buf.get16(4); + uint16_t 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); + + uint8_t seqnumber = buf.get8(17); + + bool defer_attributes = false; + + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, + srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber); + + Z_IncomingMessage(zcl_received); + + return -1; +} + +#endif + + + + + + +#ifdef USE_ZIGBEE_ZNP + + +typedef struct Z_Dispatcher { + uint8_t match[2]; + ZB_RecvMsgFunc func; +} Z_Dispatcher; + + +const Z_Dispatcher Z_DispatchTable[] PROGMEM = { + { { Z_AREQ | Z_AF, AF_DATA_CONFIRM }, &ZNP_DataConfirm }, + { { Z_AREQ | Z_AF, AF_INCOMING_MSG }, &ZNP_ReceiveAfIncomingMessage }, + + { { Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND }, &Z_ReceiveEndDeviceAnnonce }, + { { Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND }, &ZNP_ReceiveTCDevInd }, + { { Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND }, &ZNP_ReceivePermitJoinStatus }, + { { Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP }, &ZNP_ReceiveNodeDesc }, + { { Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP }, &Z_ReceiveActiveEp }, + { { Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP}, &Z_ReceiveSimpleDesc}, + { { Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP }, &Z_ReceiveIEEEAddr }, + { { Z_AREQ | Z_ZDO, ZDO_BIND_RSP }, &Z_BindRsp }, + { { Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP }, &Z_UnbindRsp }, + { { Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP }, &Z_MgmtBindRsp }, +}; + + + + + +int32_t ZNP_Recv_Default(int32_t res, const class SBuffer &buf) { + + if (zigbee.init_phase) { + + return -1; + } else { + for (uint32_t i = 0; i < ARRAY_SIZE(Z_DispatchTable); i++) { + if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { + (*Z_DispatchTable[i].func)(res, buf); + } + } + return -1; + } +} + +#endif +# 1731 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +int32_t Z_Load_Devices(uint8_t value) { + + loadZigbeeDevices(); + return 0; +} + + + + +void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) { + const uint32_t inter_message_ms = 100; + + if (0 <= zigbee_devices.getHueBulbtype(shortaddr)) { + uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + + if (endpoint) { + zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0006, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0008, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0300, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 , &Z_Unreachable); + wait_ms += 1000; + } + } +} + + + + +int32_t Z_Query_Bulbs(uint8_t value) { + + uint32_t wait_ms = 1000; + for (uint32_t i = 0; i < zigbee_devices.devicesSize(); i++) { + const Z_Device &device = zigbee_devices.devicesAt(i); + Z_Query_Bulb(device.shortaddr, wait_ms); + } + return 0; +} + + + + +int32_t Z_State_Ready(uint8_t value) { + zigbee.init_phase = false; + return 0; +} + + + + + + +void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) { + Z_attribute_list attr_list; + + for (uint32_t i=0; i 0xFEFF) ? uxy[i] : 0xFEFF; + } + if (0x0000 == attr_id) { attr.setUInt(changeUIntScale(hue, 0, 360, 0, 254)); } + if (0x0001 == attr_id) { attr.setUInt(changeUIntScale(sat, 0, 255, 0, 254)); } + if (0x0003 == attr_id) { attr.setUInt(uxy[0]); } + if (0x0004 == attr_id) { attr.setUInt(uxy[1]); } + if (0x0007 == attr_id) { attr.setUInt(LightGetColorTemp()); } + } + break; +#endif + case 0x000A0000: + attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time); + break; + case 0x000AFF00: + attr.setUInt(Rtc.utc_time); + break; + case 0x000A0001: + attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? 0x02 : 0x00); + break; + case 0x000A0002: + attr.setUInt(Settings.toffset[0] * 60); + break; + case 0x000A0007: + attr.setUInt(Settings.toffset[0] * 60 + ((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time)); + break; + } + if (!attr.isNone()) { + Z_parseAttributeKey(attr); + attr_list.addAttribute(_cluster_id, attr_id) = attr; + } + } + + SBuffer buf(200); + for (const auto & attr : attr_list) { + if (!ZbAppendWriteBuf(buf, attr, true)) { + return; + } + } + + if (buf.len() > 0) { + + + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Auto-responder: ZbSend {\"Device\":\"0x%04X\"" + ",\"Cluster\":\"0x%04X\"" + ",\"Endpoint\":%d" + ",\"Response\":%s}" + ), + _srcaddr, _cluster_id, _srcendpoint, + attr_list.toString().c_str()); + + + + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + _srcaddr, + 0x0000, + _cluster_id , + _srcendpoint, + ZCL_READ_ATTRIBUTES_RESPONSE, + 0x0000, + false , + false , + true , + _transact_seq, + buf.getBuffer(), buf.len() + })); + } +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" +#ifdef USE_ZIGBEE + +#ifdef USE_ZIGBEE_ZNP +const uint32_t ZIGBEE_BUFFER_SIZE = 256; +const uint8_t ZIGBEE_SOF = 0xFE; +const uint8_t ZIGBEE_SOF_ALT = 0xFF; +#endif + +#ifdef USE_ZIGBEE_EZSP +const uint32_t ZIGBEE_BUFFER_SIZE = 256; +const uint8_t ZIGBEE_EZSP_CANCEL = 0x1A; +const uint8_t ZIGBEE_EZSP_EOF = 0x7E; +const uint8_t ZIGBEE_EZSP_ESCAPE = 0x7D; + +const uint32_t ZIGBEE_LED_RECEIVE = 0; +const uint32_t ZIGBEE_LED_SEND = 0; + +class EZSP_Serial_t { +public: + uint8_t to_send = 0; + uint8_t to_end = 0; + uint8_t to_ack = 0; + uint8_t from_ack = 0; + uint8_t ezsp_seq = 0; + SBuffer *to_packets[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; +}; + + +EZSP_Serial_t EZSP_Serial; + + + + +const uint32_t Z_LED_STATUS_ON_MILLIS = 50; +bool Z_LedStatusSet(bool onoff) { + static bool led_status_on = false; + static uint32_t led_on_time = 0; + + if (onoff) { + SetLedPowerIdx(ZIGBEE_LED_RECEIVE, 1); + led_status_on = true; + led_on_time = millis(); + } else if ((led_status_on) && (TimePassedSince(led_on_time) >= Z_LED_STATUS_ON_MILLIS)) { + SetLedPowerIdx(ZIGBEE_LED_RECEIVE, 0); + led_status_on = false; + } + return led_status_on; +} + +#endif + +#include +TasmotaSerial *ZigbeeSerial = nullptr; + + + + + +void ZigbeeInputLoop(void) { + +#ifdef USE_ZIGBEE_ZNP + static uint32_t zigbee_polling_window = 0; + static uint8_t fcs = ZIGBEE_SOF; + static uint32_t zigbee_frame_len = 5; +# 92 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" + while (ZigbeeSerial->available()) { + yield(); + uint8_t zigbee_in_byte = ZigbeeSerial->read(); + + + if (0 == zigbee_buffer->len()) { + zigbee_frame_len = 5; + fcs = ZIGBEE_SOF; + + + + if (ZIGBEE_SOF_ALT == zigbee_in_byte) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); + zigbee_in_byte = ZIGBEE_SOF; + } + } + + if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput 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)); + + + + 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 { + + + + 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); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + + ZigbeeProcessInput(znp_buffer); + } + zigbee_buffer->setLen(0); + } +#endif + +#ifdef USE_ZIGBEE_EZSP + static uint32_t zigbee_polling_window = 0; + static bool escape = false; + bool frame_complete = false; + + + + + + Z_LedStatusSet(false); + + while (ZigbeeSerial->available()) { + Z_LedStatusSet(true); + + yield(); + uint8_t zigbee_in_byte = ZigbeeSerial->read(); + + + + + + + + if ((0x11 == zigbee_in_byte) || (0x13 == zigbee_in_byte)) { + continue; + } + + if (ZIGBEE_EZSP_ESCAPE == zigbee_in_byte) { + + escape = true; + continue; + } + + if (ZIGBEE_EZSP_CANCEL == zigbee_in_byte) { + + zigbee_buffer->setLen(0); + escape = false; + frame_complete = false; + continue; + } + + if (ZIGBEE_EZSP_EOF == zigbee_in_byte) { + + frame_complete = true; + break; + } + + if (zigbee_buffer->len() < ZIGBEE_BUFFER_SIZE) { + if (escape) { + + zigbee_in_byte ^= 0x20; + escape = false; + } + + zigbee_buffer->add8(zigbee_in_byte); + zigbee_polling_window = millis(); + } + } + + uint32_t frame_len = zigbee_buffer->len(); + if (frame_complete || (frame_len && (millis() > (zigbee_polling_window + ZIGBEE_POLLING)))) { + char hex_char[frame_len * 2 + 2]; + ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); + + + if ((frame_complete) && (frame_len >= 3)) { + + + uint16_t crc = 0xFFFF; + + for (uint32_t i=0; iget8(i) << 8); + for (uint32_t i=0; i<8; i++) { + if (crc & 0x8000) { + crc = (crc << 1) ^ 0x1021; + } else { + crc <<= 1; + } + } + } + + uint16_t crc_received = zigbee_buffer->get8(frame_len - 2) << 8 | zigbee_buffer->get8(frame_len - 1); + + + if (crc_received != crc) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": bad crc (received 0x%04X, computed 0x%04X) %s"), crc_received, crc, hex_char); + } else { + + SBuffer ezsp_buffer = zigbee_buffer->subBuffer(0, frame_len - 2); + + + if (0 == (ezsp_buffer.get8(0) & 0x80)) { + + uint8_t rand = 0x42; + for (uint32_t i=1; i> 1) ^ 0xB8; } + else { rand = (rand >> 1); } + } + } + + ToHex_P((unsigned char*)ezsp_buffer.getBuffer(), ezsp_buffer.len(), hex_char, sizeof(hex_char)); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "{\"" D_JSON_ZIGBEE_EZSP_RECEIVED "2\":\"%s\"}"), hex_char); + + ZigbeeProcessInputRaw(ezsp_buffer); + } + } else { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": time-out, discarding %s, %d"), hex_char); + } + zigbee_buffer->setLen(0); + escape = false; + frame_complete = false; + } + +#endif + +} + + + + +void ZigbeeInitSerial(void) +{ + + zigbee.active = false; + if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX)); + + ZigbeeSerial = new TasmotaSerial(Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX), seriallog_level ? 1 : 2, 0, 256); + ZigbeeSerial->begin(115200); + if (ZigbeeSerial->hardwareSerial()) { + ClaimSerial(); + uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; + zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); + } else { + + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); + + } + + if (PinUsed(GPIO_ZIGBEE_RST)) { + pinMode(Pin(GPIO_ZIGBEE_RST), OUTPUT); + digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); + } + + zigbee.active = true; + zigbee.init_phase = true; + zigbee.state_machine = true; + ZigbeeSerial->flush(); + } + +} + +#ifdef USE_ZIGBEE_ZNP + + +void ZigbeeZNPFlush(void) { + if (ZigbeeSerial) { + for (uint32_t i = 0; i < 256; i++) { + ZigbeeSerial->write(0xFF); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " 0xFF x 255")); + } +} + +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); + + ZigbeeSerial->write(data_len); + + for (uint32_t i = 0; i < len; i++) { + uint8_t b = pgm_read_byte(msg + i); + ZigbeeSerial->write(b); + fcs ^= b; + + } + ZigbeeSerial->write(fcs); + + } + + char hex_char[(len * 2) + 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), + ToHex_P(msg, len, hex_char, sizeof(hex_char))); +} + + + + + +void CmndZbZNPSendOrReceive(bool send) +{ + 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 > 1) { + char stemp[3]; + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, nullptr, 16); + buf.add8(code); + size -= 2; + codes += 2; + } + if (send) { + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + } else { + + ZigbeeProcessInput(buf); + } + } + ResponseCmndDone(); +} + + +void CmndZbZNPReceive(void) +{ + CmndZbZNPSendOrReceive(false); +} + +void CmndZbZNPSend(void) +{ + CmndZbZNPSendOrReceive(true); +} + +#endif + +#ifdef USE_ZIGBEE_EZSP + + +void ZigbeeEZSPSend_Out(uint8_t out_byte) { + switch (out_byte) { + case 0x7E: + case 0x11: + case 0x13: + case 0x18: + case 0x1A: + case 0x7D: + + ZigbeeSerial->write(ZIGBEE_EZSP_ESCAPE); + ZigbeeSerial->write(out_byte ^ 0x20); + break; + default: + ZigbeeSerial->write(out_byte); + break; + } +} +# 443 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" +void ZigbeeEZSPSendRaw(const uint8_t *msg, size_t len, bool send_cancel) { + if ((len < 1) || (len > 252)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEE_EZSP_SENT ": bad message len %d"), len); + return; + } + uint8_t data_len = len - 2; + + + Z_LedStatusSet(true); + + if (ZigbeeSerial) { + if (send_cancel) { + ZigbeeSerial->write(ZIGBEE_EZSP_CANCEL); + } + + bool data_frame = (0 == (msg[0] & 0x80)); + uint8_t rand = 0x42; + uint16_t crc = 0xFFFF; + + for (uint32_t i=0; i 0)) { + out_byte ^= rand; + if (rand & 1) { rand = (rand >> 1) ^ 0xB8; } + else { rand = (rand >> 1); } + } + + + crc = crc ^ ((uint16_t)out_byte << 8); + for (uint32_t i=0; i<8; i++) { + if (crc & 0x8000) { + crc = (crc << 1) ^ 0x1021; + } else { + crc <<= 1; + } + } + + + ZigbeeEZSPSend_Out(out_byte); + } + + ZigbeeEZSPSend_Out(crc >> 8); + ZigbeeEZSPSend_Out(crc & 0xFF); + + + ZigbeeSerial->write(ZIGBEE_EZSP_EOF); + } + + + char hex_char[(len * 2) + 2]; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEE_EZSP_SENT_RAW " %s"), + ToHex_P(msg, len, hex_char, sizeof(hex_char))); +} + + + +void ZigbeeEZSPSendCmd(const uint8_t *msg, size_t len) { + char hex_char[len*2 + 2]; + ToHex_P(msg, len, hex_char, sizeof(hex_char)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbEZSPSend %s"), hex_char); + + SBuffer cmd(len+3); + + cmd.add8(EZSP_Serial.ezsp_seq++); + cmd.add8(0x00); + cmd.add8(0x01); + cmd.addBuffer(msg, len); + + + ZigbeeEZSPSendDATA(cmd.getBuffer(), cmd.len()); +} + + +void ZigbeeEZSPSendDATA_frm(bool send_cancel, uint8_t to_frm, uint8_t from_ack) { + SBuffer *buf = EZSP_Serial.to_packets[to_frm]; + if (!buf) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Buffer for packet %d is not allocated"), EZSP_Serial.to_send); + return; + } + + uint8_t control_byte = ((to_frm & 0x07) << 4) + (from_ack & 0x07); + buf->set8(0, control_byte); + + ZigbeeEZSPSendRaw(buf->getBuffer(), buf->len(), send_cancel); +} + + +void ZigbeeEZSPSendDATA(const uint8_t *msg, size_t len) { + + SBuffer *buf = new SBuffer(len+1); + buf->add8(0x00); + buf->addBuffer(msg, len); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: adding packet to_send, to_ack:%d, to_send:%d, to_end:%d"), + EZSP_Serial.to_ack, EZSP_Serial.to_send, EZSP_Serial.to_end); + uint8_t to_frm = EZSP_Serial.to_end; + if (EZSP_Serial.to_packets[to_frm]) { + delete EZSP_Serial.to_packets[to_frm]; + EZSP_Serial.to_packets[to_frm] = nullptr; + } + EZSP_Serial.to_packets[to_frm] = buf; + EZSP_Serial.to_end = (to_frm + 1) & 0x07; + + + + + + +} + + +int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) { + + + + uint16_t frame_control = buf.get16(1); + bool truncated = frame_control & 0x02; + bool overflow = frame_control & 0x01; + bool callbackPending = frame_control & 0x04; + bool security_enabled = frame_control & 0x8000; + if (truncated || overflow || security_enabled) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: specific frame_control 0x%04X"), frame_control); + } + + + for (uint32_t i=0; i> 4) + 1) & 0x07; + uint8_t ack_byte = 0x80 | EZSP_Serial.from_ack; + ZigbeeEZSPSendRaw(&ack_byte, 1, false); + + + + for (uint8_t i=0; i 0)) { + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int32_t size = strlen(XdrvMailbox.data); + + SBuffer buf((size+1)/2); + + while (size > 1) { + char stemp[3]; + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, nullptr, 16); + buf.add8(code); + size -= 2; + codes += 2; + } + if (send) { + + if (2 == XdrvMailbox.index) { ZigbeeEZSPSendDATA(buf.getBuffer(), buf.len()); } + else if (3 == XdrvMailbox.index) { ZigbeeEZSPSendRaw(buf.getBuffer(), buf.len(), true); } + else { ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); } + + } else { + + if (2 == XdrvMailbox.index) { ZigbeeProcessInput(buf); } + else if (3 == XdrvMailbox.index) { ZigbeeProcessInputRaw(buf); } + else { ZigbeeProcessInputEZSP(buf); } + } + } + ResponseCmndDone(); +} + + +void CmndZbEZSPReceive(void) +{ + CmndZbEZSPSendOrReceive(false); +} + +void CmndZbEZSPSend(void) +{ + CmndZbEZSPSendOrReceive(true); +} +#endif +# 773 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" +void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl) { + +#ifdef USE_ZIGBEE_ZNP + SBuffer buf(32+zcl.len); + buf.add8(Z_SREQ | Z_AF); + buf.add8(AF_DATA_REQUEST_EXT); + if (BAD_SHORTADDR == zcl.shortaddr) { + buf.add8(Z_Addr_Group); + buf.add64(zcl.groupaddr); + buf.add8(0xFF); + } else { + buf.add8(Z_Addr_ShortAddress); + buf.add64(zcl.shortaddr); + buf.add8(zcl.endpoint); + } + buf.add16(0x0000); + buf.add8(0x01); + buf.add16(zcl.cluster); + buf.add8(zcl.transacId); + buf.add8(0x30); + buf.add8(0x1E); + + buf.add16(3 + zcl.len + (zcl.manuf ? 2 : 0)); + buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); + if (zcl.manuf) { + buf.add16(zcl.manuf); + } + buf.add8(zcl.transacId); + buf.add8(zcl.cmd); + if (zcl.len > 0) { + buf.addBuffer(zcl.msg, zcl.len); + } + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +#endif + +#ifdef USE_ZIGBEE_EZSP + SBuffer buf(32+zcl.len); + + if (BAD_SHORTADDR != zcl.shortaddr) { + + buf.add16(EZSP_sendUnicast); + buf.add8(EMBER_OUTGOING_DIRECT); + buf.add16(zcl.shortaddr); + + buf.add16(Z_PROF_HA); + buf.add16(zcl.cluster); + buf.add8(0x01); + buf.add8(zcl.endpoint); + if (zcl.direct) { + buf.add16(0x0000); + } else { + buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); + } + buf.add16(zcl.groupaddr); + buf.add8(zcl.transacId); + + buf.add8(0x01); + + buf.add8(3 + zcl.len + (zcl.manuf ? 2 : 0)); + buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); + if (zcl.manuf) { + buf.add16(zcl.manuf); + } + buf.add8(zcl.transacId); + buf.add8(zcl.cmd); + if (zcl.len > 0) { + buf.addBuffer(zcl.msg, zcl.len); + } + } else { + + buf.add16(EZSP_sendMulticast); + + buf.add16(Z_PROF_HA); + buf.add16(zcl.cluster); + buf.add8(0x01); + buf.add8(zcl.endpoint); + if (zcl.direct) { + buf.add16(0x0000); + } else { + buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); + } + buf.add16(zcl.groupaddr); + buf.add8(zcl.transacId); + + buf.add8(0); + buf.add8(7); + buf.add8(0x01); + + buf.add8(3 + zcl.len + (zcl.manuf ? 2 : 0)); + buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); + if (zcl.manuf) { + buf.add16(zcl.manuf); + } + buf.add8(zcl.transacId); + buf.add8(zcl.cmd); + if (zcl.len > 0) { + buf.addBuffer(zcl.msg, zcl.len); + } + } + + ZigbeeEZSPSendCmd(buf.buf(), buf.len()); +#endif +} + + + + + +void ZigbeeOutputLoop(void) { +#ifdef USE_ZIGBEE_EZSP + + if (EZSP_Serial.to_send != EZSP_Serial.to_end) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Something to_send, to_ack:%d, to_send:%d, to_end:%d"), + EZSP_Serial.to_ack, EZSP_Serial.to_send, EZSP_Serial.to_end); + + ZigbeeEZSPSendDATA_frm(true, EZSP_Serial.to_send, EZSP_Serial.from_ack); + + EZSP_Serial.to_send = (EZSP_Serial.to_send + 1) & 0x07; + } +#endif +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" +#ifdef USE_ZIGBEE + +#ifdef USE_ZIGBEE_EZSP +# 33 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" +#define XM_SOH 0x01 +#define XM_EOT 0x04 +#define XM_ACK 0x06 +#define XM_CR 0x0d +#define XM_NAK 0x15 +#define XM_CAN 0x18 +#define XM_SUB 0x1a + +enum ZbUploadSteps { ZBU_IDLE, ZBU_INIT, + ZBU_SOFTWARE_RESET, ZBU_SOFTWARE_SEND, ZBU_HARDWARE_RESET, ZBU_PROMPT, + ZBU_SYNC, ZBU_UPLOAD, ZBU_EOT, ZBU_COMPLETE, ZBU_DONE, ZBU_ERROR, ZBU_FINISH }; + +const uint8_t PIN_ZIGBEE_BOOTLOADER = 5; + +struct ZBUPLOAD { + uint32_t ota_size = 0; + uint32_t sector_cursor = 0; + uint32_t sector_counter = 0; + uint32_t byte_counter = 0; + char *buffer; + uint8_t ota_step = ZBU_IDLE; + uint8_t bootloader = 0; + uint8_t state = ZBU_IDLE; +} ZbUpload; + + + + + +uint32_t ZigbeeUploadFlashStart(void) { + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; +} + +uint32_t ZigbeeUploadAvailable(void) { + int available = ZbUpload.ota_size - ZbUpload.byte_counter; + if (available < 0) { available = 0; } + return available; +} + +char ZigbeeUploadFlashRead(void) { + if (0 == ZbUpload.byte_counter) { + if (!(ZbUpload.buffer = (char *)malloc(SPI_FLASH_SEC_SIZE))) { + return (-1); + } + ZbUpload.sector_counter = ZigbeeUploadFlashStart(); + } + + uint32_t index = ZbUpload.byte_counter % SPI_FLASH_SEC_SIZE; + if (0 == index) { + ESP.flashRead(ZbUpload.sector_counter * SPI_FLASH_SEC_SIZE, (uint32_t*)ZbUpload.buffer, SPI_FLASH_SEC_SIZE); + ZbUpload.sector_counter++; + } + + char data = ZbUpload.buffer[index]; + ZbUpload.byte_counter++; + + if (ZbUpload.byte_counter > ZbUpload.ota_size) { + + + data = XM_SUB; + + } + return data; +} + + + + + + +const uint32_t XMODEM_FLUSH_DELAY = 1000; + +const uint8_t XMODEM_SYNC_TIMEOUT = 30; + +const uint8_t XMODEM_MAX_RETRY = 30; + +const uint8_t XMODEM_PACKET_SIZE = 128; + +struct XMODEM { + uint32_t timeout = 0; + uint32_t delay = 0; + uint32_t flush_delay = 0xFFFFFFFF; + uint32_t filepos = 0; + int crcBuf = 0; + uint8_t packetNo = 1; + uint8_t checksumBuf = 0; + bool oldChecksum; +} XModem; + + +void XModemOutputByte(uint8_t out_char) { + XModem.checksumBuf += out_char; + + XModem.crcBuf = XModem.crcBuf ^ (int) out_char << 8; + for (uint32_t i = 0; i < 8; i++) { + if (XModem.crcBuf & 0x8000) { + XModem.crcBuf = XModem.crcBuf << 1 ^ 0x1021; + } else { + XModem.crcBuf = XModem.crcBuf << 1; + } + } + + ZigbeeSerial->write(out_char); +} + + + +char XModemWaitACK(void) +{ + char in_char; + do { + uint8_t i = 0; + while (!ZigbeeSerial->available()) { + delayMicroseconds(100); + i++; + if (i > 200) { return -1; } + } + in_char = ZigbeeSerial->read(); + if (XM_CAN == in_char) { return XM_CAN; } + } while ((in_char != XM_NAK) && (in_char != XM_ACK) && (in_char != 'C')); + return in_char; +} + +bool XModemSendPacket(uint32_t packet_no) { + XModem.filepos = ZbUpload.byte_counter; + + + uint32_t retries = 0; + char in_char; + do { + + + ZbUpload.byte_counter = XModem.filepos; + + + XModem.checksumBuf = 0x00; + XModem.crcBuf = 0x00; + + + ZigbeeSerial->write(XM_SOH); + ZigbeeSerial->write(packet_no); + ZigbeeSerial->write(~packet_no); + for (uint32_t i = 0; i < XMODEM_PACKET_SIZE; i++) { + in_char = ZigbeeUploadFlashRead(); + XModemOutputByte(in_char); + } + + + if (XModem.oldChecksum) { + ZigbeeSerial->write((char)XModem.checksumBuf); + } else { + ZigbeeSerial->write((char)(XModem.crcBuf >> 8)); + ZigbeeSerial->write((char)(XModem.crcBuf & 0xFF)); + } + in_char = XModemWaitACK(); + if (XM_CAN == in_char) { return false; } + retries++; + if (retries > XMODEM_MAX_RETRY) { return false; } + } while (in_char != XM_ACK); + return true; +} + + + + + + + +void ZigbeeUploadSetSoftwareBootloader() { + + SBuffer buf(4); + buf.add16(EZSP_launchStandaloneBootloader); + buf.add8(0x01); + ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); +} + +void ZigbeeUploadSetBootloader(uint8_t state) { + pinMode(PIN_ZIGBEE_BOOTLOADER, OUTPUT); + digitalWrite(PIN_ZIGBEE_BOOTLOADER, state); + digitalWrite(Pin(GPIO_ZIGBEE_RST), 0); + delay(100); + digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); +} + +bool ZigbeeUploadBootloaderPrompt(void) { + + + + + uint8_t serial_buffer[255]; + uint32_t buf_len = 0; + + while (ZigbeeSerial->available()) { + yield(); + char bootloader_byte = ZigbeeSerial->read(); + + if (((uint8_t)bootloader_byte >=0) && (buf_len < sizeof(serial_buffer) -2)) { + serial_buffer[buf_len++] = bootloader_byte; + } + + if (ZbUpload.byte_counter != 4) { + switch (ZbUpload.byte_counter) { + case 0: + if ('B' == bootloader_byte) { ZbUpload.byte_counter++; } break; + case 1: + if ('L' == bootloader_byte) { ZbUpload.byte_counter++; } break; + case 2: + if (' ' == bootloader_byte) { ZbUpload.byte_counter++; } break; + case 3: + if ('>' == bootloader_byte) { + ZbUpload.byte_counter++; + XModem.flush_delay = millis() + XMODEM_FLUSH_DELAY; + XModem.delay = XModem.flush_delay + XMODEM_FLUSH_DELAY; + } + } + } + } + + if (buf_len) { + char hex_char[256]; + ToHex_P(serial_buffer, buf_len, hex_char, 256); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("XMD: Rcvd %s"), hex_char); + } + + return ((4 == ZbUpload.byte_counter) && (millis() > XModem.flush_delay)); +} + +bool ZigbeeUploadXmodem(void) { + switch (ZbUpload.ota_step) { + case ZBU_IDLE: { + return false; + } +#ifdef ZIGBEE_BOOTLOADER_SOFTWARE_RESET_FIRST + case ZBU_INIT: { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init bootloader")); + ZbUpload.ota_step = ZBU_SOFTWARE_RESET; + return false; + } + case ZBU_SOFTWARE_RESET: { + SBuffer buf(4); + buf.add16(EZSP_launchStandaloneBootloader); + buf.add8(0x01); + ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); + XModem.timeout = millis() + (10 * 1000); + ZbUpload.ota_step = ZBU_SOFTWARE_SEND; + return false; + } + case ZBU_SOFTWARE_SEND: { + if (millis() > XModem.timeout) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader software reset send timeout")); + ZbUpload.ota_step = ZBU_HARDWARE_RESET; + return true; + } + if (EZSP_Serial.to_send == EZSP_Serial.to_end) { + ZbUpload.bootloader = ZBU_SOFTWARE_RESET; + XModem.timeout = millis() + (10 * 1000); + XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); + ZbUpload.byte_counter = 0; + ZbUpload.ota_step = ZBU_PROMPT; + } + break; + } + case ZBU_HARDWARE_RESET: { + ZbUpload.bootloader = ZBU_HARDWARE_RESET; + ZigbeeUploadSetBootloader(0); + XModem.timeout = millis() + (30 * 1000); + XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); + ZbUpload.byte_counter = 0; + ZbUpload.ota_step = ZBU_PROMPT; + break; + } + case ZBU_PROMPT: { + if (millis() > XModem.timeout) { + if (ZBU_SOFTWARE_RESET == ZbUpload.bootloader) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader software reset timeout")); + ZbUpload.ota_step = ZBU_HARDWARE_RESET; + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader hardware reset timeout")); + ZbUpload.ota_step = ZBU_ERROR; + } + return true; + } +#else + case ZBU_INIT: { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init bootloader")); + ZigbeeUploadSetBootloader(0); + XModem.timeout = millis() + (30 * 1000); + XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); + ZbUpload.byte_counter = 0; + ZbUpload.ota_step = ZBU_PROMPT; + break; + } + case ZBU_PROMPT: { + if (millis() > XModem.timeout) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader timeout")); + ZbUpload.ota_step = ZBU_ERROR; + return true; + } +#endif + else if (!ZigbeeSerial->available() && (millis() < XModem.flush_delay)) { + + + if (millis() > XModem.delay) { + ZigbeeSerial->write(XM_CR); + XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); + } + } else { + + + + + + + if (ZigbeeUploadBootloaderPrompt()) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init sync")); + ZigbeeSerial->flush(); + ZigbeeSerial->write('1'); + if (ssleep > 0) { + ssleep = 1; + } + XModem.timeout = millis() + (XMODEM_SYNC_TIMEOUT * 1000); + ZbUpload.ota_step = ZBU_SYNC; + } + } + break; + } + case ZBU_SYNC: { + if (millis() > XModem.timeout) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: SYNC timeout")); + ZbUpload.ota_step = ZBU_ERROR; + return true; + } + + if (ZigbeeSerial->available()) { + char xmodem_sync = ZigbeeSerial->read(); + if (('C' == xmodem_sync) || (XM_NAK == xmodem_sync)) { + + XModem.oldChecksum = (xmodem_sync == XM_NAK); + XModem.packetNo = 1; + ZbUpload.byte_counter = 0; + ZbUpload.ota_step = ZBU_UPLOAD; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init packet send")); + } + } + break; + } + case ZBU_UPLOAD: { + if (ZigbeeUploadAvailable()) { + if (!XModemSendPacket(XModem.packetNo)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Packet send failed")); + ZbUpload.ota_step = ZBU_ERROR; + return true; + } + XModem.packetNo++; + } else { + + + + ZigbeeSerial->write(XM_EOT); + XModem.timeout = millis() + (30 * 1000); + ZbUpload.ota_step = ZBU_EOT; + } + break; + } + case ZBU_EOT: { + + + + + + if (millis() > XModem.timeout) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: EOT ACK timeout")); + ZbUpload.ota_step = ZBU_ERROR; + return true; + } + if (ZigbeeSerial->available()) { + char xmodem_ack = XModemWaitACK(); + if (XM_ACK == xmodem_ack) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: " D_SUCCESSFUL)); + XModem.timeout = millis() + (30 * 1000); + ZbUpload.byte_counter = 0; + ZbUpload.ota_step = ZBU_COMPLETE; + } + } + break; + } + case ZBU_COMPLETE: { + if (millis() > XModem.timeout) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader timeout")); + ZbUpload.ota_step = ZBU_ERROR; + return true; + } else { +# 433 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" + if (ZigbeeUploadBootloaderPrompt()) { + ZbUpload.state = ZBU_COMPLETE; + ZbUpload.ota_step = ZBU_DONE; + } + } + break; + } + case ZBU_ERROR: + ZbUpload.state = ZBU_ERROR; + case ZBU_DONE: { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: " D_RESTARTING)); + ZigbeeUploadSetBootloader(1); + if (1 == ssleep) { + ssleep = Settings.sleep; + } + + ZbUpload.ota_step = ZBU_FINISH; + break; + } + case ZBU_FINISH: { + + break; + } + } + return true; +} + + + + + +bool ZigbeeUploadOtaReady(void) { + return (ZBU_INIT == ZbUpload.ota_step); +} + +bool ZigbeeUploadFinish(void) { + return (ZBU_FINISH == ZbUpload.ota_step); +} + +uint8_t ZigbeeUploadInit(void) { + if (!PinUsed(GPIO_ZIGBEE_RST) && (ZigbeeSerial == nullptr)) { return 1; } + + ZbUpload.sector_counter = ZigbeeUploadFlashStart(); + ZbUpload.sector_cursor = 0; + ZbUpload.ota_size = 0; + ZbUpload.ota_step = ZBU_IDLE; + ZbUpload.state = ZBU_IDLE; + return 0; +} + +bool ZigbeeUploadWriteBuffer(uint8_t *buf, size_t size) { + + + if (0 == ZbUpload.sector_cursor) { + ESP.flashEraseSector(ZbUpload.sector_counter); + } + ZbUpload.sector_cursor++; + ESP.flashWrite((ZbUpload.sector_counter * SPI_FLASH_SEC_SIZE) + ((ZbUpload.sector_cursor-1) * 2048), (uint32_t*)buf, size); + ZbUpload.ota_size += size; + if (2 == ZbUpload.sector_cursor) { + ZbUpload.sector_cursor = 0; + ZbUpload.sector_counter++; + if (ZbUpload.sector_counter > (SPIFFS_END -2)) { + return false; + } + } + return true; +} + +void ZigbeeUploadDone(void) { + ZbUpload.ota_step = ZBU_INIT; + ZbUpload.state = ZBU_UPLOAD; +} + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_ZIGBEE_XFER "zx" + +const char HTTP_SCRIPT_XFER_STATE[] PROGMEM = + "function z9(){" + "if(x!=null){x.abort();}" + "x=new XMLHttpRequest();" + "x.onreadystatechange=function(){" + "if(x.readyState==4&&x.status==200){" + "var s=x.responseText;" + "if(s!=7){" + "location.href='/u3';" + "}" + "}" + "};" + "x.open('GET','" WEB_HANDLE_ZIGBEE_XFER "?z=1',true);" + "x.send();" + "lt=setTimeout(z9,950);" + "}" + "wl(z9);"; + +void HandleZigbeeXfer(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + if (Webserver->hasArg("z")) { + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%d"), ZbUpload.state); + WSContentEnd(); + if (ZBU_ERROR == ZbUpload.state) { + Web.upload_error = 7; + } + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_UPLOAD_TRANSFER)); + + WSContentStart_P(S_INFORMATION); + WSContentSend_P(HTTP_SCRIPT_XFER_STATE); + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPLOAD_TRANSFER " ...
")); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + +#endif + +#endif + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" +#ifdef USE_ZIGBEE + +#define XDRV_23 23 + +const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" +#ifdef USE_ZIGBEE_ZNP + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEEZNPRECEIVE "|" +#endif +#ifdef USE_ZIGBEE_EZSP + D_CMND_ZIGBEE_EZSP_SEND "|" D_CMND_ZIGBEE_EZSP_RECEIVE "|" D_CMND_ZIGBEE_EZSP_LISTEN "|" +#endif + D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" + D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" + D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" + D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA + ; + +void (* const ZigbeeCommand[])(void) PROGMEM = { +#ifdef USE_ZIGBEE_ZNP + &CmndZbZNPSend, &CmndZbZNPReceive, +#endif +#ifdef USE_ZIGBEE_EZSP + &CmndZbEZSPSend, &CmndZbEZSPReceive, &CmndZbEZSPListen, +#endif + &CmndZbPermitJoin, + &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, + &CmndZbForget, &CmndZbSave, &CmndZbName, + &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, + &CmndZbLight, &CmndZbRestore, &CmndZbBindState, + &CmndZbConfig, CmndZbData, + }; + + + + +void ZigbeeInit(void) +{ + + + + + + if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { + if (0 == Settings.zb_channel) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Randomizing Zigbee parameters, please check with 'ZbConfig'")); + uint64_t mac64 = 0; + WiFi.macAddress((uint8_t*) &mac64); + uint32_t esp_id = ESP_getChipId(); +#ifdef ESP8266 + uint32_t flash_id = ESP.getFlashChipId(); +#else + uint32_t flash_id = 0; +#endif + + uint16_t pan_id = (mac64 & 0x3FFF); + if (0x0000 == pan_id) { pan_id = 0x0001; } + if (0x3FFF == pan_id) { pan_id = 0x3FFE; } + Settings.zb_pan_id = pan_id; + + Settings.zb_ext_panid = 0xCCCCCCCC00000000L | (mac64 & 0x00000000FFFFFFFFL); + Settings.zb_precfgkey_l = (mac64 << 32) | (esp_id << 16) | flash_id; + Settings.zb_precfgkey_h = (mac64 << 32) | (esp_id << 16) | flash_id; + Settings.zb_channel = USE_ZIGBEE_CHANNEL; + Settings.zb_txradio_dbm = USE_ZIGBEE_TXRADIO_DBM; + } + + if (Settings.zb_txradio_dbm < 0) { + Settings.zb_txradio_dbm = -Settings.zb_txradio_dbm; +#ifdef USE_ZIGBEE_EZSP + EZ_reset_config = true; +#endif + SettingsSave(2); + } + } + + +#ifdef USE_ZIGBEE_ZNP + ZNP_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h); +#endif +#ifdef USE_ZIGBEE_EZSP + EZ_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h, Settings.zb_txradio_dbm); +#endif + + ZigbeeInitSerial(); +} + + + + + +#ifdef USE_ZIGBEE_ZNP + +const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = + { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; + +#endif + +void CmndZbReset(void) { + if (ZigbeeSerial) { + switch (XdrvMailbox.payload) { + case 1: +#ifdef USE_ZIGBEE_ZNP + ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); +#endif + eraseZigbeeDevices(); + case 2: + Settings.zb_txradio_dbm = - abs(Settings.zb_txradio_dbm); + restart_flag = 2; +#ifdef USE_ZIGBEE_ZNP + ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING)); +#endif +#ifdef USE_ZIGBEE_EZSP + ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_EZSP " " D_JSON_RESET_AND_RESTARTING)); +#endif + break; + default: + ResponseCmndChar_P(PSTR("1 or 2 to reset")); + } + } +} +# 158 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" +void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf, + uint16_t cluster, uint8_t cmd, const char *param) { + size_t size = param ? strlen(param) : 0; + SBuffer buf((size+2)/2); + + if (param) { + while (*param) { + uint8_t code = parseHex_P(¶m, 2); + buf.add8(code); + } + } + + if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) { + + endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), + shortaddr, groupaddr, cluster, endpoint, cmd, param); + + if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); + return; + } + + + + uint8_t seq = zigbee_devices.getNextSeqNumber(shortaddr); + ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ + shortaddr, + groupaddr, + cluster , + endpoint, + cmd, + manuf, + clusterSpecific , + true , + false , + seq, + buf.getBuffer(), buf.len() + })); + + if (clusterSpecific) { +#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES + sendHueUpdate(shortaddr, groupaddr, cluster, endpoint); +#endif + } +} + + + + + + +void ZbApplyMultiplier(double &val_d, int8_t multiplier) { + if ((0 != multiplier) && (1 != multiplier)) { + if (multiplier > 0) { + val_d = val_d / multiplier; + } else { + val_d = val_d * (-multiplier); + } + } +} + + + + +bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr, uint8_t transid) { + double val_d = attr.getFloat(); + const char * val_str = attr.getStr(); + + if (attr.key_is_str) { return false; } + if (attr.isNum() && (1 != attr.attr_multiplier)) { + ZbApplyMultiplier(val_d, attr.attr_multiplier); + } + buf.add8(0); + buf.add8(transid); + buf.add16(attr.key.id.attr_id); + buf.add8(0); + int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); + if (res < 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Error for Tuya attribute type %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); + return false; + } + return true; +} + + + + +bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok) { + double val_d = attr.getFloat(); + const char * val_str = attr.getStr(); + + if (attr.key_is_str) { return false; } + if (attr.isNum() && (1 != attr.attr_multiplier)) { + ZbApplyMultiplier(val_d, attr.attr_multiplier); + } + + + buf.add16(attr.key.id.attr_id); + if (prepend_status_ok) { + buf.add8(Z_SUCCESS); + } + buf.add8(attr.attr_type); + int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); + if (res < 0) { + + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Unsupported attribute type %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); + return false; + } + return true; +} + + + + + +void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZigbeeZCLSendMessage & packet) { + SBuffer buf(200); + + if (nullptr == XdrvMailbox.command) { + XdrvMailbox.command = (char*) ""; + } + + + for (auto key : val_pubwrite.getObject()) { + JsonParserToken value = key.getValue(); + + Z_attribute attr; + attr.setKeyName(key.getStr()); + if (Z_parseAttributeKey(attr)) { + + + + if (0xFFFF == packet.cluster) { + packet.cluster = attr.key.id.cluster; + } else if (packet.cluster != attr.key.id.cluster) { + ResponseCmndChar_P(PSTR("No more than one cluster id per command")); + return; + } + + } else { + if (attr.key_is_str) { + Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute "), key); + return; + } + if (Zunk == attr.attr_type) { + Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute type for attribute "), key); + return; + } + } + + + if (value.isStr()) { + attr.setStr(value.getStr()); + } else if (value.isNum()) { + attr.setFloat(value.getFloat()); + } + + double val_d = 0; + const char* val_str = ""; + + + if (packet.cmd != ZCL_CONFIGURE_REPORTING) { + if ((packet.cluster == 0XEF00) && (packet.cmd == ZCL_WRITE_ATTRIBUTES)) { + + if (buf.len() > 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Only 1 attribute allowed for Tuya")); + return; + } + packet.clusterSpecific = true; + packet.cmd = 0x00; + if (!ZbTuyaWrite(buf, attr, zigbee_devices.getNextSeqNumber(packet.shortaddr))) { + return; + } + } else if (!ZbAppendWriteBuf(buf, attr, packet.cmd == ZCL_READ_ATTRIBUTES_RESPONSE)) { + return; + } + } else { + + + if (!value.isObject()) { + ResponseCmndChar_P(PSTR("Config requires JSON objects")); + return; + } + JsonParserObject attr_config = value.getObject(); + bool attr_direction = false; + + uint32_t dir = attr_config.getUInt(PSTR("DirectionReceived"), 0); + if (dir) { attr_direction = true; } + + + uint16_t attr_min_interval = attr_config.getUInt(PSTR("MinInterval"), 0xFFFF); + uint16_t attr_max_interval = attr_config.getUInt(PSTR("MaxInterval"), 0xFFFF); + + + JsonParserToken val_attr_rc = attr_config[PSTR("ReportableChange")]; + if (val_attr_rc) { + val_d = val_attr_rc.getFloat(); + val_str = val_attr_rc.getStr(); + ZbApplyMultiplier(val_d, attr.attr_multiplier); + } + + + uint16_t attr_timeout = attr_config.getUInt(PSTR("TimeoutPeriod"), 0x0000); + + bool attr_discrete = Z_isDiscreteDataType(attr.attr_type); + + + + buf.add8(attr_direction ? 0x01 : 0x00); + buf.add16(attr.key.id.attr_id); + if (attr_direction) { + buf.add16(attr_timeout); + } else { + buf.add8(attr.attr_type); + buf.add16(attr_min_interval); + buf.add16(attr_max_interval); + if (!attr_discrete) { + int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); + if (res < 0) { + Response_P(PSTR("{\"%s\":\"%s'%s' 0x%02X\"}"), XdrvMailbox.command, PSTR("Unsupported attribute type "), key, attr.attr_type); + return; + } + } + } + } + } + + + if (0 == buf.len()) { + ResponseCmndChar_P(PSTR("No attribute in list")); + return; + } + + + packet.transacId = zigbee_devices.getNextSeqNumber(packet.shortaddr); + packet.msg = buf.getBuffer(); + packet.len = buf.len(); + ZigbeeZCLSend_Raw(packet); + ResponseCmndDone(); +} + + +void ZbSendSend(class JsonParserToken val_cmd, uint16_t device, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint16_t manuf) { + uint8_t cmd = 0; + String cmd_str = ""; + const char *cmd_s = ""; + bool clusterSpecific = true; + + static char delim[] = ", "; + + + + if (val_cmd.isObject()) { + + JsonParserObject cmd_obj = val_cmd.getObject(); + int32_t cmd_size = cmd_obj.size(); + if (cmd_size > 1) { + Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); + return; + } else if (1 == cmd_size) { + + JsonParserKey key = cmd_obj.getFirstElement(); + JsonParserToken value = key.getValue(); + uint32_t x = 0, y = 0, z = 0; + uint16_t cmd_var; + uint16_t local_cluster_id; + + const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.getStr(), &local_cluster_id, &cmd_var); + if (tasmota_cmd) { + cmd_str = tasmota_cmd; + } else { + Response_P(PSTR("Unrecognized zigbee command: %s"), key.getStr()); + return; + } + + if (0xFFFF == cluster) { + cluster = local_cluster_id; + } else if (cluster != local_cluster_id) { + ResponseCmndChar_P(PSTR("No more than one cluster id per command")); + return; + } + + + if (value.isNum()) { + x = value.getUInt(); + + + + + + } else { + + const char *s_const = value.getStr(nullptr); + + if (s_const != nullptr) { + char s[strlen(s_const)+1]; + strcpy(s, s_const); + if ((nullptr != s) && (0x00 != *s)) { + char *sval = strtok(s, delim); + if (sval) { + x = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + y = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + z = ZigbeeAliasOrNumber(sval); + } + } + } + } + } + } + + + if (0xFF == cmd_var) { + cmd = x; + x = y; + y = z; + } else { + cmd = cmd_var; + } + cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); + + cmd_s = cmd_str.c_str(); + } else { + + } + } else if (val_cmd.isStr()) { + + + + + + const char * data = val_cmd.getStr(); + uint16_t local_cluster_id = parseHex(&data, 4); + + + if (0xFFFF == cluster) { + cluster = local_cluster_id; + } else if (cluster != local_cluster_id) { + ResponseCmndChar_P(PSTR("No more than one cluster id per command")); + return; + } + + + if (('_' == *data) || ('!' == *data)) { + if ('_' == *data) { clusterSpecific = false; } + data++; + } else { + ResponseCmndChar_P(PSTR("Wrong delimiter for payload")); + return; + } + + cmd = parseHex(&data, 2); + + + + if ('/' == *data) { data++; } + + cmd_s = data; + } else { + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLSend device: 0x%04X, group: 0x%04X, endpoint:%d, cluster:0x%04X, cmd:0x%02X, send:\"%s\""), + device, groupaddr, endpoint, cluster, cmd, cmd_s); + zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, manuf, cluster, cmd, cmd_s); + ResponseCmndDone(); +} + + + +void ZbSendRead(JsonParserToken val_attr, ZigbeeZCLSendMessage & packet) { +# 546 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + size_t attrs_len = 0; + uint8_t* attrs = nullptr; + size_t attr_item_len = 2; + size_t attr_item_offset = 0; + if (ZCL_READ_REPORTING_CONFIGURATION == packet.cmd) { + attr_item_len = 3; + attr_item_offset = 1; + } + + if (val_attr.isArray()) { + + JsonParserArray attr_arr = val_attr.getArray(); + attrs_len = attr_arr.size() * attr_item_len; + attrs = (uint8_t*) calloc(attrs_len, 1); + + uint32_t i = 0; + for (auto value : attr_arr) { + uint16_t val = value.getUInt(); + i += attr_item_offset; + attrs[i++] = val & 0xFF; + attrs[i++] = val >> 8; + i += attr_item_len - 2 - attr_item_offset; + } + } else if (val_attr.isObject()) { + + JsonParserObject attr_obj = val_attr.getObject(); + attrs_len = attr_obj.size() * attr_item_len; + attrs = (uint8_t*) calloc(attrs_len, 1); + uint32_t actual_attr_len = 0; + + + for (auto key : attr_obj) { + JsonParserToken value = key.getValue(); + + bool found = false; + + for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + bool match = false; + uint16_t local_attr_id = pgm_read_word(&converter->attribute); + uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); + + + if ((pgm_read_word(&converter->name_offset)) && (0 == strcasecmp_P(key.getStr(), Z_strings + pgm_read_word(&converter->name_offset)))) { + + + + if (!(value.getBool()) && attr_item_offset) { + + attrs[actual_attr_len] = 0x01; + } + actual_attr_len += attr_item_offset; + attrs[actual_attr_len++] = local_attr_id & 0xFF; + attrs[actual_attr_len++] = local_attr_id >> 8; + actual_attr_len += attr_item_len - 2 - attr_item_offset; + found = true; + + if (0xFFFF == packet.cluster) { + packet.cluster = local_cluster_id; + } else if (packet.cluster != local_cluster_id) { + ResponseCmndChar_P(PSTR("No more than one cluster id per command")); + if (attrs) { free(attrs); } + return; + } + break; + } + } + if (!found) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Unknown attribute name (ignored): %s"), key); + } + } + + attrs_len = actual_attr_len; + } else { + + if (0xFFFF != packet.cluster) { + uint16_t val = val_attr.getUInt(); + attrs_len = attr_item_len; + attrs = (uint8_t*) calloc(attrs_len, 1); + attrs[0 + attr_item_offset] = val & 0xFF; + attrs[1 + attr_item_offset] = val >> 8; + } + } + + if (attrs_len > 0) { + + packet.transacId = zigbee_devices.getNextSeqNumber(packet.shortaddr); + packet.msg = attrs; + packet.len = attrs_len; + ZigbeeZCLSend_Raw(packet); + ResponseCmndDone(); + } else { + ResponseCmndChar_P(PSTR("Missing parameters")); + } + + if (attrs) { free(attrs); } +} +# 656 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" +void CmndZbSend(void) { +# 668 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + + uint16_t device = BAD_SHORTADDR; + uint16_t groupaddr = 0x0000; + uint16_t cluster = 0xFFFF; + uint8_t endpoint = 0x00; + uint16_t manuf = 0x0000; + + + + JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)]; + if (val_device) { + device = zigbee_devices.parseDeviceParam(val_device.getStr()); + if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + } + if (BAD_SHORTADDR == device) { + JsonParserToken val_group = root[PSTR(D_CMND_ZIGBEE_GROUP)]; + if (val_group) { + groupaddr = val_group.getUInt(); + } else { + ResponseCmndChar_P(PSTR("Unknown device")); + return; + } + } + + + + + cluster = root.getUInt(PSTR(D_CMND_ZIGBEE_CLUSTER), cluster); + endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), endpoint); + manuf = root.getUInt(PSTR(D_CMND_ZIGBEE_MANUF), manuf); + + + if (BAD_SHORTADDR == device) { + endpoint = 0xFF; + } else if (0 == endpoint) { + endpoint = zigbee_devices.findFirstEndpoint(device); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: guessing endpoint %d"), endpoint); + } + if (0 == endpoint) { + ResponseCmndChar_P(PSTR("Missing endpoint")); + return; + } + + + + JsonParserToken val_cmd = root[PSTR(D_CMND_ZIGBEE_SEND)]; + JsonParserToken val_read = root[PSTR(D_CMND_ZIGBEE_READ)]; + JsonParserToken val_write = root[PSTR(D_CMND_ZIGBEE_WRITE)]; + JsonParserToken val_publish = root[PSTR(D_CMND_ZIGBEE_REPORT)]; + JsonParserToken val_response = root[PSTR(D_CMND_ZIGBEE_RESPONSE)]; + JsonParserToken val_read_config = root[PSTR(D_CMND_ZIGBEE_READ_CONFIG)]; + JsonParserToken val_config = root[PSTR(D_CMND_ZIGBEE_CONFIG)]; + uint32_t multi_cmd = ((bool)val_cmd) + ((bool)val_read) + ((bool)val_write) + ((bool)val_publish) + + ((bool)val_response) + ((bool)val_read_config) + ((bool)val_config); + if (multi_cmd > 1) { + ResponseCmndChar_P(PSTR("Can only have one of: 'Send', 'Read', 'Write', 'Report', 'Reponse', 'ReadConfig' or 'Config'")); + return; + } + + + + ZigbeeZCLSendMessage packet({ + device, + groupaddr, + cluster , + endpoint, + ZCL_READ_ATTRIBUTES, + manuf, + false , + false , + false , + 0, + nullptr, 0 + }); + + if (val_cmd) { + + + ZbSendSend(val_cmd, device, groupaddr, cluster, endpoint, manuf); + } else if (val_read) { + + + packet.cmd = ZCL_READ_ATTRIBUTES; + ZbSendRead(val_read, packet); + } else if (val_write) { + + if (!val_write.isObject()) { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + + packet.cmd = ZCL_WRITE_ATTRIBUTES; + ZbSendReportWrite(val_write, packet); + } else if (val_publish) { + + + if (!val_publish.isObject()) { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + packet.cmd = ZCL_REPORT_ATTRIBUTES; + ZbSendReportWrite(val_publish, packet); + } else if (val_response) { + + + if (!val_response.isObject()) { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + packet.cmd = ZCL_READ_ATTRIBUTES_RESPONSE; + ZbSendReportWrite(val_response, packet); + } else if (val_read_config) { + + + packet.cmd = ZCL_READ_REPORTING_CONFIGURATION; + ZbSendRead(val_read_config, packet); + } else if (val_config) { + + + if (!val_config.isObject()) { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + packet.cmd = ZCL_CONFIGURE_REPORTING; + ZbSendReportWrite(val_config, packet); + } else { + Response_P(PSTR("Missing zigbee 'Send', 'Write', 'Report' or 'Response'")); + return; + } +} + + + + +void ZbBindUnbind(bool unbind) { + + + + + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + + uint16_t srcDevice = BAD_SHORTADDR; + uint16_t dstDevice = BAD_SHORTADDR; + uint64_t dstLongAddr = 0; + uint8_t endpoint = 0x00; + uint8_t toendpoint = 0x01; + uint16_t toGroup = 0x0000; + uint16_t cluster = 0; + uint32_t group = 0xFFFFFFFF; + + + + srcDevice = zigbee_devices.parseDeviceParam(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr)); + if (BAD_SHORTADDR == srcDevice) { ResponseCmndChar_P(PSTR("Unknown source device")); return; } + + uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice); + if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; } + + endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), endpoint); + if (0 == endpoint) { endpoint = zigbee_devices.findFirstEndpoint(srcDevice); } + + JsonParserToken val_cluster = root[PSTR(D_CMND_ZIGBEE_CLUSTER)]; + if (val_cluster) { + cluster = val_cluster.getUInt(cluster); + if (0 == cluster) { + zigbeeFindAttributeByName(val_cluster.getStr(), &cluster, nullptr, nullptr); + } + } + + + JsonParserToken to_group = root[PSTR("ToGroup")]; + if (to_group) { toGroup = to_group.getUInt(toGroup); } + + + + + + JsonParserToken dst_device = root[PSTR("ToDevice")]; + + + if ((!to_group) && (!dst_device)) { + dstDevice = 0x0000; + } + + if ((dst_device) || (BAD_SHORTADDR != dstDevice)) { + if (BAD_SHORTADDR == dstDevice) { + dstDevice = zigbee_devices.parseDeviceParam(dst_device.getStr(nullptr)); + if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + } + if (0x0000 == dstDevice) { + dstLongAddr = localIEEEAddr; + } else { + dstLongAddr = zigbee_devices.getDeviceLongAddr(dstDevice); + } + if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; } + + toendpoint = root.getUInt(PSTR("ToEndpoint"), toendpoint); + } + + + if (to_group && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; } + if (!to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; } + +#ifdef USE_ZIGBEE_ZNP + SBuffer buf(34); + buf.add8(Z_SREQ | Z_ZDO); + if (unbind) { + buf.add8(ZDO_UNBIND_REQ); + } else { + buf.add8(ZDO_BIND_REQ); + } + buf.add16(srcDevice); + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + if (dstLongAddr) { + buf.add8(Z_Addr_IEEEAddress); + buf.add64(dstLongAddr); + buf.add8(toendpoint); + } else { + buf.add8(Z_Addr_Group); + buf.add16(toGroup); + } + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +#endif + +#ifdef USE_ZIGBEE_EZSP + SBuffer buf(24); + + + buf.add64(srcLongAddr); + buf.add8(endpoint); + buf.add16(cluster); + if (dstLongAddr) { + buf.add8(Z_Addr_IEEEAddress); + buf.add64(dstLongAddr); + buf.add8(toendpoint); + } else { + buf.add8(Z_Addr_Group); + buf.add16(toGroup); + } + + EZ_SendZDO(srcDevice, unbind ? ZDO_UNBIND_REQ : ZDO_BIND_REQ, buf.buf(), buf.len()); +#endif + + ResponseCmndDone(); +} + + + + +void CmndZbBind(void) { + ZbBindUnbind(false); +} + + + + +void CmndZbUnbind(void) { + ZbBindUnbind(true); +} + + + + + +void CmndZbBindState(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + uint8_t index = XdrvMailbox.index - 1; + +#ifdef USE_ZIGBEE_ZNP + SBuffer buf(10); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_MGMT_BIND_REQ); + buf.add16(shortaddr); + buf.add8(index); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +#endif + + +#ifdef USE_ZIGBEE_EZSP + + uint8_t buf[] = { index }; + + EZ_SendZDO(shortaddr, ZDO_Mgmt_Bind_req, buf, sizeof(buf)); +#endif + + ResponseCmndDone(); +} + + +void CmndZbProbe(void) { + CmndZbProbeOrPing(true); +} + + + + +void CmndZbProbeOrPing(boolean probe) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + + Z_SendIEEEAddrReq(shortaddr); + if (probe) { + Z_SendActiveEpReq(shortaddr); + } + ResponseCmndDone(); +} + + +void CmndZbPing(void) { + CmndZbProbeOrPing(false); +} + + + + + +void CmndZbName(void) { + + + + + + + + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + if (p == nullptr) { + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName : ""); + } else { + if (strlen(p) > 32) { p[32] = 0x00; } + zigbee_devices.setFriendlyName(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); + } +} + + + + + +void CmndZbModelId(void) { + + + + + + + + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + if (p == nullptr) { + const char * modelId = zigbee_devices.getModelId(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, modelId ? modelId : ""); + } else { + zigbee_devices.setModelId(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, p); + } +} + + + + +void CmndZbLight(void) { + + + + + + + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + if (p) { + int8_t bulbtype = strtol(p, nullptr, 10); + if (bulbtype > 5) { bulbtype = 5; } + if (bulbtype < -1) { bulbtype = -1; } + zigbee_devices.setLightProfile(shortaddr, bulbtype); + } + String dump = zigbee_devices.dumpLightState(shortaddr); + Response_P(PSTR("{\"" D_PRFX_ZB D_CMND_ZIGBEE_LIGHT "\":%s}"), dump.c_str()); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_ZB D_CMND_ZIGBEE_LIGHT)); + ResponseCmndDone(); +} + + + + + +void CmndZbForget(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + + if (zigbee_devices.removeDevice(shortaddr)) { + ResponseCmndDone(); + } else { + ResponseCmndChar_P(PSTR("Unknown device")); + } +} + + + + + +void CmndZbSave(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + saveZigbeeDevices(); + ResponseCmndDone(); +} +# 1128 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" +void CmndZbRestore(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + JsonParser parser(XdrvMailbox.data); + JsonParserToken root = parser.getRoot(); + + if (!parser || !(root.isObject() || root.isArray())) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + + JsonParserToken zbstatus = root.getObject().findStartsWith(PSTR("ZbStatus")); + if (zbstatus) { + root = zbstatus; + } + + + if (root.isArray()) { + JsonParserArray arr = JsonParserArray(root); + for (const auto elt : arr) { + + if (elt.isObject()) { + int32_t res = zigbee_devices.deviceRestore(JsonParserObject(elt)); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } + } + } + } else if (root.isObject()) { + int32_t res = zigbee_devices.deviceRestore(JsonParserObject(root)); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } + + } else { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + ResponseCmndDone(); +} + + + + + +void CmndZbPermitJoin(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + uint32_t payload = XdrvMailbox.payload; + uint8_t duration = 60; + + if (payload <= 0) { + duration = 0; + } + + +#ifdef USE_ZIGBEE_ZNP + if (99 == payload) { + duration = 0xFF; + } + + uint16_t dstAddr = 0xFFFC; + + SBuffer buf(34); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); + buf.add8(0x0F); + buf.add16(0xFFFC); + buf.add8(duration); + buf.add8(0x00); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + +#endif + + +#ifdef USE_ZIGBEE_EZSP + if (99 == payload) { + ResponseCmndChar_P(PSTR("Unlimited time not supported")); return; + } + + SBuffer buf(3); + buf.add16(EZSP_permitJoining); + buf.add8(duration); + ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); + + + buf.setLen(0); + buf.add8(duration); + buf.add8(0x01); + EZ_SendZDO(0xFFFC, ZDO_Mgmt_Permit_Joining_req, buf.buf(), buf.len()); + + + if (duration > 0) { + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":21,\"Message\":\"Pairing mode enabled\"}}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + zigbee.permit_end_time = millis() + duration * 1000; + AddLog_P2(LOG_LEVEL_INFO, "zigbee.permit_end_time = %d", zigbee.permit_end_time); + } else { + zigbee.permit_end_time = millis(); + } +#endif + + ResponseCmndDone(); +} + +#ifdef USE_ZIGBEE_EZSP + + + + + +void CmndZbEZSPListen(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + int32_t index = XdrvMailbox.index; + int32_t group = XdrvMailbox.payload; + + if (group <= 0) { + group = 0; + } else if (group > 0xFFFF) { + group = 0xFFFF; + } + + SBuffer buf(8); + buf.add16(EZSP_setMulticastTableEntry); + buf.add8(index); + buf.add16(group); + buf.add8(0x01); + buf.add8(0x00); + ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); + + ResponseCmndDone(); +} + +void ZigbeeGlowPermitJoinLight(void) { + static const uint16_t cycle_time = 1000; + static const uint16_t half_cycle_time = cycle_time / 2; + if (zigbee.permit_end_time) { + uint16_t led_power = 0; + + if (TimeReached(zigbee.permit_end_time)) { + zigbee.permit_end_time = 0; + Z_PermitJoinDisable(); + } else { + uint32_t millis_to_go = millis() - zigbee.permit_end_time; + uint32_t sub_second = millis_to_go % cycle_time; + if (sub_second <= half_cycle_time) { + led_power = changeUIntScale(sub_second, 0, half_cycle_time, 0, 1023); + } else { + led_power = changeUIntScale(sub_second, half_cycle_time, cycle_time, 1023, 0); + } + led_power = ledGamma10_10(led_power); + } + + + uint32_t led_pin = Pin(GPIO_LEDLNK); + if (led_pin < 99) { + analogWrite(led_pin, ledlnk_inverted ? 1023 - led_power : led_power); + } + } +} +#endif + + + + +void CmndZbStatus(void) { + if (ZigbeeSerial) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (XdrvMailbox.data_len > 0) { + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + } + + String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); + Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); + } +} + + + + + +bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root) { + for (auto data_elt : root) { + + const char * data_type_str = data_elt.getStr(); + Z_Data_Type data_type; + + switch (data_type_str[0]) { + case 'P': data_type = Z_Data_Type::Z_Plug; break; + case 'L': data_type = Z_Data_Type::Z_Light; break; + case 'O': data_type = Z_Data_Type::Z_OnOff; break; + case 'T': data_type = Z_Data_Type::Z_Thermo; break; + case 'A': data_type = Z_Data_Type::Z_Alarm; break; + case '_': data_type = Z_Data_Type::Z_Device; break; + default: data_type = Z_Data_Type::Z_Unknown; break; + } + + if (data_type == Z_Data_Type::Z_Unknown) { + Response_P(PSTR("{\"%s\":\"%s \"%s\"\"}"), XdrvMailbox.command, PSTR("Invalid Parameters"), data_type_str); + return false; + } + + JsonParserObject data_values = data_elt.getValue().getObject(); + if (!data_values) { return false; } + + + uint8_t endpoint = strtoul(&data_type_str[1], nullptr, 16); + JsonParserToken val; + + + Z_Data & data = device.data.getByType(data_type, endpoint); + + + for (auto attr : data_values) { + JsonParserToken attr_value = attr.getValue(); + uint8_t conv_zigbee_type; + Z_Data_Type conv_data_type; + uint8_t conv_map_offset; + if (zigbeeFindAttributeByName(attr.getStr(), nullptr, nullptr, nullptr, &conv_zigbee_type, &conv_data_type, &conv_map_offset) != nullptr) { + + if (conv_data_type == data_type) { + + + uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + conv_map_offset; + uint32_t uval32 = attr_value.getUInt(); + int32_t ival32 = attr_value.getInt(); + switch (conv_zigbee_type) { + case Zenum8: + case Zuint8: *(uint8_t*)attr_address = uval32; break; + case Zenum16: + case Zuint16: *(uint16_t*)attr_address = uval32; break; + case Zuint32: *(uint32_t*)attr_address = uval32; break; + case Zint8: *(int8_t*)attr_address = ival32; break; + case Zint16: *(int16_t*)attr_address = ival32; break; + case Zint32: *(int32_t*)attr_address = ival32; break; + } + } else if (conv_data_type != Z_Data_Type::Z_Unknown) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "attribute %s is wrong type %d (expected %d)"), attr.getStr(), (uint8_t)data_type, (uint8_t)conv_data_type); + } + } + } + + + switch (data_type) { +# 1385 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + case Z_Data_Type::Z_OnOff: + { + Z_Data_OnOff & onoff = (Z_Data_OnOff&) data; + + if (val = data_values[PSTR("Power")]) { onoff.setPower(val.getUInt() ? true : false); } + } + break; +# 1402 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + case Z_Data_Type::Z_Device: + { + if (val = data_values[PSTR(D_CMND_ZIGBEE_LINKQUALITY)]) { device.lqi = val.getUInt(); } + if (val = data_values[PSTR("BatteryPercentage")]) { device.batterypercent = val.getUInt(); } + if (val = data_values[PSTR("LastSeen")]) { device.last_seen = val.getUInt(); } + } + break; + } + } + return true; +} + + + + +void CmndZbData(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + RemoveSpace(XdrvMailbox.data); + if (XdrvMailbox.data[0] == '{') { + + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + + JsonParserToken zbdata = root.getObject().findStartsWith(PSTR("ZbData")); + if (zbdata) { + root = zbdata; + } + + for (auto device_name : root) { + uint16_t shortaddr = zigbee_devices.parseDeviceParam(device_name.getStr()); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + Z_Device & device = zigbee_devices.getShortAddr(shortaddr); + JsonParserObject inner_data = device_name.getValue().getObject(); + if (inner_data) { + if (!parseDeviceInnerData(device, inner_data)) { + return; + } + } + } + ResponseCmndDone(); + } else { + + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); + + Z_attribute_list attr_data; + + { + Z_attribute_list device_attr; + device.toAttributes(device_attr); + attr_data.addAttribute(F("_00")).setStrRaw(device_attr.toString(true).c_str()); + } + + + for (auto & data_elt : device.data) { + Z_attribute_list inner_attr; + char key[4]; + snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); +# 1473 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + Z_Data_Type data_type = data_elt.getType(); + switch (data_type) { + case Z_Data_Type::Z_Plug: + { + key[0] = 'P'; + ((Z_Data_Plug&)data_elt).toAttributes(inner_attr, data_type); + } + break; + case Z_Data_Type::Z_Light: + { + key[0] = 'L'; + ((Z_Data_Light&)data_elt).toAttributes(inner_attr, data_type); + } + break; + case Z_Data_Type::Z_OnOff: + { + key[0] = 'O'; + ((Z_Data_OnOff&)data_elt).toAttributes(inner_attr, data_type); + } + break; + case Z_Data_Type::Z_Thermo: + { + key[0] = 'T'; + ((Z_Data_Thermo&)data_elt).toAttributes(inner_attr, data_type); + } + break; + case Z_Data_Type::Z_Alarm: + { + key[0] = 'A'; + ((Z_Data_Alarm&)data_elt).toAttributes(inner_attr, data_type); + } + break; + } + if (key[0] != '?') { + attr_data.addAttribute(key).setStrRaw(inner_attr.toString(true).c_str()); + } + } + + char hex[8]; + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + Response_P(PSTR("{\"%s\":{\"%s\":%s}}"), XdrvMailbox.command, hex, attr_data.toString(true).c_str()); + } +} + + + + +void CmndZbConfig(void) { + + + uint8_t zb_channel = Settings.zb_channel; + uint16_t zb_pan_id = Settings.zb_pan_id; + uint64_t zb_ext_panid = Settings.zb_ext_panid; + uint64_t zb_precfgkey_l = Settings.zb_precfgkey_l; + uint64_t zb_precfgkey_h = Settings.zb_precfgkey_h; + int8_t zb_txradio_dbm = Settings.zb_txradio_dbm; + + + RemoveSpace(XdrvMailbox.data); + if (strlen(XdrvMailbox.data) > 0) { + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + + zb_channel = root.getUInt(PSTR("Channel"), zb_channel); + zb_pan_id = root.getUInt(PSTR("PanID"), zb_pan_id); + zb_ext_panid = root.getULong(PSTR("ExtPanID"), zb_ext_panid); + zb_precfgkey_l = root.getULong(PSTR("KeyL"), zb_precfgkey_l); + zb_precfgkey_h = root.getULong(PSTR("KeyH"), zb_precfgkey_h); + zb_txradio_dbm = root.getInt(PSTR("TxRadio"), zb_txradio_dbm); + + if (zb_channel < 11) { zb_channel = 11; } + if (zb_channel > 26) { zb_channel = 26; } + + if ((0 == zb_precfgkey_l) && (0 == zb_precfgkey_h)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "generating random Zigbee network key")); + zb_precfgkey_l = (uint64_t)HwRandom() << 32 | HwRandom(); + zb_precfgkey_h = (uint64_t)HwRandom() << 32 | HwRandom(); + } + + + if ( (zb_channel != Settings.zb_channel) || + (zb_pan_id != Settings.zb_pan_id) || + (zb_ext_panid != Settings.zb_ext_panid) || + (zb_precfgkey_l != Settings.zb_precfgkey_l) || + (zb_precfgkey_h != Settings.zb_precfgkey_h) || + (zb_txradio_dbm != Settings.zb_txradio_dbm) ) { + Settings.zb_channel = zb_channel; + Settings.zb_pan_id = zb_pan_id; + Settings.zb_ext_panid = zb_ext_panid; + Settings.zb_precfgkey_l = zb_precfgkey_l; + Settings.zb_precfgkey_h = zb_precfgkey_h; + Settings.zb_txradio_dbm = zb_txradio_dbm; + restart_flag = 2; + } + } + + + char hex_ext_panid[20] = "0x"; + Uint64toHex(zb_ext_panid, &hex_ext_panid[2], 64); + char hex_precfgkey_l[20] = "0x"; + Uint64toHex(zb_precfgkey_l, &hex_precfgkey_l[2], 64); + char hex_precfgkey_h[20] = "0x"; + Uint64toHex(zb_precfgkey_h, &hex_precfgkey_h[2], 64); + + + Response_P(PSTR("{\"" D_PRFX_ZB D_JSON_ZIGBEE_CONFIG "\":{" + "\"Channel\":%d" + ",\"PanID\":\"0x%04X\"" + ",\"ExtPanID\":\"%s\"" + ",\"KeyL\":\"%s\"" + ",\"KeyH\":\"%s\"" + ",\"TxRadio\":%d" + "}}"), + zb_channel, zb_pan_id, + hex_ext_panid, + hex_precfgkey_l, hex_precfgkey_h, + zb_txradio_dbm); +} + + + + + +extern "C" { + int device_cmp(const void * a, const void * b) { + const Z_Device &dev_a = zigbee_devices.devicesAt(*(uint8_t*)a); + const Z_Device &dev_b = zigbee_devices.devicesAt(*(uint8_t*)b); + const char * fn_a = dev_a.friendlyName; + const char * fn_b = dev_b.friendlyName; + + if (fn_a && fn_b) { + return strcasecmp(fn_a, fn_b); + } else if (!fn_a && !fn_b) { + return (int32_t)dev_a.shortaddr - (int32_t)dev_b.shortaddr; + } else { + if (fn_a) return -1; + return 1; + } + } +# 1627 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" + int convert_seconds_to_dhm(uint32_t n, char *result, size_t result_len){ + char fmtstr[] = "%02dmhd"; + uint32_t conversions[3] = {24 * 3600, 3600, 60}; + uint32_t value; + for(int i = 0; i < 3; ++i) { + value = n / conversions[i]; + if(value > 0) { + fmtstr[4] = fmtstr[6-i]; + break; + } + n = n % conversions[i]; + } + + + fmtstr[5] = '\0'; + return snprintf(result, result_len, fmtstr, value); + } +} +void ZigbeeShow(bool json) +{ + if (json) { + return; +#ifdef USE_WEBSERVER + } else { + uint32_t zigbee_num = zigbee_devices.devicesSize(); + if (!zigbee_num) { return; } + if (zigbee_num > 255) { zigbee_num = 255; } + + WSContentSend_P(PSTR("{t}")); + WSContentSend_P(PSTR( + "" + )); + + + uint8_t sorted_idx[zigbee_num]; + for (uint32_t i = 0; i < zigbee_num; i++) { + sorted_idx[i] = i; + } + qsort(sorted_idx, zigbee_num, sizeof(sorted_idx[0]), device_cmp); + + uint32_t now = Rtc.utc_time; + + for (uint32_t i = 0; i < zigbee_num; i++) { + const Z_Device &device = zigbee_devices.devicesAt(sorted_idx[i]); + uint16_t shortaddr = device.shortaddr; + char *name = (char*) device.friendlyName; + + char sdevice[33]; + if (nullptr == name) { + snprintf_P(sdevice, sizeof(sdevice), PSTR(D_DEVICE " 0x%04X"), shortaddr); + name = sdevice; + } + + char sbatt[64]; + snprintf_P(sbatt, sizeof(sbatt), PSTR(" ")); + if (device.validBatteryPercent()) { + snprintf_P(sbatt, sizeof(sbatt), + PSTR(""), + device.batterypercent, changeUIntScale(device.batterypercent, 0, 100, 0, 14) + ); + } + + uint32_t num_bars = 0; + + char slqi[4]; + slqi[0] = '-'; + slqi[1] = '\0'; + if (device.validLqi()){ + num_bars = changeUIntScale(device.lqi, 0, 254, 0, 4); + snprintf_P(slqi, sizeof(slqi), PSTR("%d"), device.lqi); + } + + WSContentSend_PD(PSTR( + "" + "%s" + "%s" + "
" + ), name, sbatt, slqi); + + if(device.validLqi()) { + for(uint32_t j = 0; j < 4; ++j) { + WSContentSend_PD(PSTR(""), j, (num_bars < j) ? PSTR(" o30") : PSTR("")); + } + } + char dhm[16]; + snprintf_P(dhm, sizeof(dhm), PSTR(" ")); + if(device.validLastSeen()){ + snprintf_P(dhm, sizeof(dhm), PSTR("🕗")); + convert_seconds_to_dhm(now - device.last_seen, &dhm[9], 7); + } + + WSContentSend_PD(PSTR( + "
" + "%s{e}" + ), dhm ); + + + const Z_Data_Thermo & thermo = device.data.find(); + + if (&thermo != nullptr) { + WSContentSend_P(PSTR("┆")); + if (thermo.validTemperature()) { + char buf[12]; + dtostrf(thermo.getTemperature() / 100.0f, 3, 1, buf); + WSContentSend_PD(PSTR(" ☀️ %s°C"), buf); + } + if (thermo.validTempTarget()) { + char buf[12]; + dtostrf(thermo.getTempTarget() / 100.0f, 3, 1, buf); + WSContentSend_PD(PSTR(" 🎯 %s°C"), buf); + } + if (thermo.validThSetpoint()) { + WSContentSend_PD(PSTR(" ⚙️ %d%%"), thermo.getThSetpoint()); + } + if (thermo.validHumidity()) { + WSContentSend_P(PSTR(" 💧 %d%%"), (uint16_t)(thermo.getHumidity() / 100.0f + 0.5f)); + } + if (thermo.validPressure()) { + WSContentSend_P(PSTR(" ⛅ %d hPa"), thermo.getPressure()); + } + + WSContentSend_P(PSTR("{e}")); + } + + + const Z_Data_OnOff & onoff = device.data.find(); + const Z_Data_Light & light = device.data.find(); + bool light_display = (&light != nullptr) ? light.validDimmer() : false; + const Z_Data_Plug & plug = device.data.find(); + if ((&onoff != nullptr) || light_display || (&plug != nullptr)) { + int8_t channels = device.getLightChannels(); + if (channels < 0) { channels = 5; } + WSContentSend_P(PSTR("┆")); + if (&onoff != nullptr) { + WSContentSend_P(PSTR(" %s"), device.getPower() ? PSTR(D_ON) : PSTR(D_OFF)); + } + if (&light != nullptr) { + if (light.validDimmer() && (channels >= 1)) { + WSContentSend_P(PSTR(" 🔅 %d%%"), changeUIntScale(light.getDimmer(),0,254,0,100)); + } + if (light.validCT() && ((channels == 2) || (channels == 5))) { + uint32_t ct_k = (((1000000 / light.getCT()) + 25) / 50) * 50; + WSContentSend_P(PSTR(" %dK"), light.getCT(), ct_k); + } + if (light.validHue() && light.validSat() && (channels >= 3)) { + uint8_t r,g,b; + uint8_t sat = changeUIntScale(light.getSat(), 0, 254, 0, 255); + LightStateClass::HsToRgb(light.getHue(), sat, &r, &g, &b); + WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b); + } else if (light.validX() && light.validY() && (channels >= 3)) { + uint8_t r,g,b; + LightStateClass::XyToRgb(light.getX() / 65535.0f, light.getY() / 65535.0f, &r, &g, &b); + WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b); + } + } + if (&plug != nullptr) { + WSContentSend_P(PSTR(" ⚡ ")); + if (plug.validMainsVoltage()) { + WSContentSend_P(PSTR(" %dV"), plug.getMainsVoltage()); + } + if (plug.validMainsPower()) { + WSContentSend_P(PSTR(" %dW"), plug.getMainsPower()); + } + } + WSContentSend_P(PSTR("{e}")); + } + } + + WSContentSend_P(PSTR("{t}")); +#endif + } +} + + + + + +bool Xdrv23(uint8_t function) +{ + bool result = false; + + if (zigbee.active) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (!zigbee.init_phase) { + zigbee_devices.runTimer(); + } + break; + case FUNC_LOOP: +#ifdef USE_ZIGBEE_EZSP + if (ZigbeeUploadXmodem()) { + return false; + } +#endif + if (ZigbeeSerial) { + ZigbeeInputLoop(); + ZigbeeOutputLoop(); +#ifdef USE_ZIGBEE_EZSP + ZigbeeGlowPermitJoinLight(); +#endif + } + if (zigbee.state_machine) { + ZigbeeStateMachine_Run(); + } + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ZigbeeShow(false); + break; +#ifdef USE_ZIGBEE_EZSP + + case FUNC_WEB_ADD_HANDLER: + WebServer_on(PSTR("/" WEB_HANDLE_ZIGBEE_XFER), HandleZigbeeXfer); + break; +#endif +#endif + case FUNC_PRE_INIT: + ZigbeeInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kZbCommands, ZigbeeCommand); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" +#ifdef USE_BUZZER + + + + +#define XDRV_24 24 + +struct BUZZER { + uint32_t tune = 0; + uint32_t tune_reload = 0; + bool active = true; + bool enable = false; + uint8_t inverted = 0; + uint8_t count = 0; + uint8_t mode = 0; + uint8_t freq_mode = 0; + uint8_t set[2]; + uint8_t duration; + uint8_t state = 0; +} Buzzer; + + + +void BuzzerSet(uint8_t state) +{ + if (Buzzer.inverted) { + state = !state; + } + + if (Buzzer.freq_mode == 1) { + static uint8_t last_state = 0; + if (last_state != state) { + if (state) { + analogWrite(Pin(GPIO_BUZZER, 0), Settings.pwm_range / 2); + } + else { + analogWrite(Pin(GPIO_BUZZER, 0), 0); + } + last_state = state; + } + } + else { + DigitalWrite(GPIO_BUZZER, 0, state); + } + +} + + +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) +{ + Buzzer.set[0] = off; + Buzzer.set[1] = on; + Buzzer.duration = 1; + Buzzer.tune_reload = 0; + Buzzer.mode = mode; + + 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_reload <<= 1; + Buzzer.tune_reload |= tune1 & 1; + tune1 >>= 1; + } + } + Buzzer.tune = Buzzer.tune_reload; + } + Buzzer.count = count * 2; + + + if (Settings.flag4.buzzer_freq_mode) { + Buzzer.freq_mode = 1; + } + else { + Buzzer.freq_mode = 0; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X),%d"), count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.freq_mode); + + Buzzer.enable = (Buzzer.count > 0); + if (Buzzer.enable) { + if (Settings.sleep > PWM_MAX_SLEEP) { + ssleep = PWM_MAX_SLEEP; + } else { + ssleep = Settings.sleep; + } + } + else { + ssleep = Settings.sleep; + BuzzerSet(0); + } +} + +void BuzzerSetStateToLed(uint32_t state) +{ + if (Buzzer.enable && (2 == Buzzer.mode)) { + Buzzer.state = (state != 0); + BuzzerSet(Buzzer.state); + } +} + +void BuzzerBeep(uint32_t count) +{ + BuzzerBeep(count, 1, 1, 0, 0); +} + +void BuzzerEnabledBeep(uint32_t count, uint32_t duration) +{ + if (Settings.flag3.buzzer_enable) { + BuzzerBeep(count, duration, 1, 0, 0); + } +} + + + +bool BuzzerPinState(void) +{ + if (XdrvMailbox.index == AGPIO(GPIO_BUZZER_INV)) { + Buzzer.inverted = 1; + XdrvMailbox.index -= (AGPIO(GPIO_BUZZER_INV) - AGPIO(GPIO_BUZZER)); + return true; + } + return false; +} + +void BuzzerInit(void) +{ + if (PinUsed(GPIO_BUZZER)) { + pinMode(Pin(GPIO_BUZZER), OUTPUT); + BuzzerSet(0); + } else { + Buzzer.active = false; + } +} + +void BuzzerEvery100mSec(void) +{ + if (Buzzer.enable && (Buzzer.mode != 2)) { + if (Buzzer.count) { + if (Buzzer.duration) { + Buzzer.duration--; + if (!Buzzer.duration) { + if (Buzzer.tune) { + Buzzer.state = Buzzer.tune & 1; + Buzzer.tune >>= 1; + } else { + Buzzer.tune = Buzzer.tune_reload; + Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; + Buzzer.state = Buzzer.count & 1; + if (Buzzer.mode) { + Buzzer.count |= 2; + } + } + Buzzer.duration = Buzzer.set[Buzzer.state]; + } + } + BuzzerSet(Buzzer.state); + } else { + Buzzer.enable = false; + } + } +} + + + + + +const char kBuzzerCommands[] PROGMEM = "|" + "Buzzer" ; + +void (* const BuzzerCommand[])(void) PROGMEM = { + &CmndBuzzer }; + +void CmndBuzzer(void) +{ +# 210 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload != 0) { + uint32_t parm[4] = { 0 }; + uint32_t mode = 0; + ParseParameters(4, parm); + if (XdrvMailbox.payload <= 0) { + parm[0] = 1; + mode = -XdrvMailbox.payload; + } + for (uint32_t i = 1; i < 3; i++) { + if (parm[i] < 1) { parm[i] = 1; } + } + BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); + } else { + BuzzerBeep(0); + } + } 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 "/workspace/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +# 21 "/workspace/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +#ifdef USE_A4988_STEPPER + + + + +#define XDRV_25 25 + +#include + +short A4988_dir_pin = 0; +short A4988_stp_pin = 0; +short A4988_ms1_pin = 0; +short A4988_ms2_pin = 0; +short A4988_ms3_pin = 0; +short A4988_ena_pin = 0; +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_MS1, 1); + A4988_ms3_pin = Pin(GPIO_A4988_MS1, 2); + 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 (PinUsed(GPIO_A4988_MS1) && PinUsed(GPIO_A4988_MS1, 1) && PinUsed(GPIO_A4988_MS1, 2) && (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 (PinUsed(GPIO_A4988_DIR) && PinUsed(GPIO_A4988_STP)) { + switch (function) { + case FUNC_INIT: + A4988Init(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kA4988Commands, A4988Command); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +#ifdef USE_LIGHT +#ifdef USE_ARILUX_RF + + + + +#define XDRV_26 26 + +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 { + 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 USE_WS2812_DMA +void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; +#endif + +void AriluxRfInterrupt(void) +{ + unsigned long time = micros(); + 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 int delay = Arilux.rf_timings[0] / 31; + const 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 (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) { + 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 (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) { + detachInterrupt(Pin(GPIO_ARIRFRCV)); + digitalWrite(Pin(GPIO_ARIRFSEL), 1); + } +} + + + + + +bool Xdrv26(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (PinUsed(GPIO_ARIRFRCV)) { AriluxRfHandler(); } + break; + case FUNC_EVERY_SECOND: + if (10 == uptime) { AriluxRfInit(); } + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" +#ifdef USE_SHUTTER + + + + +#define XDRV_27 27 +#ifndef SHUTTER_STEPPER + #define SHUTTER_STEPPER +#endif + +#define D_SHUTTER "SHUTTER" + +const uint16_t MOTOR_STOP_TIME = 500; +const uint16_t RESOLUTION = 1000; +const uint8_t STEPS_PER_SECOND = 20; +const uint16_t pwm_max = 500; +const uint16_t pwm_min = 90; + +uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; +uint16_t messwerte[5] = {30,50,70,90,100}; + +int32_t velocity_max = 0; +int32_t velocity_change_per_step_max = 0; +int32_t min_runtime_ms = 0; +int32_t current_stop_way = 0; +int32_t next_possible_stop_position = 0; +int32_t toBeAcc = 0; + + +const uint8_t MAX_MODES = 7; +enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; +enum Shutterswitch_mode {SHT_SWITCH, SHT_PULSE,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_EXT_HOLD, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; + +const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" + D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_TOGGLE "|" D_CMND_SHUTTER_TOGGLEDIR "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" + D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_MODE "|" D_CMND_SHUTTER_PWMRANGE "|" + D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" + D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|" + D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC; + +void (* const ShutterCommand[])(void) PROGMEM = { + &CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition, + &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterMode, &CmndShutterPwmRange, + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, + &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons, + &CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec}; + + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; + const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; + +#include + +Ticker TickerShutter; + +struct SHUTTER { + uint32_t time; + int32_t open_max; + int32_t target_position; + int32_t start_position; + int32_t real_position; + uint16_t open_time; + uint16_t close_time; + uint16_t close_velocity; + int8_t direction; + int8_t lastdirection; + uint8_t switch_mode; + int16_t motordelay; + int16_t pwm_velocity; + uint16_t pwm_value; + uint16_t close_velocity_max; + int32_t accelerator; +} Shutter[MAX_SHUTTERS]; + +struct SHUTTERGLOBAL { + power_t RelayShutterMask = 0; + power_t RelayOldMask = 0; + power_t RelayCurrentMask = 0; + uint8_t position_mode = 0; + uint8_t skip_relay_change; + uint8_t start_reported = 0; + uint16_t open_velocity_max = 1000; +} ShutterGlobal; + +#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) + +void ShutterLogPos(uint32_t i) +{ + char stemp2[10]; + dtostrfd((float)Shutter[i].time / STEPS_PER_SECOND, 2, stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), + i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value); +} + +void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source) +{ + + if (device <= devices_present) ExecuteCommandPower(device,state,source); +} + +void ShutterUpdateVelocity(uint8_t i) +{ + + + Shutter[i].pwm_velocity += Shutter[i].accelerator; + Shutter[i].pwm_velocity = tmax(0,tmin(Shutter[i].direction==1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max,Shutter[i].pwm_velocity)); +} + +void ShutterRtc50mS(void) +{ + + for (uint8_t i = 0; i < shutters_present; i++) { + if (Shutter[i].direction) { + + Shutter[i].real_position = ShutterCalculatePosition(i); + Shutter[i].time++; + ShutterCalculateAccelerator(i); + switch (ShutterGlobal.position_mode) { + case SHT_PWM_VALUE: + ShutterUpdateVelocity(i); + Shutter[i].real_position += Shutter[i].direction > 0 ? Shutter[i].pwm_velocity : (Shutter[i].direction < 0 ? -Shutter[i].pwm_velocity : 0); + Shutter[i].pwm_value = SHT_DIV_ROUND((Settings.shutter_pwmrange[1][i]-Settings.shutter_pwmrange[0][i]) * Shutter[i].real_position , Shutter[i].open_max)+Settings.shutter_pwmrange[0][i]; + analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); + break; + + case SHT_COUNTER: + if (Shutter[i].accelerator) { + + ShutterUpdateVelocity(i); + analogWriteFreq(Shutter[i].pwm_velocity); + analogWrite(Pin(GPIO_PWM1, i), 50); + } + break; + } + } + } +} + +int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent*10 : (Settings.shuttercoeff[1][index] * percent + (Settings.shuttercoeff[0][index]*10))*10; + } else { + uint32_t realpos; + + for (uint32_t j = 0; j < 5; j++) { + if (0 == Settings.shuttercoeff[j][index]) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); + for (uint32_t k = 0; k < 5; k++) { + Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); + } + } + } + for (uint32_t k = 0; k < 5; k++) { + if ((percent * 10) >= Settings.shuttercoeff[k][index]) { + realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100); + + } else { + if (0 == k) { + realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]), 10); + } else { + + + realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index]), 100); + } + break; + } + } + return realpos; + } +} + +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return (Settings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings.shuttercoeff[0][index]*10, Settings.shuttercoeff[1][index]); + } else { + uint16_t realpercent; + + for (uint32_t j = 0; j < 5; j++) { + if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) { + realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10); + + } else { + if (0 == j) { + realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * Settings.shuttercoeff[j][index], calibrate_pos[j+1]), Shutter[index].open_max); + } else { + + + + realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])), Shutter[index].open_max) ; + } + break; + } + } + return (int16_t)realpercent < 0 ? 0 : realpercent; + } +} + +void ShutterInit(void) +{ + shutters_present = 0; + ShutterGlobal.RelayShutterMask = 0; + + ShutterGlobal.RelayOldMask = power; + + + + if (Settings.shutter_startrelay[MAX_SHUTTERS -1] == 0) { + ShutterGlobal.open_velocity_max = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : ShutterGlobal.open_velocity_max; + } + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + + 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++; + + + ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1) ; + + + switch (Settings.pulse_timer[i]) { + case 0: + Shutter[i].switch_mode = SHT_SWITCH; + break; + default: + Shutter[i].switch_mode = SHT_PULSE; + break; + } + + if (Settings.shutter_mode == SHT_UNDEF) { + bool relay_in_interlock = false; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: mode undef.. calculate...")); + + for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { + + if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) { + + relay_in_interlock = true; + } + } + + if (relay_in_interlock) { + ShutterGlobal.position_mode = SHT_TIME; + } else { + ShutterGlobal.position_mode = SHT_TIME_UP_DOWN; + if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) { + ShutterGlobal.position_mode = SHT_COUNTER; + } + } + + } else { + ShutterGlobal.position_mode = Settings.shutter_mode; + } + + + TickerShutter.attach_ms(50, ShutterRtc50mS ); + + + Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; + + + Shutter[i].open_time = Settings.shutter_opentime[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; + Shutter[i].close_time = Settings.shutter_closetime[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; + + + Shutter[i].open_max = STEPS_PER_SECOND * RESOLUTION * Shutter[i].open_time / 10; + Shutter[i].close_velocity = Shutter[i].open_max / Shutter[i].close_time / 2 ; + + + if (Settings.shutter_set50percent[i] != 50) { + Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ; + Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10); + Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5; + + } + ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1); + + Shutter[i].real_position = ShutterPercentToRealPosition(Settings.shutter_position[i], i); + + Shutter[i].start_position = Shutter[i].target_position = Shutter[i].real_position; + Shutter[i].motordelay = Settings.shutter_motordelay[i]; + Shutter[i].lastdirection = (50 < Settings.shutter_position[i]) ? 1 : -1; + + switch (ShutterGlobal.position_mode) { + case SHT_PWM_VALUE: + ShutterGlobal.open_velocity_max = RESOLUTION; + + Settings.shutter_pwmrange[0][i] = Settings.shutter_pwmrange[0][i] > 0 ? Settings.shutter_pwmrange[0][i] : pwm_min; + Settings.shutter_pwmrange[1][i] = Settings.shutter_pwmrange[1][i] > 0 ? Settings.shutter_pwmrange[1][i] : pwm_max; + break; + } + Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init. Pos: %d,inverted %d, locked %d, end stop time enabled %d, webButtons inverted %d"), + i+1, Shutter[i].real_position, + (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, (Settings.shutter_options[i]&8) ? 1 : 0); + + } else { + + break; + } + ShutterLimitRealAndTargetPositions(i); + Settings.shutter_accuracy = 1; + } +} + +void ShutterReportPosition(bool always, uint32_t index) +{ + Response_P(PSTR("{")); + rules_flag.shutter_moving = 0; + uint32_t i = 0; + uint32_t n = shutters_present; + if( index != MAX_SHUTTERS) { + i = index; + n = index+1; + } + for (i; i < n; i++) { + + uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); + if (Shutter[i].direction != 0) { + rules_flag.shutter_moving = 1; + ShutterLogPos(i); + } + if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } + uint32_t target = ShutterRealToPercentPosition(Shutter[i].target_position, i); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings.shutter_options[i] & 1) ? 100-target : target ); + } + ResponseJsonEnd(); + if (always || (rules_flag.shutter_moving)) { + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + } + +} + +void ShutterLimitRealAndTargetPositions(uint32_t i) { + if (Shutter[i].real_position<0) Shutter[i].real_position = 0; + if (Shutter[i].real_position>Shutter[i].open_max) Shutter[i].real_position = Shutter[i].open_max; + if (Shutter[i].target_position<0) Shutter[i].target_position = 0; + if (Shutter[i].target_position>Shutter[i].open_max) Shutter[i].target_position = Shutter[i].open_max; +} + +void ShutterCalculateAccelerator(uint8_t i) +{ + + if (Shutter[i].direction != 0) { + switch (ShutterGlobal.position_mode) { + case SHT_COUNTER: + case SHT_PWM_VALUE: + + velocity_max = Shutter[i].direction == 1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max; + + velocity_change_per_step_max = velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); + + min_runtime_ms = Shutter[i].pwm_velocity * 1000 / STEPS_PER_SECOND / velocity_change_per_step_max; + + current_stop_way = (min_runtime_ms * (Shutter[i].pwm_velocity+velocity_change_per_step_max)/100 - Shutter[i].pwm_velocity)*RESOLUTION/ShutterGlobal.open_velocity_max * Shutter[i].direction ; + next_possible_stop_position = Shutter[i].real_position + current_stop_way ; + toBeAcc = 0; + + if (Shutter[i].accelerator < 0 || (next_possible_stop_position * Shutter[i].direction) +RESOLUTION*Shutter[i].pwm_velocity/ShutterGlobal.open_velocity_max>= Shutter[i].target_position * Shutter[i].direction ) { + + toBeAcc = 100+(Shutter[i].direction*(next_possible_stop_position-Shutter[i].target_position)*velocity_max/Shutter[i].pwm_velocity*10/RESOLUTION); + Shutter[i].accelerator = - tmin(tmax( velocity_change_per_step_max*toBeAcc/100 , (velocity_change_per_step_max*9/10)), (velocity_change_per_step_max*11/10)); + } else if ( Shutter[i].accelerator > 0 && Shutter[i].pwm_velocity == velocity_max) { + Shutter[i].accelerator = 0; + } + break; + } + } +} + +void ShutterDecellerateForStop(uint8_t i) +{ + switch (ShutterGlobal.position_mode) { + case SHT_PWM_VALUE: + case SHT_COUNTER: + int16_t missing_steps; + Shutter[i].accelerator = -(ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>4 ? (Shutter[i].motordelay*11)/10 : 4) ); + while (Shutter[i].pwm_velocity > -2*Shutter[i].accelerator ) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: velocity: %ld, delta: %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator ); + + + delay(50); + } + if (ShutterGlobal.position_mode == SHT_COUNTER){ + missing_steps = ((Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i]; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter[i].pwm_velocity); + Shutter[i].accelerator = 0; + Shutter[i].pwm_velocity = Shutter[i].pwm_velocity > 250 ? 250 : Shutter[i].pwm_velocity; + analogWriteFreq(Shutter[i].pwm_velocity); + analogWrite(Pin(GPIO_PWM1, i), 50); + Shutter[i].pwm_velocity = 0; + analogWriteFreq(Shutter[i].pwm_velocity); + while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) { + delay(1); + } + analogWrite(Pin(GPIO_PWM1, i), 0); + Shutter[i].real_position = ShutterCalculatePosition(i); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Real %d, pulsecount %d, start %d"), Shutter[i].real_position,RtcSettings.pulse_counter[i], Shutter[i].start_position); + + } + Shutter[i].direction = 0; + Shutter[i].pwm_velocity = 0; + break; + } +} + +void ShutterPowerOff(uint8_t i) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i,Shutter[i].switch_mode); + ShutterDecellerateForStop(i); + if (Shutter[i].direction !=0) { + Shutter[i].direction = 0; + delay(MOTOR_STOP_TIME); + } + switch (Shutter[i].switch_mode) { + case SHT_SWITCH: + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPowerShutter(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + } + if ((1 << (Settings.shutter_startrelay[i])) & power) { + ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; + case SHT_PULSE: + uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ; + + if ((SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source)) { + ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER); + + if ((1 << (Settings.shutter_startrelay[i])) & power) { + ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + } else { + last_source = SRC_SHUTTER; + } + break; + } + + switch (ShutterGlobal.position_mode) { + case SHT_PWM_VALUE: + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM " %d" ),Shutter[i].pwm_value); + ExecuteCommand(scmnd, SRC_BUTTON); + break; + } +} + +void ShutterUpdatePosition(void) +{ + + char scommand[CMDSZ]; + char stopic[TOPSZ]; + for (uint32_t i = 0; i < shutters_present; i++) { + if (Shutter[i].direction != 0) { + if (!ShutterGlobal.start_reported) { + ShutterReportPosition(true, i); + XdrvRulesProcess(); + ShutterGlobal.start_reported = 1; + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, toBeAcc %d, current_stop_way %d,vel_cur %d, vel_max %d, act_vel_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d, max_vel_change %d, dir: %d"),Shutter[i].time,toBeAcc,current_stop_way, + Shutter[i].pwm_velocity,velocity_max, Shutter[i].accelerator,min_runtime_ms,Shutter[i].real_position, next_possible_stop_position,Shutter[i].target_position,velocity_change_per_step_max,Shutter[i].direction); + + + if ( Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction || Shutter[i].pwm_velocity=<%s>, max10s?"),i+i, rules_vars[i]); + rules_flag.shutter_moving = 1; + XdrvRulesProcess(); + uptime_Local = uptime; + while (uptime_Local+10 > uptime && (String)rules_vars[i] == "99") { + loop(); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. Done")); +#endif +} + +void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) +{ + + if ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) / 100 <= 2) ) + || ( (-1 == direction) && (Shutter[i].real_position / Shutter[i].close_velocity <= 2)) ) { + ShutterGlobal.skip_relay_change = 1; + } else { + Shutter[i].pwm_velocity = 0; + switch (ShutterGlobal.position_mode) { +#ifdef SHUTTER_STEPPER + case SHT_COUNTER: + analogWriteFreq(Shutter[i].pwm_velocity); + analogWrite(Pin(GPIO_PWM1, i), 0); + RtcSettings.pulse_counter[i] = 0; + break; +#endif + } + Shutter[i].accelerator = ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); + Shutter[i].target_position = target_pos; + Shutter[i].start_position = Shutter[i].real_position; + rules_flag.shutter_moving = 1; + ShutterAllowPreStartProcedure(i); + Shutter[i].time = 0; + Shutter[i].direction = direction; + ShutterGlobal.skip_relay_change = 0; + rules_flag.shutter_moved = 0; + ShutterGlobal.start_reported = 0; + + } + +} + +int32_t ShutterCalculatePosition(uint32_t i) +{ + + if (Shutter[i].direction != 0) { + switch (ShutterGlobal.position_mode) { + case SHT_COUNTER: + return ((int32_t)RtcSettings.pulse_counter[i]*Shutter[i].direction*STEPS_PER_SECOND / ShutterGlobal.open_velocity_max * RESOLUTION)+Shutter[i].start_position; + break; + case SHT_TIME: + case SHT_TIME_UP_DOWN: + case SHT_TIME_GARAGE: + return Shutter[i].start_position + ( (Shutter[i].time - Shutter[i].motordelay) * (Shutter[i].direction > 0 ? RESOLUTION : -Shutter[i].close_velocity)); + break; + case SHT_PWM_TIME: + break; + case SHT_PWM_VALUE: + return Shutter[i].real_position; + break; + default: + break; + } + } else { + return Shutter[i].real_position; + } +} + +void ShutterRelayChanged(void) +{ + + + + + char stemp1[10]; + + for (uint32_t i = 0; i < shutters_present; i++) { + power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; + + + uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + if (manual_relays_changed) { + + ShutterLimitRealAndTargetPositions(i); + switch (Shutter[i].switch_mode ) { + case SHT_PULSE: + if (Shutter[i].direction != 0 && powerstate_local) { + Shutter[i].target_position = Shutter[i].real_position; + powerstate_local = 0; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + } + break; + default: + last_source = SRC_SHUTTER; + if (Shutter[i].direction != 0 ) ShutterPowerOff(i); + } + switch (ShutterGlobal.position_mode) { + + case SHT_TIME_UP_DOWN: + case SHT_COUNTER: + case SHT_PWM_VALUE: + case SHT_PWM_TIME: + ShutterPowerOff(i); + switch (powerstate_local) { + case 1: + ShutterStartInit(i, 1, Shutter[i].open_max); + break; + case 3: + ShutterStartInit(i, -1, 0); + break; + default: + + Shutter[i].target_position = Shutter[i].real_position; + } + break; + case SHT_TIME: + switch (powerstate_local) { + case 1: + ShutterStartInit(i, 1, Shutter[i].open_max); + break; + case 2: + ShutterStartInit(i, -1, 0); + break; + default: + + Shutter[i].target_position = Shutter[i].real_position; + } + break; + case SHT_TIME_GARAGE: + switch (powerstate_local) { + case 1: + ShutterStartInit(i, Shutter[i].lastdirection*-1 , Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Garage. NewTarget %d"), i, Shutter[i].target_position); + break; + default: + Shutter[i].target_position = Shutter[i].real_position; + } + + + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); + } + } +} + +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { + + uint32 min_shutterbutton_hold_timer = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + min_shutterbutton_hold_timer = Button.hold_timer[i]; + } + return ((-1 != min_shutterbutton_hold_timer) && (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1))); +} + +void ShutterButtonHandler(void) +{ + uint8_t buttonState = SHT_NOT_PRESSED; + uint8_t button = XdrvMailbox.payload; + uint8_t press_index; + uint32_t button_index = XdrvMailbox.index; + uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; + uint16_t loops_per_second = 1000 / Settings.button_debounce; + + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + if (Settings.flag.button_single) { + buttonState = SHT_PRESSED_MULTI; + press_index = 1; + } else { + if ((Shutter[shutter_index].direction) && (Button.press_counter[button_index]==0)) { + buttonState = SHT_PRESSED_IMMEDIATE; + press_index = 1; + Button.press_counter[button_index] = 99; + } else { + Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + + Button.window_timer[button_index] = (loops_per_second >> 2) * 3; + } + } + blinks = 201; + } + + if (NOT_PRESSED == button) { + Button.hold_timer[button_index] = 0; + } else { + Button.hold_timer[button_index]++; + if (!Settings.flag.button_single) { + 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; + } + } + if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + Button.press_counter[i] = 99; + press_index = 0; + buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; + } + if (Button.press_counter[button_index]<99) { + press_index = 0; + buttonState = SHT_PRESSED_HOLD; + } + Button.press_counter[button_index] = 0; + } + if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { + press_index = -1; + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; + } else { + buttonState = SHT_PRESSED_EXT_HOLD; + } + } + } + } + + 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)) { + if (Button.press_counter[button_index]<99) { + + uint32 min_shutterbutton_press_counter = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); + if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + min_shutterbutton_press_counter = Button.press_counter[i]; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); + } + } + if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: simultanous presss deteced")); + press_index = Button.press_counter[button_index]; + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) + Button.press_counter[i] = 99; + buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; + } + if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { + + press_index = Button.press_counter[button_index]; + buttonState = SHT_PRESSED_MULTI; + } + } + Button.press_counter[button_index] = 0; + } + } + } + + if (buttonState != SHT_NOT_PRESSED) { + if ((!Settings.flag.button_restrict) && (((press_index>=5) && (press_index<=7)) || (buttonState == SHT_PRESSED_EXT_HOLD) || (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS))){ + + uint8_t shutter_index_num_buttons = 0; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) { + shutter_index_num_buttons++; + } + } + if ((buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_MULTI))){ + + + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } else if ((buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_EXT_HOLD))){ + + + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } + if (buttonState <= SHT_PRESSED_IMMEDIATE) { + if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { + uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); + if (pos_press_index>3) pos_press_index=3; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); + XdrvMailbox.index = shutter_index +1; + last_source = SRC_BUTTON; + XdrvMailbox.data_len = 0; + char databuf[1] = ""; + XdrvMailbox.data = databuf; + XdrvMailbox.command = NULL; + if (buttonState == SHT_PRESSED_IMMEDIATE) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; + if (position) { + if (Shutter[shutter_index].direction) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + XdrvMailbox.payload = position = (position-1)<<1; + + if (102 == position) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterToggle(); + } else { + CmndShutterPosition(); + } + if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (dir) { + XdrvMailbox.payload = (Shutter[index].lastdirection > 0) ? 0 : 100; + } + else { + XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter[index].real_position, index)) ? 0 : 100; + } + XdrvMailbox.data_len = 0; + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } +} + + + + + +void CmndShutterOpen(void) +{ + + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + XdrvMailbox.payload = 100; + last_source = SRC_WEBGUI; + CmndShutterPosition(); +} + +void CmndShutterStopOpen(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (Shutter[index].direction) { + CmndShutterStop(); + } else { + CmndShutterOpen(); + } + } +} + +void CmndShutterClose(void) +{ + + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + XdrvMailbox.payload = 0; + XdrvMailbox.data_len = 0; + last_source = SRC_WEBGUI; + CmndShutterPosition(); +} + +void CmndShutterStopClose(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (Shutter[index].direction) { + CmndShutterStop(); + } else { + CmndShutterClose(); + } + } +} + +void CmndShutterToggle(void) +{ + ShutterToggle(false); +} + +void CmndShutterToggleDir(void) +{ + ShutterToggle(true); +} + +void CmndShutterStopToggle(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (Shutter[index].direction) { + CmndShutterStop(); + } else { + CmndShutterToggle(); + } + } +} + +void CmndShutterStopToggleDir(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (Shutter[index].direction) { + CmndShutterStop(); + } else { + CmndShutterToggleDir(); + } + } +} + +void CmndShutterStop(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + uint32_t i = XdrvMailbox.index -1; + if (Shutter[i].direction != 0) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction); + + int32_t temp_realpos = ShutterCalculatePosition(i); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } else { + if (XdrvMailbox.command) + ResponseCmndDone(); + } + } else { + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterIncDec(void) +{ + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + XdrvMailbox.payload = ShutterRealToPercentPosition(Shutter[XdrvMailbox.index-1].target_position, XdrvMailbox.index-1)+XdrvMailbox.payload; + + XdrvMailbox.payload = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload); + CmndShutterPosition(); + } + } +} + + +void CmndShutterPosition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + uint32_t index = XdrvMailbox.index-1; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + + + + if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { + + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) { + CmndShutterOpen(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE))) { + CmndShutterClose(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLE)) { + CmndShutterToggle(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDIR)) { + CmndShutterToggleDir(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter[index].direction) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE)))) { + XdrvMailbox.payload = -99; + CmndShutterStop(); + return; + } + } + + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter[index].real_position, index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + + target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; + if (XdrvMailbox.payload != -99) { + + Shutter[index].target_position = ShutterPercentToRealPosition(target_pos_percent, index); + + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter[index].real_position ,Shutter[index].target_position,target_pos_percent); + } + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2) { + if (Settings.shutter_options[index] & 4) { + if (0 == target_pos_percent) Shutter[index].target_position -= 1 * RESOLUTION * STEPS_PER_SECOND; + if (100 == target_pos_percent) Shutter[index].target_position += 1 * RESOLUTION * STEPS_PER_SECOND; + } + int8_t new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; + if (Shutter[index].direction == -new_shutterdirection) { + ShutterPowerOff(index); + } + if (Shutter[index].direction != new_shutterdirection) { + ShutterStartInit(index, new_shutterdirection, Shutter[index].target_position); + switch (ShutterGlobal.position_mode) { + case SHT_COUNTER: + case SHT_PWM_TIME: + case SHT_PWM_VALUE: + case SHT_TIME_UP_DOWN: + if (!ShutterGlobal.skip_relay_change) { + + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } + if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings.shutter_startrelay[index]+2, 1, SRC_SHUTTER); + break; + case SHT_TIME: + if (!ShutterGlobal.skip_relay_change) { + if ( (power >> (Settings.shutter_startrelay[index] -1)) & 3 > 0 ) { + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), Shutter[index].switch_mode == SHT_SWITCH ? 0 : 1, SRC_SHUTTER); + } + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + } + break; + case SHT_TIME_GARAGE: + if (!ShutterGlobal.skip_relay_change) { + if (new_shutterdirection == Shutter[index].lastdirection) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Garage not move in this direction: %d"), Shutter[index].switch_mode == SHT_PULSE); + for (uint8_t k=0 ; k <= (uint8_t)(Shutter[index].switch_mode == SHT_PULSE) ; k++) { + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + delay(500); + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + delay(500); + } + + Shutter[index].time = 0; + } + ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } + break; + } + ShutterGlobal.RelayCurrentMask = 0; + } + } else { + target_pos_percent = ShutterRealToPercentPosition(Shutter[index].real_position, index); + ShutterReportPosition(true, index); + } + XdrvMailbox.index = index +1; + if (XdrvMailbox.command) + ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); + } else { + ShutterReportPosition(true, MAX_SHUTTERS); + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterStopPosition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index-1; + if (Shutter[index].direction) { + XdrvMailbox.payload = -99; + CmndShutterStop(); + } else { + CmndShutterPosition(); + } + } +} +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 CmndShutterMotorDelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / STEPS_PER_SECOND, 2, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterMode(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) { + ShutterGlobal.position_mode = XdrvMailbox.payload; + Settings.shutter_mode = XdrvMailbox.payload; + ShutterInit(); + } + ResponseCmndNumber(ShutterGlobal.position_mode); +} + +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) { + ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1); + } else { + ShutterGlobal.RelayShutterMask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); + } + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + ShutterInit(); + + } + ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); + } +} + +void CmndShutterButton(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + uint32_t setting = 0; +# 1218 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" + if (XdrvMailbox.data_len > 0) { + uint32_t i = 0; + uint32_t button_index = 0; + bool done = false; + bool isShortCommand = false; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field; + switch (str[0]) { + case '-': + field = -1; + break; + case 't': + field = 102; + break; + default: + field = atoi(str); + break; + } + switch (i) { + case 0: + if ((field >= -1) && (field<=4)) { + button_index = (field<=0)?(-1):field; + done = (button_index==-1); + } else + done = true; + break; + case 1: + if (!strcmp_P(str, PSTR("up"))) { + setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("down"))) { + setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("updown"))) { + setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("toggle"))) { + setting |= (((102>>1)+1)<<2) | (((50>>1)+1)<<8); + isShortCommand = true; + break; + } + case 2: + if (isShortCommand) { + if ((field==1) && (setting & (0x3F<<(2+6*3)))) + + setting |= (0x3<<29); + done = true; + break; + } + case 3: + case 4: + if ((field >= -1) && (field<=102)) + setting |= (((field>>1)+1)<<(i*6 + (2-6))); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + if (field==1) + setting |= (1<<(i + (26-5))); + break; + } + if (done) break; + } + + if (button_index) { + if (button_index==-1) { + + for (uint32_t i=0 ; i < MAX_KEYS ; i++) + if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) + Settings.shutter_button[i] = 0; + } else { + if (setting) { + + setting |= (1<<31); + setting |= (XdrvMailbox.index-1) & 0x3; + } + Settings.shutter_button[button_index-1] = setting; + } + } + } + char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; + for (uint32_t i=0 ; i < MAX_KEYS ; i++) { + setting = Settings.shutter_button[i]; + if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { + if (*setting_chr_ptr == 0) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); + setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); + + for (uint32_t j=0 ; j < 4 ; j++) { + int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; + if (0 <= pos) + if (102 == pos) { + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" t")); + } else { + setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); + } + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + for (uint32_t j=0 ; j < 5 ; j++) { + bool mqtt = ((setting>>(26+j))&(0x01)!=0); + if (mqtt) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + } + } + ResponseCmndIdxChar(setting_chr); + } +} + +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_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + ShutterInit(); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); + } +} + +void CmndShutterFrequency(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { + ShutterGlobal.open_velocity_max = XdrvMailbox.payload; + if (shutters_present < 4) { + Settings.shuttercoeff[4][3] = ShutterGlobal.open_velocity_max; + } + ShutterInit(); + } + ResponseCmndNumber(ShutterGlobal.open_velocity_max); +} + +void CmndShutterSetClose(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + Shutter[XdrvMailbox.index -1].real_position = 0; + ShutterStartInit(XdrvMailbox.index -1, 0, 0); + Settings.shutter_position[XdrvMailbox.index -1] = 0; + ResponseCmndIdxChar(D_CONFIGURATION_RESET); + } +} + +void CmndShutterSetOpen(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + Shutter[XdrvMailbox.index -1].real_position = Shutter[XdrvMailbox.index -1].open_max; + ShutterStartInit(XdrvMailbox.index -1, 0, Shutter[XdrvMailbox.index -1].open_max); + Settings.shutter_position[XdrvMailbox.index -1] = 100; + ResponseCmndIdxChar(D_CONFIGURATION_RESET); + } +} + +void CmndShutterPwmRange(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + uint8_t i = 0; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 2; str = strtok_r(nullptr, " ", &str_ptr), i++) { + uint16_t field = atoi(str); + + + if ((field <= 0) || (field > 1023)) { + break; + } + Settings.shutter_pwmrange[i][XdrvMailbox.index -1] = field; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); + ShutterInit(); + ResponseCmndIdxChar(XdrvMailbox.data); + } else { + char setting_chr[30] = "0"; + snprintf_P(setting_chr, sizeof(setting_chr), PSTR("Shutter %d: min:%d max:%d"), XdrvMailbox.index, Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); + ResponseCmndIdxChar(setting_chr); + } + } +} + +void CmndShutterCalibration(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + uint8_t i = 0; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field = atoi(str); + + + if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { + break; + } + messwerte[i] = field; + } + for (i = 0; i < 5; i++) { + Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); + } + ShutterInit(); + ResponseCmndIdxChar(XdrvMailbox.data); + } else { + char setting_chr[30] = "0"; + snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); + ResponseCmndIdxChar(setting_chr); + } + } +} + +void ShutterOptionsSetHelper(uint16_t option){ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(option); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (option); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & option) ? 1 : 0); + } +} + +void CmndShutterInvert(void) { + ShutterOptionsSetHelper(1); +} + +void CmndShutterLock(void) { + ShutterOptionsSetHelper(2); +} + +void CmndShutterEnableEndStopTime(void) { + ShutterOptionsSetHelper(4); +} + +void CmndShutterInvertWebButtons(void) { + ShutterOptionsSetHelper(8); +} + + + + + +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: + ShutterUpdatePosition(); + break; + case FUNC_EVERY_SECOND: + + ShutterReportPosition(false, MAX_SHUTTERS); + break; + + case FUNC_COMMAND: + result = DecodeCommand(kShutterCommands, ShutterCommand); + break; + case FUNC_JSON_APPEND: + for (uint8_t i = 0; i < shutters_present; i++) { + uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i] : Settings.shutter_position[i]; + uint8_t target = (Settings.shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter[i].target_position, i) : ShutterRealToPercentPosition(Shutter[i].target_position, i); + + ResponseAppend_P(","); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter[i].direction,target); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_SHUTTER, position); + } +#endif + } + break; + case FUNC_SET_POWER: + char stemp1[10]; + + ShutterGlobal.RelayCurrentMask = XdrvMailbox.index ^ ShutterGlobal.RelayOldMask; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), ShutterGlobal.RelayCurrentMask,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + ShutterRelayChanged(); + ShutterGlobal.RelayOldMask = XdrvMailbox.index; + break; + case FUNC_SET_DEVICE_POWER: + if (ShutterGlobal.skip_relay_change ) { + uint8_t i; + for (i = 0; i < devices_present; i++) { + if (ShutterGlobal.RelayCurrentMask &1) { + break; + } + ShutterGlobal.RelayCurrentMask >>= 1; + } + + result = true; + ShutterGlobal.skip_relay_change = 0; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); + ExecuteCommandPowerShutter(i+1, 0, SRC_SHUTTER); + } + break; + case FUNC_BUTTON_PRESSED: + if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { + ShutterButtonHandler(); + result = true; + } + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_28_pcf8574.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_28_pcf8574.ino" +#ifdef USE_I2C +#ifdef USE_PCF8574 + + + + + + + +#define XDRV_28 28 +#define XI2C_02 2 + +#define PCF8574_ADDR1 0x20 +#define PCF8574_ADDR2 0x38 + +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; + uint8_t max_devices = 0; + char stype[9]; + bool type = false; +} Pcf8574; + +void Pcf8574SwitchRelay(void) +{ + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t relay_state = bitRead(XdrvMailbox.index, 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; + + + + 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(); + } + + } + } +} + +void Pcf8574Init(void) +{ + uint8_t pcf8574_address = PCF8574_ADDR1; + while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { + +#ifdef USE_MCP230xx_ADDR + if (USE_MCP230xx_ADDR == pcf8574_address) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Address 0x%02x reserved for MCP320xx skipped"), pcf8574_address); + pcf8574_address++; + if ((PCF8574_ADDR1 +7) == pcf8574_address) { + pcf8574_address = PCF8574_ADDR2 +1; + } + } +#endif + + + + if (I2cSetDevice(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"); + } + I2cSetActiveFound(pcf8574_address, Pcf8574.stype); + } + + pcf8574_address++; + if ((PCF8574_ADDR1 +7) == pcf8574_address) { + pcf8574_address = PCF8574_ADDR2 +1; + } + } + if (Pcf8574.type) { + for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { + Pcf8574.pin[i] = 99; + } + devices_present = devices_present - Pcf8574.max_connected_ports; + Pcf8574.max_connected_ports = 0; + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + + 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; + + 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"), Pcf8574.max_devices, Pcf8574.max_connected_ports); + } +} + + + + + +#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 " " + "
" + "


"; + +const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = + "" D_DEVICE " %d " D_PORT " %d"; + +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++) { + 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("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void Pcf8574SaveSettings(void) +{ + char stemp[7]; + char tmp[100]; + + + + 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 ); + } + } + + + + } +} +#endif + + + + + +bool Xdrv28(uint8_t function) +{ + if (!I2cEnabled(XI2C_02)) { return false; } + + bool result = false; + + if (FUNC_PRE_INIT == function) { + Pcf8574Init(); + } + else if (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(PSTR("/" WEB_HANDLE_PCF8574), HandlePcf8574); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#ifdef USE_DEEPSLEEP +# 31 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#define XDRV_29 29 + +#define D_PRFX_DEEPSLEEP "DeepSleep" +#define D_CMND_DEEPSLEEP_TIME "Time" + +const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; +const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; +const uint32_t DEEPSLEEP_MIN_TIME = 5; +const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; + +const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" + D_CMND_DEEPSLEEP_TIME ; + +void (* const DeepsleepCommand[])(void) PROGMEM = { + &CmndDeepsleepTime }; + +uint32_t deepsleep_sleeptime = 0; +uint8_t deepsleep_flag = 0; + +bool DeepSleepEnabled(void) +{ + if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { + Settings.deepsleep = 0; + return false; + } + + if (PinUsed(GPIO_DEEPSLEEP)) { + pinMode(Pin(GPIO_DEEPSLEEP), INPUT_PULLUP); + return (digitalRead(Pin(GPIO_DEEPSLEEP))); + } + + return true; +} + +void DeepSleepReInit(void) +{ + if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { + if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { + + RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); + RtcSettingsSave(); + RtcRebootReset(); +#ifdef ESP8266 + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); +#else + esp_sleep_enable_timer_wakeup(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep)); + esp_deep_sleep_start(); +#endif + yield(); + + } + } + + RtcSettings.ultradeepsleep = 0; +} + +void DeepSleepPrepare(void) +{ + + + + + if ((RtcSettings.nextwakeup == 0) || + (RtcSettings.deepsleep_slip < 9000) || + (RtcSettings.deepsleep_slip > 11000) || + (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); + RtcSettings.nextwakeup = 0; + RtcSettings.deepsleep_slip = 10000; + } + + + + int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; + + + + timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; + if (timeslip) { + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); + + RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); + RtcSettings.nextwakeup += Settings.deepsleep; + } + + + + if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { + + RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; + } + + String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); + + + deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_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)); + + + +} + +void DeepSleepStart(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); + + WifiShutdown(); + RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); + RtcSettingsSave(); +#ifdef ESP8266 + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); +#else + esp_sleep_enable_timer_wakeup(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); + esp_deep_sleep_start(); +#endif + yield(); +} + +void DeepSleepEverySecond(void) +{ + if (!deepsleep_flag) { return; } + + if (DeepSleepEnabled()) { + if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { + SettingsSaveAll(); + DeepSleepPrepare(); + } + deepsleep_flag--; + if (deepsleep_flag <= 0) { + DeepSleepStart(); + } + } else { + deepsleep_flag = 0; + } +} + + + + + +void CmndDeepsleepTime(void) +{ + if ((0 == XdrvMailbox.payload) || + ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { + Settings.deepsleep = XdrvMailbox.payload; + RtcSettings.nextwakeup = 0; + deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; + if (deepsleep_flag) { + if (!Settings.tele_period) { + Settings.tele_period = TELE_PERIOD; + } + } + } + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); +} + + + + + +bool Xdrv29(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + DeepSleepEverySecond(); + break; + case FUNC_AFTER_TELEPERIOD: + if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { + deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); + break; + case FUNC_PRE_INIT: + DeepSleepReInit(); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_EXS_DIMMER + + + + + + + +#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 + +#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; + int byte_counter = 0; + int cmd_status = 0; + uint8_t power = 0; + uint8_t dimm[2] = {0, 0}; + DIMMER dimmer; +} Exs; + + + + + +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(); + + + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + + if (!ExsSerial->available()) + { + +#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); +} + +void ExsSetPower(uint8_t device, uint8_t power) +{ + Exs.dimmer.channel[device].dimm = power; + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); +} + +void ExsSetBri(uint8_t device, uint8_t bri) +{ + Exs.dimmer.channel[device].bright_tbl = bri; + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); +} + +void 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); + return true; +} + +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: +# 295 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + if (len > 9) + { + Exs.dimmer.version_major = Exs.buffer[3]; + Exs.dimmer.version_minor = Exs.buffer[4]; + + + 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[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 +# 328 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + { + Exs.dimmer.version_major = 1; + Exs.dimmer.version_minor = 0; + + + 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[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(); + ExsSyncState(); + ExsDebugState(); + break; + default: + break; + } +} + + + +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_ENABLE)); +#endif + + pinMode(Pin(GPIO_EXS_ENABLE), OUTPUT); + digitalWrite(Pin(GPIO_EXS_ENABLE), LOW); + + delay(1); + + while (ExsSerial->available()) + { + + 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]); + + + 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); + ExsPacketProcess(); + } + else + { + ExsSerial->write(0x00); + } + + } + } + } +} + + + + + +#ifdef EXS_MCU_CMNDS + +#define D_PRFX_EXS "Exs" +#define D_CMND_EXS_DIMM "Dimm" +#define D_CMND_EXS_DIMM_TBL "DimmTbl" +#define D_CMND_EXS_DIMM_VAL "DimmVal" +#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_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" + D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" + D_CMND_EXS_STATE; + +void (* const ExsCommand[])(void) PROGMEM = { + &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, + &CmndExsDimms, &CmndExsChLock, + &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 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); + + + 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 + + + + + +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 +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_31_tasmota_client.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_31_tasmota_client.ino" +#ifdef USE_TASMOTA_CLIENT + + + + +#define XDRV_31 31 + +#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 + + + + + +#define CMND_START 0xFC +#define CMND_END 0xFD + +#define CMND_FEATURES 0x01 +#define CMND_JSON 0x02 +#define CMND_FUNC_EVERY_SECOND 0x03 +#define CMND_FUNC_EVERY_100_MSECOND 0x04 +#define CMND_CLIENT_SEND 0x05 +#define CMND_PUBLISH_TELE 0x06 +#define CMND_EXECUTE_CMND 0x07 + +#define PARAM_DATA_START 0xFE +#define PARAM_DATA_END 0xFF + +#include + + + + + +class SimpleHexParse { + public: + SimpleHexParse(void); + uint8_t parseLine(char *hexline); + uint8_t ptr_l = 0; + uint8_t ptr_h = 0; + bool PageIsReady = false; + bool firstrun = true; + bool EndOfFile = false; + uint8_t FlashPage[128]; + uint8_t FlashPageIdx = 0; + uint8_t layoverBuffer[16]; + uint8_t layoverIdx = 0; + uint8_t getByte(char *hexline, uint8_t idx); +}; + +SimpleHexParse::SimpleHexParse(void) { + +} + +uint8_t SimpleHexParse::parseLine(char *hexline) { + if (layoverIdx) { + memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); + FlashPageIdx = layoverIdx; + layoverIdx = 0; + } + uint8_t len = getByte(hexline, 1); + uint8_t addr_h = getByte(hexline, 2); + uint8_t addr_l = getByte(hexline, 3); + uint8_t rectype = getByte(hexline, 4); + for (uint8_t idx = 0; idx < len; idx++) { + if (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = getByte(hexline, idx+5); + FlashPageIdx++; + } else { + layoverBuffer[layoverIdx] = getByte(hexline, idx+5); + layoverIdx++; + } + } + if (1 == rectype) { + EndOfFile = true; + while (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = 0xFF; + FlashPageIdx++; + } + } + if (FlashPageIdx == 128) { + if (firstrun) { + firstrun = false; + } else { + ptr_l += 0x40; + if (ptr_l == 0) { + ptr_l = 0; + ptr_h++; + } + } + firstrun = false; + PageIsReady = true; + } + return 0; +} + +uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) { + char buff[3]; + buff[3] = '\0'; + memcpy(&buff, &hexline[(idx*2)-1], 2); + return strtol(buff, 0, 16); +} + + + + + +struct TCLIENT { + 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; + bool SerialEnabled = false; + uint8_t waitstate = 0; + bool unsupported = false; +} TClient; + +typedef union { + uint32_t data; + struct { + uint32_t func_json_append : 1; + uint32_t func_every_second : 1; + uint32_t func_every_100_msecond : 1; + uint32_t func_client_send : 1; + uint32_t spare4 : 1; + uint32_t spare5 : 1; + uint32_t spare6 : 1; + uint32_t spare7 : 1; + uint32_t spare8 : 1; + uint32_t spare9 : 1; + uint32_t spare10 : 1; + uint32_t spare11 : 1; + uint32_t spare12 : 1; + uint32_t spare13 : 1; + uint32_t spare14 : 1; + uint32_t spare15 : 1; + uint32_t spare16 : 1; + uint32_t spare17 : 1; + uint32_t spare18 : 1; + uint32_t spare19 : 1; + uint32_t spare20 : 1; + uint32_t spare21 : 1; + uint32_t spare22 : 1; + uint32_t spare23 : 1; + uint32_t spare24 : 1; + uint32_t spare25 : 1; + uint32_t spare26 : 1; + uint32_t spare27 : 1; + uint32_t spare28 : 1; + uint32_t spare29 : 1; + uint32_t spare30 : 1; + uint32_t spare31 : 1; + }; +} TClientFeatureCfg; + + + + + + +struct TCLIENT_FEATURES { + uint32_t features_version; + TClientFeatureCfg features; +} TClientSettings; + +struct TCLIENT_COMMAND { + uint8_t command; + uint8_t parameter; + uint8_t unused2; + uint8_t unused3; +} TClientCommand; + +TasmotaSerial *TasmotaClient_Serial; + +uint32_t TasmotaClient_FlashStart(void) { + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; +} + +uint8_t TasmotaClient_UpdateInit(void) { + TClient.spi_hex_size = 0; + TClient.spi_sector_counter = TasmotaClient_FlashStart(); + TClient.spi_sector_cursor = 0; + return 0; +} + +void TasmotaClient_Reset(void) { + if (TClient.SerialEnabled) { + digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted); + delay(1); + digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), TClient.inverted); + delay(1); + digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted); + delay(5); + } +} + +uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout) { + int timer = 0; + while (timer < timeout) { + if (TasmotaClient_Serial->available() >= dataCount) { + return 1; + } + delay(1); + timer++; + } + return 0; +} + +uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count) { + TasmotaClient_Serial->write(bytes, count); + TasmotaClient_waitForSerialData(2, 250); + uint8_t sync = TasmotaClient_Serial->read(); + uint8_t ok = TasmotaClient_Serial->read(); + if ((sync == 0x14) && (ok == 0x10)) { + return 1; + } + return 0; +} + +uint8_t TasmotaClient_execCmd(uint8_t cmd) { + uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; + return TasmotaClient_sendBytes(bytes, 2); +} + +uint8_t TasmotaClient_execParam(uint8_t cmd, uint8_t* params, int count) { + uint8_t 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 TasmotaClient_sendBytes(bytes, i + 2); +} + +uint8_t TasmotaClient_exitProgMode(void) { + return TasmotaClient_execCmd(CMND_STK_LEAVE_PROGMODE); +} + +uint8_t TasmotaClient_SetupFlash(void) { + 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}; + TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_FLASH_SPEED); + if (TasmotaClient_Serial->hardwareSerial()) { + ClaimSerial(); + } + + TasmotaClient_Reset(); + + uint8_t timeout = 0; + uint8_t no_error = 0; + while (50 > timeout) { + if (TasmotaClient_execCmd(CMND_STK_GET_SYNC)) { + timeout = 200; + no_error = 1; + } + timeout++; + delay(1); + } + if (no_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Found bootloader")); + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Bootloader could not be found")); + } + if (no_error) { + if (TasmotaClient_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (1)")); + } + } + if (no_error) { + if (TasmotaClient_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (2)")); + } + } + if (no_error) { + if (TasmotaClient_execCmd(CMND_STK_ENTER_PROGMODE)) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Failed to put bootloader into programming mode")); + } + } + return no_error; +} + +uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo) { + uint8_t params[] = { adrLo, adrHi }; + return TasmotaClient_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); +} + +void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { + uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; + TasmotaClient_loadAddress(addr_h, addr_l); + TasmotaClient_Serial->write(Header, 4); + for (int i = 0; i < 128; i++) { + TasmotaClient_Serial->write(data[i]); + } + TasmotaClient_Serial->write(CONST_STK_CRC_EOP); + TasmotaClient_waitForSerialData(2, 250); + TasmotaClient_Serial->read(); + TasmotaClient_Serial->read(); +} + +void TasmotaClient_Flash(void) { + bool reading = true; + uint32_t read = 0; + uint32_t processed = 0; + char thishexline[50]; + uint8_t position = 0; + char* flash_buffer; + + SimpleHexParse hexParse = SimpleHexParse(); + + if (!TasmotaClient_SetupFlash()) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flashing aborted!")); + TClient.flashing = false; + restart_flag = 2; + return; + } + + flash_buffer = new char[SPI_FLASH_SEC_SIZE]; + uint32_t flash_start = TasmotaClient_FlashStart() * SPI_FLASH_SEC_SIZE; + while (reading) { + ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); + read = read + SPI_FLASH_SEC_SIZE; + if (read >= TClient.spi_hex_size) { + reading = false; + } + for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { + processed++; + if ((processed <= TClient.spi_hex_size) && (!hexParse.EndOfFile)) { + if (':' == flash_buffer[ca]) { + position = 0; + } + if (0x0D == flash_buffer[ca]) { + thishexline[position] = 0; + hexParse.parseLine(thishexline); + if (hexParse.PageIsReady) { + TasmotaClient_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); + hexParse.PageIsReady = false; + hexParse.FlashPageIdx = 0; + } + } else { + if (0x0A != flash_buffer[ca]) { + thishexline[position] = flash_buffer[ca]; + position++; + } + } + } + } + } + TasmotaClient_exitProgMode(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flash done!")); + TClient.flashing = false; + restart_flag = 2; +} + +void TasmotaClient_SetFlagFlashing(bool value) { + TClient.flashing = value; +} + +bool TasmotaClient_GetFlagFlashing(void) { + return TClient.flashing; +} + +void TasmotaClient_WriteBuffer(uint8_t *buf, size_t size) { + if (0 == TClient.spi_sector_cursor) { + ESP.flashEraseSector(TClient.spi_sector_counter); + } + TClient.spi_sector_cursor++; + ESP.flashWrite((TClient.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TClient.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); + TClient.spi_hex_size = TClient.spi_hex_size + size; + if (2 == TClient.spi_sector_cursor) { + TClient.spi_sector_cursor = 0; + TClient.spi_sector_counter++; + } +} + +void TasmotaClient_Init(void) { + if (TClient.type) { + return; + } + if (10 > TClient.waitstate) { + TClient.waitstate++; + return; + } + if (!TClient.SerialEnabled) { + if (PinUsed(GPIO_TASMOTACLIENT_RXD) && PinUsed(GPIO_TASMOTACLIENT_TXD) && + (PinUsed(GPIO_TASMOTACLIENT_RST) || PinUsed(GPIO_TASMOTACLIENT_RST_INV))) { + TasmotaClient_Serial = new TasmotaSerial(Pin(GPIO_TASMOTACLIENT_RXD), Pin(GPIO_TASMOTACLIENT_TXD), 1, 0, 200); + if (TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_SERIAL_SPEED)) { + if (TasmotaClient_Serial->hardwareSerial()) { + ClaimSerial(); + } + TasmotaClient_Serial->setTimeout(100); + if (PinUsed(GPIO_TASMOTACLIENT_RST_INV)) { + SetPin(Pin(GPIO_TASMOTACLIENT_RST_INV), AGPIO(GPIO_TASMOTACLIENT_RST)); + TClient.inverted = HIGH; + } + pinMode(Pin(GPIO_TASMOTACLIENT_RST), OUTPUT); + TClient.SerialEnabled = true; + TasmotaClient_Reset(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Enabled")); + } + } + } + if (TClient.SerialEnabled) { + TasmotaClient_sendCmnd(CMND_FEATURES, 0); + char buffer[32] = { 0 }; + TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); + uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); + + if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } + + memcpy(&TClientSettings, &buffer, sizeof(TClientSettings)); + if (20191129 == TClientSettings.features_version) { + TClient.type = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version); + } else { + if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version); + TClient.unsupported = true; + } + } + } +} + +bool TasmotaClient_Available(void) { + return TClient.SerialEnabled; +} + +void TasmotaClient_Show(void) { + if ((TClient.type) && (TClientSettings.features.func_json_append)) { + char buffer[100]; + TasmotaClient_sendCmnd(CMND_JSON, 0); + TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); + uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); + buffer[len] = '\0'; + ResponseAppend_P(PSTR(",\"TasmotaClient\":%s"), buffer); + } +} + +void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param) { + TClientCommand.command = cmnd; + TClientCommand.parameter = param; + char buffer[sizeof(TClientCommand)+2]; + buffer[0] = CMND_START; + memcpy(&buffer[1], &TClientCommand, sizeof(TClientCommand)); + buffer[sizeof(TClientCommand)+1] = CMND_END; + + TasmotaClient_Serial->flush(); + + for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { + TasmotaClient_Serial->write(buffer[ca]); + } +} + +#define D_PRFX_CLIENT "Client" +#define D_CMND_CLIENT_RESET "Reset" +#define D_CMND_CLIENT_SEND "Send" + +const char kTasmotaClientCommands[] PROGMEM = D_PRFX_CLIENT "|" + D_CMND_CLIENT_RESET "|" D_CMND_CLIENT_SEND; + +void (* const TasmotaClientCommand[])(void) PROGMEM = { + &CmndClientReset, &CmndClientSend }; + +void CmndClientReset(void) { + TasmotaClient_Reset(); + TClient.type = false; + TClient.waitstate = 7; + TClient.unsupported = false; + ResponseCmndDone(); +} + +void CmndClientSend(void) { + if (TClient.SerialEnabled) { + if (0 < XdrvMailbox.data_len) { + TasmotaClient_sendCmnd(CMND_CLIENT_SEND, XdrvMailbox.data_len); + TasmotaClient_Serial->write(char(PARAM_DATA_START)); + for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + TasmotaClient_Serial->write(XdrvMailbox.data[idx]); + } + TasmotaClient_Serial->write(char(PARAM_DATA_END)); + } + ResponseCmndDone(); + } +} + +void TasmotaClient_ProcessIn(void) { + uint8_t cmnd = TasmotaClient_Serial->read(); + if (CMND_START == cmnd) { + TasmotaClient_waitForSerialData(sizeof(TClientCommand),50); + uint8_t buffer[sizeof(TClientCommand)]; + for (uint8_t idx = 0; idx < sizeof(TClientCommand); idx++) { + buffer[idx] = TasmotaClient_Serial->read(); + } + TasmotaClient_Serial->read(); + memcpy(&TClientCommand, &buffer, sizeof(TClientCommand)); + char inbuf[TClientCommand.parameter+1]; + TasmotaClient_waitForSerialData(TClientCommand.parameter, 50); + TasmotaClient_Serial->read(); + for (uint8_t idx = 0; idx < TClientCommand.parameter; idx++) { + inbuf[idx] = TasmotaClient_Serial->read(); + } + TasmotaClient_Serial->read(); + inbuf[TClientCommand.parameter] = '\0'; + + if (CMND_PUBLISH_TELE == TClientCommand.command) { + Response_P(PSTR("{\"TasmotaClient\":")); + ResponseAppend_P("%s", inbuf); + ResponseJsonEnd(); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, mqtt_data); + } + if (CMND_EXECUTE_CMND == TClientCommand.command) { + ExecuteCommand(inbuf, SRC_IGNORE); + } + } +} + + + + + +bool Xdrv31(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if (TClient.type) { + if (TasmotaClient_Serial->available()) { + TasmotaClient_ProcessIn(); + } + if (TClientSettings.features.func_every_100_msecond) { + TasmotaClient_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); + } + } + break; + case FUNC_EVERY_SECOND: + if ((TClient.type) && (TClientSettings.features.func_every_second)) { + TasmotaClient_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); + } + TasmotaClient_Init(); + break; + case FUNC_JSON_APPEND: + if ((TClient.type) && (TClientSettings.features.func_json_append)) { + TasmotaClient_Show(); + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kTasmotaClientCommands, TasmotaClientCommand); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_32_hotplug.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_32_hotplug.ino" +#ifdef USE_HOTPLUG + + + + + + + +#define XDRV_32 32 + +const uint32_t HOTPLUG_MAX = 254; + +const char kHotPlugCommands[] PROGMEM = "|" + D_CMND_HOTPLUG; + +void (* const HotPlugCommand[])(void) PROGMEM = { + &CmndHotPlugTime }; + +struct { + + bool enabled = false; + uint8_t timeout = 0; +} Hotplug; + +void HotPlugInit(void) +{ + + if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } + if (Settings.hotplug_scan != 0) { + Hotplug.enabled = true; + Hotplug.timeout = 1; + } else + Hotplug.enabled = false; +} + +void HotPlugEverySecond(void) +{ + if (Hotplug.enabled) { + if (Hotplug.timeout == 0) { + XsnsCall(FUNC_HOTPLUG_SCAN); + Hotplug.timeout = Settings.hotplug_scan; + } + Hotplug.timeout--; + } +} + + + + + +void CmndHotPlugTime(void) +{ + if (XdrvMailbox.payload <= HOTPLUG_MAX) { + Settings.hotplug_scan = XdrvMailbox.payload; + HotPlugInit(); + } + ResponseCmndNumber(Settings.hotplug_scan); +} + + + + + +bool Xdrv32(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + HotPlugEverySecond(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kHotPlugCommands, HotPlugCommand); + break; + case FUNC_PRE_INIT: + HotPlugInit(); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +# 31 "/workspace/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 + + + + + + + +#define XDRV_33 33 + +#include + +const char NRF24type[] PROGMEM = "NRF24"; + +struct { + uint8_t chipType = 0; +} NRF24; + + + +RF24 NRF24radio; + +bool NRF24initRadio() +{ + NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); + NRF24radio.powerUp(); + + if(NRF24radio.isChipConnected()){ + DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); + return true; + } + DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); + return false; +} + +bool NRF24Detect(void) +{ + if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_DC)) { + if(NRF24initRadio()){ + NRF24.chipType = 32; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); + if(NRF24radio.isPVariant()){ + NRF24.chipType = 43; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); + } + return true; + } + } + return false; +} + + + + + +bool Xdrv33(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + result = NRF24Detect(); + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +#ifdef USE_I2C +#ifdef USE_WEMOS_MOTOR_V1 +# 45 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +#define XDRV_34 34 +#define XI2C_44 44 + +#ifndef WEMOS_MOTOR_V1_ADDR +#define WEMOS_MOTOR_V1_ADDR 0x30 +#endif +#ifndef WEMOS_MOTOR_V1_FREQ +#define WEMOS_MOTOR_V1_FREQ 1000 +#endif + +#define MOTOR_A 0 +#define MOTOR_B 1 + +#define SHORT_BRAKE 0 +#define CCW 1 +#define CW 2 +#define STOP 3 +#define STANDBY 4 + +struct WMOTORV1 { + bool detected = false; + uint8_t motor; +} WMotorV1; + +void WMotorV1Detect(void) +{ + if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) { + WMotorV1.detected = true; + I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); + WMotorV1Reset(); + } +} + +void WMotorV1Reset(void) +{ + + WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ); +} + +void WMotorV1SetFrequency(uint32_t freq) +{ + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); + Wire.write(((byte)(freq >> 16)) & (byte)0x0f); + Wire.write((byte)(freq >> 16)); + Wire.write((byte)(freq >> 8)); + Wire.write((byte)freq); + Wire.endTransmission(); + +} + +void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val) +{ + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); + Wire.write(motor | (byte)0x10); + Wire.write(dir); + + uint16_t _pwm_val = uint16_t(pwm_val * 100); + if (_pwm_val > 10000) { + _pwm_val = 10000; + } + + Wire.write((byte)(_pwm_val >> 8)); + Wire.write((byte)_pwm_val); + Wire.endTransmission(); + +} + +bool WMotorV1Command(void) +{ + uint8_t args_count = 0; + + if (XdrvMailbox.data_len > 0) { + args_count = 1; + } else { + return false; + } + + for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + if (' ' == XdrvMailbox.data[idx]) { + XdrvMailbox.data[idx] = ','; + } + if (',' == XdrvMailbox.data[idx]) { + args_count++; + } + } + UpperCase(XdrvMailbox.data, XdrvMailbox.data); + + char *command = strtok(XdrvMailbox.data, ","); + + if (strcmp(command, "RESET") == 0) { + WMotorV1Reset(); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); + return true; + } + + if (strcmp(command, "SETMOTOR") == 0) { + if (args_count >= 3) { + + int motor = atoi(strtok(NULL, ",")); + int dir = atoi(strtok(NULL, ",")); + int duty = 100; + if (args_count == 4) { + duty = atoi(strtok(NULL, ",")); + } + + WMotorV1SetMotor(motor, dir, duty); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); + return true; + } + } + return false; +} + + + + + +bool Xdrv34(uint8_t function) +{ + if (!I2cEnabled(XI2C_44)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + WMotorV1Detect(); + } + else if (WMotorV1.detected) { + switch (function) { + case FUNC_COMMAND_DRIVER: + if (XI2C_44 == XdrvMailbox.index) { + result = WMotorV1Command(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" +#ifdef USE_PWM_DIMMER +# 33 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" +#define XDRV_35 35 +#define MAX_PWM_DIMMER_KEYS 3 + +const char kPWMDimmerCommands[] PROGMEM = "|" + D_CMND_BRI_PRESET +#ifdef USE_DEVICE_GROUPS + "|" D_CMND_PWM_DIMMER_PWMS +#endif + ; + +void (* const PWMDimmerCommand[])(void) PROGMEM = { + &CmndBriPreset, +#ifdef USE_DEVICE_GROUPS + &CmndPWMDimmerPWMs, +#endif + }; + +#ifdef USE_PWM_DIMMER_REMOTE +struct remote_pwm_dimmer { + bool power_on; + uint8_t bri_power_on; + uint8_t bri_preset_low; + uint8_t bri_preset_high; + uint8_t fixed_color_index; + uint8_t bri; + bool power_button_increases_bri; +}; +#endif + +uint32_t ignore_any_key_time = 0; +uint32_t button_hold_time[3]; +uint8_t led_timeout_seconds = 0; +uint8_t restore_powered_off_led_counter = 0; +uint8_t power_button_index = 0; +uint8_t down_button_index = 1; +uint8_t buttons_pressed = 0; +uint8_t local_fixed_color_index = 128; +bool button_tapped = false; +bool down_button_tapped = false; +bool ignore_power_button = false; +bool multibutton_in_progress = false; +bool power_button_increases_bri = true; +bool tap_handled = false; +bool invert_power_button_bri_direction = false; +bool button_pressed[3] = { false, false, false }; +bool button_held[3]; +#ifdef USE_PWM_DIMMER_REMOTE +struct remote_pwm_dimmer remote_pwm_dimmers[MAX_PWM_DIMMER_KEYS]; +struct remote_pwm_dimmer * active_remote_pwm_dimmer; +#endif + +void PWMModulePreInit(void) +{ + Settings.seriallog_level = 0; + Settings.flag.mqtt_serial = 0; + Settings.ledstate = 0; + + + if (Settings.last_module != Settings.module) { + Settings.flag.pwm_control = true; + Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0; + Settings.last_module = Settings.module; + + + + + + if (Settings.param[P_HOLD_TIME] == 5) Settings.param[P_HOLD_TIME] = 40; + } + + + if (!Settings.bri_power_on) Settings.bri_power_on = 128; + if (!Settings.bri_preset_low) Settings.bri_preset_low = 10; + if (Settings.bri_preset_high < Settings.bri_preset_low) Settings.bri_preset_high = 255; + + PWMDimmerSetPoweredOffLed(); + + + + +#ifdef USE_PWM_DIMMER_REMOTE + + + if (Settings.flag4.multiple_device_groups) { + Settings.flag4.device_groups_enabled = true; + + device_group_count = 0; + for (uint32_t button_index = 0; button_index < MAX_PWM_DIMMER_KEYS; button_index++) { + if (PinUsed(GPIO_KEY1, button_index)) device_group_count++; + } + + + if (!PinUsed(GPIO_REL1) && !PinUsed(GPIO_PWM1)) { + first_device_group_is_local = false; + + + devices_present--; + light_type = 0; + } + + for (uint8_t i = 0; i < MAX_PWM_DIMMER_KEYS; i++) { + active_remote_pwm_dimmer = &remote_pwm_dimmers[i]; + active_remote_pwm_dimmer->bri_power_on = 128; + active_remote_pwm_dimmer->bri_preset_low = 10; + active_remote_pwm_dimmer->bri_preset_high = 255; + active_remote_pwm_dimmer->fixed_color_index = 128; + } + } +#endif +} + + +void PWMDimmerSetBrightnessLeds(int32_t bri) +{ + + uint32_t leds = 0; + uint32_t mask = 1; + int32_t led; + for (led = 0; led < leds_present; led++) { + if (Settings.ledmask & mask) leds++; + mask <<= 1; + } + + + + if (leds) { + led_timeout_seconds = 5; + if (bri < 0) { + bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri()); + if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0; + } + uint32_t step = 256 / (leds + 1); + + + uint32_t level = 0; + led = -1; + mask = 0; + for (uint32_t count = 0; count < leds; count++) { + level += step; + for (;;) { + led++; + mask <<= 1; + if (!mask) mask = 1; + if (Settings.ledmask & mask) break; + } + SetLedPowerIdx(led, bri >= level); + } + } +} + +void PWMDimmerSetPoweredOffLed(void) +{ + + if (PinUsed(GPIO_LEDLNK)) { + bool power_off_led_on = !power && Settings.flag4.powered_off_led; + if (ledlnk_inverted) power_off_led_on ^= 1; + digitalWrite(Pin(GPIO_LEDLNK), power_off_led_on); + } +} + +void PWMDimmerSetPower(void) +{ + DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power); + PWMDimmerSetBrightnessLeds(-1); + PWMDimmerSetPoweredOffLed(); +} + +#ifdef USE_DEVICE_GROUPS +void PWMDimmerHandleDevGroupItem(void) +{ +#ifdef USE_PWM_DIMMER_REMOTE + uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic; + bool is_local = ((XdrvMailbox.index & DGR_FLAG_LOCAL) != 0); + if (device_group_index > MAX_PWM_DIMMER_KEYS) return; + struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index]; +#else + if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return; +#endif + uint32_t value = XdrvMailbox.payload; + + switch (XdrvMailbox.command_code) { +#ifdef USE_PWM_DIMMER_REMOTE + case DGR_ITEM_LIGHT_BRI: + remote_pwm_dimmer->bri = value; + break; + case DGR_ITEM_POWER: + remote_pwm_dimmer->power_on = value & 1; + remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128); + break; +#endif + case DGR_ITEM_LIGHT_FIXED_COLOR: +#ifdef USE_PWM_DIMMER_REMOTE + remote_pwm_dimmer->fixed_color_index = value; + if (is_local) +#endif + local_fixed_color_index = value; + break; + case DGR_ITEM_BRI_POWER_ON: +#ifdef USE_PWM_DIMMER_REMOTE + remote_pwm_dimmer->bri_power_on = value; + if (is_local) +#endif + Settings.bri_power_on = value; + break; + case DGR_ITEM_BRI_PRESET_LOW: +#ifdef USE_PWM_DIMMER_REMOTE + remote_pwm_dimmer->bri_preset_low = value; + if (is_local) +#endif + Settings.bri_preset_low = value; + break; + case DGR_ITEM_BRI_PRESET_HIGH: +#ifdef USE_PWM_DIMMER_REMOTE + remote_pwm_dimmer->bri_preset_high = value; + if (is_local) +#endif + Settings.bri_preset_high = value; + break; + case DGR_ITEM_STATUS: +#ifdef USE_PWM_DIMMER_REMOTE + if (is_local) +#endif + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on, + DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); + break; + } +} +#endif + +void PWMDimmerHandleButton(uint32_t button_index, bool pressed) +{ + bool handle_tap = false; + bool state_updated = false; + int32_t bri_offset = 0; + uint8_t power_on_bri = 0; + uint8_t dgr_item = 0; + uint8_t dgr_value = 0; + uint8_t dgr_more_to_come = true; + uint8_t mqtt_trigger = 0; + + +#ifdef USE_PWM_DIMMER_REMOTE + bool power_is_on = (active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : power); + bool is_power_button = (button_index == power_button_index); + bool is_down_button = (button_index == down_button_index); +#else + bool power_is_on = power; + bool is_power_button = !button_index; + bool is_down_button = (button_index == (power_button_index ? 0 : 1)); +#endif + + + if (pressed) { + uint32_t now = millis(); + + + if (is_power_button) { + + + if (!ignore_power_button && buttons_pressed == 1) { + + + + + if (power_is_on) { +#ifdef USE_PWM_DIMMER_REMOTE + bri_offset = (active_remote_pwm_dimmer ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); +#else + bri_offset = (power_button_increases_bri ? 1 : -1); +#endif + invert_power_button_bri_direction = true; + } + + + + else { +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; + else +#endif + power_on_bri = Settings.bri_preset_low; + button_hold_time[button_index] = now + 500; + } + } + } + + + else { + + + if (button_pressed[power_button_index]) { + + + + if (button_tapped) { + handle_tap = true; + button_hold_time[button_index] = now + 500; + } + + + + else if (power_is_on && Settings.flag4.multiple_device_groups) { + bri_offset = (is_down_button ? -1 : 1); + } + + + else { + mqtt_trigger = (is_down_button ? 1 : 2); + button_hold_time[button_index] = now + 60000; + ignore_power_button = true; + } + } + + + + else if (power_is_on && !button_tapped) { + bri_offset = (is_down_button ? -1 : 1); + } + } + } + + + else { + bool button_was_held = button_held[button_index]; + + + if (is_power_button) { + + + + + if (button_tapped) { + if (!tap_handled) { +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_remote_pwm_dimmer) { +#endif + + + if (down_button_tapped) { + Settings.flag4.led_timeout ^= 1; + if (Light.power) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? 0 : -1); + } + + + else { + Settings.flag4.powered_off_led ^= 1; + PWMDimmerSetPoweredOffLed(); + } +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif + } + tap_handled = false; + } + + + else if (button_was_held) { + + + + if (invert_power_button_bri_direction) { + invert_power_button_bri_direction = false; +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + active_remote_pwm_dimmer->power_button_increases_bri ^= 1; + else +#endif + power_button_increases_bri ^= 1; +#ifdef USE_PWM_DIMMER_REMOTE + dgr_item = DGR_ITEM_FLAGS; + state_updated = true; +#endif + } + } + + + + else if (!ignore_power_button) { +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + power_on_bri = active_remote_pwm_dimmer->bri_power_on; + else +#endif + power_on_bri = Settings.bri_power_on; + } + } + + + else { + + + + if (button_pressed[power_button_index]) { + ignore_power_button = true; + + + if (button_tapped) { + handle_tap = true; + } + + + else if (!button_was_held) { + button_tapped = true; + down_button_tapped = is_down_button; + } + } + + + else { + + + if (power_is_on) { + + + + if (!button_was_held) { + bri_offset = (is_down_button ? -5 : 5); + dgr_more_to_come = false; + state_updated = true; + } + + + + else { + dgr_item = DGR_ITEM_FLAGS; + state_updated = true; + } + } + + + + else { +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); + else +#endif + power_on_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); + } + } + } + } + + + if (bri_offset) { + int32_t bri; +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + bri = active_remote_pwm_dimmer->bri; + else +#endif + bri = light_state.getBri(); + int32_t new_bri = bri + bri_offset * ((dgr_item ? 16 : Settings.light_correction ? 4 : bri / 16 + 1)); + + if (bri_offset > 0) { + if (new_bri > 255) new_bri = 255; + } + else { + if (new_bri < 1) new_bri = 1; + } + if (new_bri != bri) { +#ifdef USE_DEVICE_GROUPS + SendDeviceGroupMessage(power_button_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_BRI, new_bri); +#endif +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) { + active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; + PWMDimmerSetBrightnessLeds(new_bri); + } + else { +#endif + skip_light_fade = true; +#ifdef USE_DEVICE_GROUPS + ignore_dgr_sends = true; +#endif + light_state.setBri(new_bri); + LightAnimate(); + skip_light_fade = false; +#ifdef USE_DEVICE_GROUPS + ignore_dgr_sends = false; +#endif + Settings.bri_power_on = new_bri; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif + } +#ifdef USE_PWM_DIMMER_REMOTE + else if (active_remote_pwm_dimmer) + PWMDimmerSetBrightnessLeds(new_bri); +#endif + else + PWMDimmerSetBrightnessLeds(-1); + } + + + else if (power_on_bri) { + power_t new_power; +#ifdef USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) { + active_remote_pwm_dimmer->power_on ^= 1; + new_power = active_remote_pwm_dimmer->power_on; + PWMDimmerSetBrightnessLeds(new_power ? -power_on_bri : 0); + } + else { +#endif + new_power = power ^ 1; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif + if (new_power) + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, power_on_bri, DGR_ITEM_POWER, new_power); + else + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, new_power); +#endif +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) + active_remote_pwm_dimmer->power_button_increases_bri = (power_on_bri < 128); + else { +#endif + light_state.setBri(power_on_bri); +#ifdef USE_DEVICE_GROUPS + Light.devgrp_no_channels_out = true; +#endif + ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); +#ifdef USE_DEVICE_GROUPS + Light.devgrp_no_channels_out = false; +#endif +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif + } + + + + if (handle_tap) { + ignore_power_button = tap_handled = true; + + + + if (down_button_tapped) { +#ifdef USE_DEVICE_GROUPS + int8_t add_value = (is_down_button ? -1 : 1); +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) { + active_remote_pwm_dimmer->fixed_color_index += add_value; + dgr_value = active_remote_pwm_dimmer->fixed_color_index; + } + else { +#endif + local_fixed_color_index += add_value; + dgr_value = local_fixed_color_index; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif + dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR; +#endif + ; + } + + else { + mqtt_trigger = (is_down_button ? 3 : 4); + } + } + + + if (mqtt_trigger) { + char topic[TOPSZ]; + sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); +#ifdef USE_PWM_DIMMER_REMOTE + if (active_remote_pwm_dimmer) { + snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/EVENT"), device_groups[power_button_index].group_name); + MqttPublish(topic); + } + else +#endif + MqttPublishPrefixTopic_P(CMND, PSTR("EVENT")); + } + + + if (dgr_item) { +#ifdef USE_DEVICE_GROUPS + DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT; +#ifdef USE_PWM_DIMMER_REMOTE + if (handle_tap && !active_remote_pwm_dimmer) +#else + if (handle_tap) +#endif + message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL); + SendDeviceGroupMessage(power_button_index, message_type, dgr_item, dgr_value); +#endif +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_remote_pwm_dimmer) +#endif + light_controller.saveSettings(); + } + + if (state_updated && Settings.flag3.hass_tele_on_power) { +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_remote_pwm_dimmer) +#endif + MqttPublishTeleState(); + } +} + + + + + +void CmndBriPreset(void) +{ + if (XdrvMailbox.data_len > 0) { + bool valid = true; + uint32_t value; + uint8_t parm[2]; + parm[0] = Settings.bri_preset_low; + parm[1] = Settings.bri_preset_high; + char * ptr = XdrvMailbox.data; + for (uint32_t i = 0; i < 2; i++) { + while (*ptr == ' ') ptr++; + if (*ptr == '+') { + if (parm[i] < 255) parm[i]++; + } + else if (*ptr == '-') { + if (parm[i] > 1) parm[i]--; + } + else { + value = strtoul(ptr, &ptr, 0); + if (value < 1 || value > 255) { + valid = false; + break; + } + parm[i] = value; + if (*ptr != ',') break; + } + ptr++; + } + if (valid && !*ptr) { + if (parm[0] < parm[1]) { + Settings.bri_preset_low = parm[0]; + Settings.bri_preset_high = parm[1]; + } else + { + Settings.bri_preset_low = parm[1]; + Settings.bri_preset_high = parm[0]; + } +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); +#endif + } + } + Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings.bri_preset_low, Settings.bri_preset_high); +} + +#ifdef USE_DEVICE_GROUPS +void CmndPWMDimmerPWMs(void) +{ + if (XdrvMailbox.data_len > 0 && XdrvMailbox.payload <= 5) { + Settings.pwm_dimmer_cfg.pwm_count = XdrvMailbox.payload - 1; + restart_flag = 2; + } + Response_P(PSTR("{\"" D_CMND_PWM_DIMMER_PWMS "\":%u}"), Settings.pwm_dimmer_cfg.pwm_count + 1); +} +#endif + + + + + +bool Xdrv35(uint8_t function) +{ + bool result = false; + + if (PWM_DIMMER != my_module_type) return result; + + switch (function) { + case FUNC_EVERY_SECOND: + + if (led_timeout_seconds && !--led_timeout_seconds) { + PWMDimmerSetBrightnessLeds(-2); + } + + + + + + if (global_state.data) + restore_powered_off_led_counter = 5; + else if (restore_powered_off_led_counter) { + PWMDimmerSetPoweredOffLed(); + restore_powered_off_led_counter--; + } + break; + + case FUNC_BUTTON_PRESSED: + + if (!XdrvMailbox.payload || button_pressed[XdrvMailbox.index]) { + uint32_t button_index = XdrvMailbox.index; + uint32_t now = millis(); + + + if (!XdrvMailbox.payload) { + + + + if (!button_pressed[button_index]) { + button_pressed[button_index] = true; + button_hold_time[button_index] = now + (button_index == power_button_index ? 500 : 250); + buttons_pressed++; + if (buttons_pressed > 1) multibutton_in_progress = true; + +#ifdef USE_PWM_DIMMER_REMOTE +# 759 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" + if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) { + power_button_index = button_index; + down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? gpio_pin[1] : gpio_pin[15]) - 32; + active_remote_pwm_dimmer = nullptr; + if (power_button_index || !first_device_group_is_local) + active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index]; + } +#endif + } + + + else if (button_hold_time[button_index] <= now) { + PWMDimmerHandleButton(button_index, true); + button_held[button_index] = true; + } + } + + + + else { + button_pressed[button_index] = false; + buttons_pressed--; + + + if (multibutton_in_progress || button_held[button_index]) { + PWMDimmerHandleButton(button_index, false); + + + + ignore_any_key_time = now + 500; + } + + + if (button_index == power_button_index) { + if (ignore_power_button) ignore_any_key_time = now + 500; + ignore_power_button = false; + button_tapped = false; + } + button_held[button_index] = false; + } + + + if (multibutton_in_progress) { + result = true; + if (buttons_pressed == 0) multibutton_in_progress = false; + } + } + break; + + case FUNC_ANY_KEY: + { + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + if ((state == 2 || state == 10) && ignore_any_key_time < millis()) { + PWMDimmerHandleButton((XdrvMailbox.payload & 0xFF) - 1, false); + } + } + break; + +#ifdef USE_DEVICE_GROUPS + case FUNC_DEVICE_GROUP_ITEM: + PWMDimmerHandleDevGroupItem(); + break; +#endif + + case FUNC_COMMAND: + result = DecodeCommand(kPWMDimmerCommands, PWMDimmerCommand); + break; + + case FUNC_SET_DEVICE_POWER: + + + if (XdrvMailbox.index) { + PWMDimmerSetPower(); + + + power_button_increases_bri = (light_state.getBri() < 128); + } + + + + else + result = true; + break; + + case FUNC_PRE_INIT: + PWMModulePreInit(); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" +#ifdef USE_KEELOQ +# 30 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" +#define XDRV_36 36 + +#include "cc1101.h" +#include + +#define SYNC_WORD 199 + +#define Lowpulse 400 +#define Highpulse 800 + +const char kJaroliftCommands[] PROGMEM = "Keeloq|" + "SendRaw|SendButton|Set"; + +void (* const jaroliftCommand[])(void) PROGMEM = { + &CmndSendRaw, &CmdSendButton, &CmdSet}; + +CC1101 cc1101; + +struct JAROLIFT_DEVICE { + int device_key_msb = 0x0; + int device_key_lsb = 0x0; + uint64_t button = 0x0; + int disc = 0x0100; + uint32_t enc = 0x0; + uint64_t pack = 0; + int count = 0; + uint32_t serial = 0x0; + uint8_t port_tx; + uint8_t port_rx; +} jaroliftDevice; + +void CmdSet(void) +{ + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload > 0) { + char *p; + uint32_t i = 0; + uint32_t param[4] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { + param[i] = strtoul(str, nullptr, 0); + i++; + } + for (uint32_t i = 0; i < 3; i++) { + if (param[i] < 1) { param[i] = 1; } + } + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("params: %08x %08x %08x %08x"), param[0], param[1], param[2], param[3]); + Settings.keeloq_master_msb = param[0]; + Settings.keeloq_master_lsb = param[1]; + Settings.keeloq_serial = param[2]; + Settings.keeloq_count = param[3]; + + jaroliftDevice.serial = param[2]; + jaroliftDevice.count = param[3]; + + GenerateDeviceCryptKey(); + ResponseCmndDone(); + } else { + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); + } + } else { + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no param")); + } +} + +void GenerateDeviceCryptKey() +{ + Keeloq k(Settings.keeloq_master_msb, Settings.keeloq_master_lsb); + jaroliftDevice.device_key_msb = k.decrypt(jaroliftDevice.serial | 0x60000000L); + jaroliftDevice.device_key_lsb = k.decrypt(jaroliftDevice.serial | 0x20000000L); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("generated device keys: %08x %08x"), jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); +} + +void CmdSendButton(void) +{ + noInterrupts(); + entertx(); + + if (XdrvMailbox.data_len > 0) + { + if (XdrvMailbox.payload > 0) + { + jaroliftDevice.button = strtoul(XdrvMailbox.data, nullptr, 0); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("msb: %08x"), jaroliftDevice.device_key_msb); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("lsb: %08x"), jaroliftDevice.device_key_lsb); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("serial: %08x"), jaroliftDevice.serial); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("disc: %08x"), jaroliftDevice.disc); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("KLQ: count: %08x"), jaroliftDevice.count); + + CreateKeeloqPacket(); + jaroliftDevice.count++; + Settings.keeloq_count = jaroliftDevice.count; + + for(int repeat = 0; repeat <= 1; repeat++) + { + uint64_t bitsToSend = jaroliftDevice.pack; + digitalWrite(jaroliftDevice.port_tx, LOW); + delayMicroseconds(1150); + SendSyncPreamble(13); + delayMicroseconds(3500); + for(int i=72; i>0; i--) + { + SendBit(bitsToSend & 0x0000000000000001); + bitsToSend >>= 1; + } + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); + + delay(16); + } + } + } + + interrupts(); + enterrx(); + + ResponseCmndDone(); +} + +void SendBit(byte bitToSend) +{ + if (bitToSend==1) + { + digitalWrite(jaroliftDevice.port_tx, LOW); + delayMicroseconds(Lowpulse); + digitalWrite(jaroliftDevice.port_tx, HIGH); + delayMicroseconds(Highpulse); + } + else + { + digitalWrite(jaroliftDevice.port_tx, LOW); + delayMicroseconds(Highpulse); + digitalWrite(jaroliftDevice.port_tx, HIGH); + delayMicroseconds(Lowpulse); + } +} + +void CmndSendRaw(void) +{ + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("cmd send called at %d"), micros()); + noInterrupts(); + entertx(); + for(int repeat = 0; repeat <= 1; repeat++) + { + if (XdrvMailbox.data_len > 0) + { + digitalWrite(jaroliftDevice.port_tx, LOW); + delayMicroseconds(1150); + SendSyncPreamble(13); + delayMicroseconds(3500); + + for(int i=XdrvMailbox.data_len-1; i>=0; i--) + { + SendBit(XdrvMailbox.data[i] == '1'); + } + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); + + delay(16); + } + interrupts(); + } + enterrx(); + ResponseCmndDone(); +} + +void enterrx() { + unsigned char marcState = 0; + cc1101.setRxState(); + delay(2); + unsigned long rx_time = micros(); + while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x0D ) + { + if (micros() - rx_time > 50000) break; + } +} + +void entertx() { + unsigned char marcState = 0; + cc1101.setTxState(); + delay(2); + unsigned long rx_time = micros(); + while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x13 && 0x14 && 0x15) + { + if (micros() - rx_time > 50000) break; + } +} + +void SendSyncPreamble(int l) +{ + for (int i = 0; i < l; ++i) + { + digitalWrite(jaroliftDevice.port_tx, LOW); + delayMicroseconds(400); + digitalWrite(jaroliftDevice.port_tx, HIGH); + delayMicroseconds(380); + } +} + +void CreateKeeloqPacket() +{ + Keeloq k(jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); + unsigned int result = (jaroliftDevice.disc << 16) | jaroliftDevice.count; + jaroliftDevice.pack = (uint64_t)0; + jaroliftDevice.pack |= jaroliftDevice.serial & 0xfffffffL; + jaroliftDevice.pack |= (jaroliftDevice.button & 0xfL) << 28; + jaroliftDevice.pack <<= 32; + + jaroliftDevice.enc = k.encrypt(result); + jaroliftDevice.pack |= jaroliftDevice.enc; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack high: %08x"), jaroliftDevice.pack>>32); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack low: %08x"), jaroliftDevice.pack); +} + +void KeeloqInit() +{ + jaroliftDevice.port_tx = Pin(GPIO_CC1101_GDO2); + jaroliftDevice.port_rx = Pin(GPIO_CC1101_GDO0); + + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("cc1101.init()")); + delay(100); + cc1101.init(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("CC1101 done.")); + cc1101.setSyncWord(SYNC_WORD, false); + cc1101.setCarrierFreq(CFREQ_433); + cc1101.disableAddressCheck(); + + pinMode(jaroliftDevice.port_tx, OUTPUT); + pinMode(jaroliftDevice.port_rx, INPUT_PULLUP); + + jaroliftDevice.serial = Settings.keeloq_serial; + jaroliftDevice.count = Settings.keeloq_count; + GenerateDeviceCryptKey(); +} + + + + +bool Xdrv36(uint8_t function) +{ + if (!PinUsed(GPIO_CC1101_GDO0) || !PinUsed(GPIO_CC1101_GDO2)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_COMMAND: + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("calling command")); + result = DecodeCommand(kJaroliftCommands, jaroliftCommand); + break; + case FUNC_INIT: + KeeloqInit(); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("init done.")); + break; + } + + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" +#ifdef USE_LIGHT +#ifdef USE_SONOFF_D1 +# 35 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" +#define XDRV_37 37 + +struct SONOFFD1 { + uint8_t receive_len = 0; + uint8_t power = 255; + uint8_t dimmer = 255; +} SnfD1; + + + +void SonoffD1Received(void) +{ + if (serial_in_byte_counter < 8) { return; } + + uint8_t action = serial_in_buffer[6] & 1; + if (action != SnfD1.power) { + SnfD1.power = action; + + + + ExecuteCommandPower(1, action, SRC_SWITCH); + } + + uint8_t dimmer = serial_in_buffer[7]; + if (dimmer != SnfD1.dimmer) { + SnfD1.dimmer = dimmer; + + + + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), SnfD1.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } +# 79 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" +} + +bool SonoffD1SerialInput(void) +{ + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + SnfD1.receive_len = 7; + } + if (SnfD1.receive_len) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (6 == serial_in_byte_counter) { + SnfD1.receive_len += serial_in_byte; + } + if (serial_in_byte_counter == SnfD1.receive_len) { +# 102 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < SnfD1.receive_len -1; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[SnfD1.receive_len -1]) { + SonoffD1Received(); + SnfD1.receive_len = 0; + return true; + } + } + serial_in_byte = 0; + } + return false; +} + + + +void SonoffD1Send() +{ + + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + + buffer[6] = SnfD1.power; + buffer[7] = SnfD1.dimmer; + + for (uint32_t i = 0; i < sizeof(buffer); i++) { + if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } + Serial.write(buffer[i]); + } +} + +bool SonoffD1SendPower(void) +{ + uint8_t action = XdrvMailbox.index &1; + if (action != SnfD1.power) { + SnfD1.power = action; + + + + SonoffD1Send(); + } + return true; +} + +bool SonoffD1SendDimmer(void) +{ + uint8_t dimmer = LightGetDimmer(1); + dimmer = (dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : dimmer; + dimmer = (dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : dimmer; + if (dimmer != SnfD1.dimmer) { + SnfD1.dimmer = dimmer; + + + + SonoffD1Send(); + } + return true; +} + +bool SonoffD1ModuleSelected(void) +{ + SetSerial(9600, TS_SERIAL_8N1); + + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + + + + + +bool Xdrv37(uint8_t function) +{ + bool result = false; + + if (SONOFF_D1 == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffD1SerialInput(); + break; + case FUNC_SET_DEVICE_POWER: + result = SonoffD1SendPower(); + break; + case FUNC_SET_CHANNELS: + result = SonoffD1SendDimmer(); + break; + case FUNC_MODULE_INIT: + result = SonoffD1ModuleSelected(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" +#ifdef USE_PING + +#define XDRV_38 38 + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/raw.h" +#include "lwip/timeouts.h" + +const char kPingCommands[] PROGMEM = "|" + D_CMND_PING + ; + +void (* const PingCommand[])(void) PROGMEM = { + &CmndPing, + }; + +extern "C" { + + extern uint32 system_relative_time(uint32 time); + extern void ets_bzero(void *s, size_t n); + + const uint16_t Ping_ID = 0xAFAF; + const size_t Ping_data_size = 32; + const uint32_t Ping_timeout_ms = 1000; + const uint32_t Ping_coarse = 1000; + + typedef struct Ping_t { + uint32 ip; + Ping_t *next; + uint16_t seq_num; + uint16_t seqno; + uint8_t success_count; + uint8_t timeout_count; + uint8_t to_send_count; + uint32_t ping_time_sent; + uint32_t min_time; + uint32_t max_time; + uint32_t sum_time; + bool done; + bool fast; + String hostname; + } Ping_t; + + + Ping_t *ping_head = nullptr; + struct raw_pcb *t_ping_pcb = nullptr; + + + + + + + + Ping_t ICACHE_FLASH_ATTR * t_ping_find(uint32_t ip) { + Ping_t *ping = ping_head; + while (ping != nullptr) { + if (ping->ip == ip) { + return ping; + } + ping = ping->next; + } + return nullptr; + } +# 92 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" + void ICACHE_FLASH_ATTR t_ping_timeout(void* arg) { + Ping_t *ping = (Ping_t*) arg; + ping->timeout_count++; + } + + + + + + + void ICACHE_FLASH_ATTR t_ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len, Ping_t *ping) { + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = Ping_ID; + ping->seq_num++; + if (ping->seq_num == 0x7fff) { ping->seq_num = 0; } + + iecho->seqno = htons(ping->seq_num); + + + for (uint32_t i = 0; i < data_len; i++) { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, len); + } + + + + void ICACHE_FLASH_ATTR t_ping_send(struct raw_pcb *raw, Ping_t *ping) { + struct pbuf *p; + uint16_t ping_size = sizeof(struct icmp_echo_hdr) + Ping_data_size; + + ping->ping_time_sent = system_get_time(); + p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM); + if (!p) { return; } + if ((p->len == p->tot_len) && (p->next == nullptr)) { + ip_addr_t ping_target; + struct icmp_echo_hdr *iecho; + + ping_target.addr = ping->ip; + iecho = (struct icmp_echo_hdr *) p->payload; + + t_ping_prepare_echo(iecho, ping_size, ping); + raw_sendto(raw, p, &ping_target); + } + pbuf_free(p); + } + + + + + + static void ICACHE_FLASH_ATTR t_ping_coarse_tmr(void *arg) { + Ping_t *ping = (Ping_t*) arg; + if (ping->to_send_count > 0) { + ping->to_send_count--; + + t_ping_send(t_ping_pcb, ping); + + sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); + sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); + } else { + sys_untimeout(t_ping_coarse_tmr, ping); + ping->done = true; + } + } + + + + + + + + static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) { + Ping_t *ping = t_ping_find(addr->addr); + + if (nullptr == ping) { + return 0; + } + + if (pbuf_header( p, -PBUF_IP_HLEN)==0) { + struct icmp_echo_hdr *iecho; + iecho = (struct icmp_echo_hdr *)p->payload; + + if ((iecho->id == Ping_ID) && (iecho->seqno == htons(ping->seq_num)) && iecho->type == ICMP_ER) { + + if (iecho->seqno != ping->seqno){ + + sys_untimeout(t_ping_timeout, ping); + uint32_t delay = system_relative_time(ping->ping_time_sent); + delay /= 1000; + + ping->sum_time += delay; + if (delay < ping->min_time) { ping->min_time = delay; } + if (delay > ping->max_time) { ping->max_time = delay; } + + ping->success_count++; + ping->seqno = iecho->seqno; + if (ping->fast) { + sys_untimeout(t_ping_coarse_tmr, ping); + ping->done = true; + ping->to_send_count = 0; + } + } + + pbuf_free(p); + return 1; + } + } + + return 0; + } + + + + + + void t_ping_register_pcb(void) { + if (nullptr == t_ping_pcb) { + t_ping_pcb = raw_new(IP_PROTO_ICMP); + + raw_recv(t_ping_pcb, t_ping_recv, nullptr); + raw_bind(t_ping_pcb, IP_ADDR_ANY); + } + } + + + void t_ping_deregister_pcb(void) { + if (nullptr == ping_head) { + raw_remove(t_ping_pcb); + t_ping_pcb = nullptr; + } + } +# 237 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" + int32_t t_ping_start(const char *hostname, uint32_t count) { + IPAddress ipfull; + if (!WiFi.hostByName(hostname, ipfull)) { + return -2; + } + + uint32_t ip = ipfull; + if (0xFFFFFFFF == ip) { return -2; } + + + if (t_ping_find(ip)) { + return -1; + } + + Ping_t *ping = new Ping_t(); + if (0 == count) { + count = 4; + ping->fast = true; + } + ping->min_time = UINT32_MAX; + ping->ip = ip; + ping->to_send_count = count - 1; + ping->hostname = hostname; + + + ping->next = ping_head; + ping_head = ping; + + t_ping_register_pcb(); + t_ping_send(t_ping_pcb, ping); + + + sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); + sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); + + return 0; + } + +} + + +void PingResponsePoll(void) { + Ping_t *ping = ping_head; + Ping_t **prev_link = &ping_head; + + while (ping != nullptr) { + if (ping->done) { + uint32_t success = ping->success_count; + uint32_t ip = ping->ip; + + Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" + "\"Reachable\":%s" + ",\"IP\":\"%d.%d.%d.%d\"" + ",\"Success\":%d" + ",\"Timeout\":%d" + ",\"MinTime\":%d" + ",\"MaxTime\":%d" + ",\"AvgTime\":%d" + "}}}"), + ping->hostname.c_str(), + success ? "true" : "false", + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, + success, + ping->timeout_count, + success ? ping->min_time : 0, + ping->max_time, + success ? ping->sum_time / success : 0 + ); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); + + + *prev_link = ping->next; + + Ping_t *ping_to_delete = ping; + ping = ping->next; + delete ping_to_delete; + } else { + prev_link = &ping->next; + ping = ping->next; + } + } +} + + + + + +void CmndPing(void) { + uint32_t count = XdrvMailbox.index; + + RemoveSpace(XdrvMailbox.data); + if (count > 10) { count = 8; } + + int32_t res = t_ping_start(XdrvMailbox.data, count); + if (0 == res) { + ResponseCmndDone(); + } else if (-1 == res) { + ResponseCmndChar_P(PSTR("Ping already ongoing for this IP")); + } else { + Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" + "\"Reachable\":false" + ",\"IP\":\"\"" + ",\"Success\":false" + "}}}"), + XdrvMailbox.data + ); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); + ResponseCmndChar_P(PSTR("Unable to resolve IP address")); + } +} + + + + + + +bool Xdrv38(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + PingResponsePoll(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kPingCommands, PingCommand); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" +#ifdef USE_THERMOSTAT + +#define XDRV_39 39 +# 31 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" +#ifdef DEBUG_THERMOSTAT +#define DOMOTICZ_MAX_IDX 4 +#define DOMOTICZ_IDX1 791 +#define DOMOTICZ_IDX2 792 +#define DOMOTICZ_IDX3 799 +#define DOMOTICZ_IDX4 800 +#define DOMOTICZ_IDX5 801 +#endif + + +#define D_CMND_THERMOSTATMODESET "ThermostatModeSet" +#define D_CMND_CLIMATEMODESET "ClimateModeSet" +#define D_CMND_TEMPFROSTPROTECTSET "TempFrostProtectSet" +#define D_CMND_CONTROLLERMODESET "ControllerModeSet" +#define D_CMND_INPUTSWITCHSET "InputSwitchSet" +#define D_CMND_INPUTSWITCHUSE "InputSwitchUse" +#define D_CMND_OUTPUTRELAYSET "OutputRelaySet" +#define D_CMND_TIMEALLOWRAMPUPSET "TimeAllowRampupSet" +#define D_CMND_TEMPFORMATSET "TempFormatSet" +#define D_CMND_TEMPMEASUREDSET "TempMeasuredSet" +#define D_CMND_TEMPTARGETSET "TempTargetSet" +#define D_CMND_TEMPMEASUREDGRDREAD "TempMeasuredGrdRead" +#define D_CMND_TEMPSENSNUMBERSET "TempSensNumberSet" +#define D_CMND_SENSORINPUTSET "SensorInputSet" +#define D_CMND_STATEEMERGENCYSET "StateEmergencySet" +#define D_CMND_TIMEMANUALTOAUTOSET "TimeManualToAutoSet" +#define D_CMND_TIMEONLIMITSET "TimeOnLimitSet" +#define D_CMND_PROPBANDSET "PropBandSet" +#define D_CMND_TIMERESETSET "TimeResetSet" +#define D_CMND_TIMEPICYCLESET "TimePiCycleSet" +#define D_CMND_TEMPANTIWINDUPRESETSET "TempAntiWindupResetSet" +#define D_CMND_TEMPHYSTSET "TempHystSet" +#ifdef USE_PI_AUTOTUNING +#define D_CMND_PERFLEVELAUTOTUNE "PerfLevelAutotune" +#endif +#define D_CMND_TIMEMAXACTIONSET "TimeMaxActionSet" +#define D_CMND_TIMEMINACTIONSET "TimeMinActionSet" +#define D_CMND_TIMEMINTURNOFFACTIONSET "TimeMinTurnoffActionSet" +#define D_CMND_TEMPRUPDELTINSET "TempRupDeltInSet" +#define D_CMND_TEMPRUPDELTOUTSET "TempRupDeltOutSet" +#define D_CMND_TIMERAMPUPMAXSET "TimeRampupMaxSet" +#define D_CMND_TIMERAMPUPCYCLESET "TimeRampupCycleSet" +#define D_CMND_TEMPRAMPUPPIACCERRSET "TempRampupPiAccErrSet" +#define D_CMND_TIMEPIPROPORTREAD "TimePiProportRead" +#define D_CMND_TIMEPIINTEGRREAD "TimePiIntegrRead" +#define D_CMND_TIMESENSLOSTSET "TimeSensLostSet" +#define D_CMND_DIAGNOSTICMODESET "DiagnosticModeSet" +#define D_CMND_CTRDUTYCYCLEREAD "CtrDutyCycleRead" +#define D_CMND_ENABLEOUTPUTSET "EnableOutputSet" + +enum ThermostatModes { THERMOSTAT_OFF, THERMOSTAT_AUTOMATIC_OP, THERMOSTAT_MANUAL_OP, THERMOSTAT_MODES_MAX }; +#ifdef USE_PI_AUTOTUNING +enum ControllerModes { CTR_HYBRID, CTR_PI, CTR_RAMP_UP, CTR_PI_AUTOTUNE, CTR_MODES_MAX }; +enum ControllerHybridPhases { CTR_HYBRID_RAMP_UP, CTR_HYBRID_PI, CTR_HYBRID_PI_AUTOTUNE }; +enum AutotuneStates { AUTOTUNE_OFF, AUTOTUNE_ON, AUTOTUNE_MAX }; +enum AutotunePerformanceParam { AUTOTUNE_PERF_FAST, AUTOTUNE_PERF_NORMAL, AUTOTUNE_PERF_SLOW, AUTOTUNE_PERF_MAX }; +#else +enum ControllerModes { CTR_HYBRID, CTR_PI, CTR_RAMP_UP, CTR_MODES_MAX }; +enum ControllerHybridPhases { CTR_HYBRID_RAMP_UP, CTR_HYBRID_PI }; +#endif +enum ClimateModes { CLIMATE_HEATING, CLIMATE_COOLING, CLIMATE_MODES_MAX }; +enum InterfaceStates { IFACE_OFF, IFACE_ON }; +enum InputUsage { INPUT_NOT_USED, INPUT_USED }; +enum CtrCycleStates { CYCLE_OFF, CYCLE_ON }; +enum EmergencyStates { EMERGENCY_OFF, EMERGENCY_ON }; +enum SensorType { SENSOR_MQTT, SENSOR_LOCAL, SENSOR_MAX }; +enum TempFormat { TEMP_CELSIUS, TEMP_FAHRENHEIT }; +enum TempConvType { TEMP_CONV_ABSOLUTE, TEMP_CONV_RELATIVE }; +enum DiagnosticModes { DIAGNOSTIC_OFF, DIAGNOSTIC_ON }; +enum ThermostatSupportedInputSwitches { + THERMOSTAT_INPUT_NONE, + THERMOSTAT_INPUT_SWT1 = 1, + THERMOSTAT_INPUT_SWT2, + THERMOSTAT_INPUT_SWT3, + THERMOSTAT_INPUT_SWT4, + THERMOSTAT_INPUT_SWT5, + THERMOSTAT_INPUT_SWT6, + THERMOSTAT_INPUT_SWT7, + THERMOSTAT_INPUT_SWT8 +}; +enum ThermostatSupportedOutputRelays { + THERMOSTAT_OUTPUT_NONE, + THERMOSTAT_OUTPUT_REL1 = 1, + THERMOSTAT_OUTPUT_REL2, + THERMOSTAT_OUTPUT_REL3, + THERMOSTAT_OUTPUT_REL4, + THERMOSTAT_OUTPUT_REL5, + THERMOSTAT_OUTPUT_REL6, + THERMOSTAT_OUTPUT_REL7, + THERMOSTAT_OUTPUT_REL8 +}; + +typedef union { + uint32_t data; + struct { + uint32_t thermostat_mode : 2; + uint32_t controller_mode : 2; + uint32_t climate_mode : 1; + uint32_t sensor_alive : 1; + uint32_t sensor_type : 1; + uint32_t temp_format : 1; + uint32_t command_output : 1; + uint32_t status_output : 1; + uint32_t status_input : 1; + uint32_t use_input : 1; + uint32_t phase_hybrid_ctr : 2; + uint32_t status_cycle_active : 1; + uint32_t counter_seconds : 6; + uint32_t output_relay_number : 4; + uint32_t input_switch_number : 3; + uint32_t enable_output : 1; +#ifdef USE_PI_AUTOTUNING + uint32_t autotune_flag : 1; + uint32_t autotune_perf_mode : 2; +#else + uint32_t free : 3; +#endif + }; +} ThermostatStateBitfield; + +typedef union { + uint8_t data; + struct { + uint8_t state_emergency : 1; + uint8_t diagnostic_mode : 1; + uint8_t output_inconsist_ctr : 2; + }; +} ThermostatDiagBitfield; + +#ifdef DEBUG_THERMOSTAT +const char DOMOTICZ_MES[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\"}"; +uint16_t Domoticz_Virtual_Switches[DOMOTICZ_MAX_IDX] = { DOMOTICZ_IDX1, DOMOTICZ_IDX3, DOMOTICZ_IDX4, DOMOTICZ_IDX5 }; +#endif + +const char kThermostatCommands[] PROGMEM = "|" D_CMND_THERMOSTATMODESET "|" D_CMND_CLIMATEMODESET "|" + D_CMND_TEMPFROSTPROTECTSET "|" D_CMND_CONTROLLERMODESET "|" D_CMND_INPUTSWITCHSET "|" D_CMND_INPUTSWITCHUSE "|" + D_CMND_OUTPUTRELAYSET "|" D_CMND_TIMEALLOWRAMPUPSET "|" D_CMND_TEMPFORMATSET "|" D_CMND_TEMPMEASUREDSET "|" + D_CMND_TEMPTARGETSET "|" D_CMND_TEMPMEASUREDGRDREAD "|" D_CMND_SENSORINPUTSET "|" D_CMND_STATEEMERGENCYSET "|" + D_CMND_TIMEMANUALTOAUTOSET "|" D_CMND_PROPBANDSET "|" D_CMND_TIMERESETSET "|" D_CMND_TIMEPICYCLESET "|" +#ifdef USE_PI_AUTOTUNING + D_CMND_TEMPANTIWINDUPRESETSET "|" D_CMND_TEMPHYSTSET "|" D_CMND_PERFLEVELAUTOTUNE "|" D_CMND_TIMEMAXACTIONSET "|" +#else + D_CMND_TEMPANTIWINDUPRESETSET "|" D_CMND_TEMPHYSTSET "|" D_CMND_TIMEMAXACTIONSET "|" +#endif + D_CMND_TIMEMINACTIONSET "|" D_CMND_TIMEMINTURNOFFACTIONSET "|" D_CMND_TEMPRUPDELTINSET "|" D_CMND_TEMPRUPDELTOUTSET "|" + D_CMND_TIMERAMPUPMAXSET "|" D_CMND_TIMERAMPUPCYCLESET "|" D_CMND_TEMPRAMPUPPIACCERRSET "|" D_CMND_TIMEPIPROPORTREAD "|" + D_CMND_TIMEPIINTEGRREAD "|" D_CMND_TIMESENSLOSTSET "|" D_CMND_DIAGNOSTICMODESET "|" D_CMND_CTRDUTYCYCLEREAD "|" + D_CMND_ENABLEOUTPUTSET; + +void (* const ThermostatCommand[])(void) PROGMEM = { + &CmndThermostatModeSet, &CmndClimateModeSet, &CmndTempFrostProtectSet, &CmndControllerModeSet, &CmndInputSwitchSet, + &CmndInputSwitchUse, &CmndOutputRelaySet, &CmndTimeAllowRampupSet, &CmndTempFormatSet, &CmndTempMeasuredSet, + &CmndTempTargetSet, &CmndTempMeasuredGrdRead, &CmndSensorInputSet, &CmndStateEmergencySet, &CmndTimeManualToAutoSet, + &CmndPropBandSet, &CmndTimeResetSet, &CmndTimePiCycleSet, &CmndTempAntiWindupResetSet, &CmndTempHystSet, +#ifdef USE_PI_AUTOTUNING + &CmndPerfLevelAutotune, &CmndTimeMaxActionSet, &CmndTimeMinActionSet, &CmndTimeMinTurnoffActionSet, &CmndTempRupDeltInSet, +#else + &CmndTimeMaxActionSet, &CmndTimeMinActionSet, &CmndTimeMinTurnoffActionSet, &CmndTempRupDeltInSet, +#endif + &CmndTempRupDeltOutSet, &CmndTimeRampupMaxSet, &CmndTimeRampupCycleSet, &CmndTempRampupPiAccErrSet, + &CmndTimePiProportRead, &CmndTimePiIntegrRead, &CmndTimeSensLostSet, &CmndDiagnosticModeSet, &CmndCtrDutyCycleRead, + &CmndEnableOutputSet }; + +struct THERMOSTAT { + ThermostatStateBitfield status; + uint32_t timestamp_temp_measured_update = 0; + uint32_t timestamp_temp_meas_change_update = 0; + uint32_t timestamp_output_off = 0; + uint32_t timestamp_input_on = 0; + uint32_t time_thermostat_total = 0; + uint32_t time_ctr_checkpoint = 0; + uint32_t time_ctr_changepoint = 0; + int32_t temp_measured_gradient = 0; + int16_t temp_target_level = THERMOSTAT_TEMP_INIT; + int16_t temp_target_level_ctr = THERMOSTAT_TEMP_INIT; + int16_t temp_pi_accum_error = 0; + int16_t temp_pi_error = 0; + int32_t time_proportional_pi; + int32_t time_integral_pi; + int32_t time_total_pi; + uint16_t kP_pi = 0; + uint16_t kI_pi = 0; + int32_t temp_rampup_meas_gradient = 0; + uint32_t timestamp_rampup_start = 0; + uint32_t time_rampup_deadtime = 0; + uint32_t time_rampup_nextcycle = 0; + int16_t temp_measured = 0; + int16_t temp_rampup_output_off = 0; + uint8_t time_output_delay = THERMOSTAT_TIME_OUTPUT_DELAY; + uint8_t counter_rampup_cycles = 0; + uint8_t temp_rampup_pi_acc_error = THERMOSTAT_TEMP_PI_RAMPUP_ACC_E; + uint8_t temp_rampup_delta_out = THERMOSTAT_TEMP_RAMPUP_DELTA_OUT; + uint8_t temp_rampup_delta_in = THERMOSTAT_TEMP_RAMPUP_DELTA_IN; + uint8_t val_prop_band = THERMOSTAT_PROP_BAND; + int16_t temp_rampup_start = 0; + int16_t temp_rampup_cycle = 0; + uint16_t time_rampup_max = THERMOSTAT_TIME_RAMPUP_MAX; + uint16_t time_rampup_cycle = THERMOSTAT_TIME_RAMPUP_CYCLE; + uint16_t time_allow_rampup = THERMOSTAT_TIME_ALLOW_RAMPUP; + uint16_t time_sens_lost = THERMOSTAT_TIME_SENS_LOST; + uint16_t time_manual_to_auto = THERMOSTAT_TIME_MANUAL_TO_AUTO; + uint32_t time_reset = THERMOSTAT_TIME_RESET; + uint16_t time_pi_cycle = THERMOSTAT_TIME_PI_CYCLE; + uint16_t time_max_action = THERMOSTAT_TIME_MAX_ACTION; + uint16_t time_min_action = THERMOSTAT_TIME_MIN_ACTION; + uint16_t time_min_turnoff_action = THERMOSTAT_TIME_MIN_TURNOFF_ACTION; + uint8_t temp_reset_anti_windup = THERMOSTAT_TEMP_RESET_ANTI_WINDUP; + int8_t temp_hysteresis = THERMOSTAT_TEMP_HYSTERESIS; + uint8_t temp_frost_protect = THERMOSTAT_TEMP_FROST_PROTECT; + ThermostatDiagBitfield diag; +#ifdef USE_PI_AUTOTUNING + uint8_t dutycycle_step_autotune = THERMOSTAT_DUTYCYCLE_AUTOTUNE; + uint8_t peak_ctr = 0; + uint8_t temp_band_no_peak_det = THERMOSTAT_TEMP_BAND_NO_PEAK_DET; + uint8_t val_prop_band_atune = 0; + uint32_t time_reset_atune = 0; + uint16_t pU_pi_atune = 0; + uint16_t kU_pi_atune = 0; + uint16_t kP_pi_atune = 0; + uint16_t kI_pi_atune = 0; + int16_t temp_peaks_atune[THERMOSTAT_PEAKNUMBER_AUTOTUNE]; + int16_t temp_abs_max_atune; + int16_t temp_abs_min_atune; + uint16_t time_peak_timestamps_atune[THERMOSTAT_PEAKNUMBER_AUTOTUNE]; + uint16_t time_std_dev_peak_det_ok = THERMOSTAT_TIME_STD_DEV_PEAK_DET_OK; +#endif +} Thermostat[THERMOSTAT_CONTROLLER_OUTPUTS]; + + + +void ThermostatInit(uint8_t ctr_output) +{ + + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; + Thermostat[ctr_output].status.controller_mode = CTR_HYBRID; + Thermostat[ctr_output].status.climate_mode = CLIMATE_HEATING; + Thermostat[ctr_output].status.sensor_alive = IFACE_OFF; + Thermostat[ctr_output].status.sensor_type = SENSOR_MQTT; + Thermostat[ctr_output].status.temp_format = TEMP_CELSIUS; + Thermostat[ctr_output].status.command_output = IFACE_OFF; + Thermostat[ctr_output].status.status_output = IFACE_OFF; + Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; + Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; + Thermostat[ctr_output].diag.state_emergency = EMERGENCY_OFF; + Thermostat[ctr_output].status.counter_seconds = 0; + Thermostat[ctr_output].status.output_relay_number = (THERMOSTAT_RELAY_NUMBER + ctr_output); + Thermostat[ctr_output].status.input_switch_number = (THERMOSTAT_SWITCH_NUMBER + ctr_output); + Thermostat[ctr_output].status.use_input = INPUT_NOT_USED; + Thermostat[ctr_output].status.enable_output = IFACE_ON; + Thermostat[ctr_output].diag.output_inconsist_ctr = 0; + Thermostat[ctr_output].diag.diagnostic_mode = DIAGNOSTIC_ON; +#ifdef USE_PI_AUTOTUNING + Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; + Thermostat[ctr_output].status.autotune_perf_mode = AUTOTUNE_PERF_FAST; +#endif + + if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { + ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT); + } +} + +bool ThermostatMinuteCounter(uint8_t ctr_output) +{ + bool result = false; + Thermostat[ctr_output].status.counter_seconds++; + + if ((Thermostat[ctr_output].status.counter_seconds % 60) == 0) { + result = true; + Thermostat[ctr_output].status.counter_seconds = 0; + } + return result; +} + +inline bool ThermostatSwitchIdValid(uint8_t switchId) +{ + return (switchId >= THERMOSTAT_INPUT_SWT1 && switchId <= THERMOSTAT_INPUT_SWT8); +} + +inline bool ThermostatRelayIdValid(uint8_t relayId) +{ + return (relayId >= THERMOSTAT_OUTPUT_REL1 && relayId <= THERMOSTAT_OUTPUT_REL8); +} + +uint8_t ThermostatInputStatus(uint8_t input_switch) +{ + bool ifId = ThermostatSwitchIdValid(input_switch); + uint8_t value = 0; + if(ifId) { + value = SwitchGetVirtual(ifId - THERMOSTAT_INPUT_SWT1); + } + return value; +} + +uint8_t ThermostatOutputStatus(uint8_t output_switch) +{ + return (uint8_t)bitRead(power, (output_switch - 1)); +} + +int16_t ThermostatCelsiusToFahrenheit(const int32_t deg, uint8_t conv_type) { + int32_t value; + value = (int32_t)(((int32_t)deg * (int32_t)90) / (int32_t)50); + if (conv_type == TEMP_CONV_ABSOLUTE) { + value += (int32_t)320; + } + + + if (value <= (int32_t)(INT16_MIN)) { + value = (int32_t)(INT16_MIN); + } + else if (value >= (int32_t)INT16_MAX) { + value = (int32_t)INT16_MAX; + } + + return (int16_t)value; +} + +int16_t ThermostatFahrenheitToCelsius(const int32_t deg, uint8_t conv_type) { + int16_t offset = 0; + int32_t value; + if (conv_type == TEMP_CONV_ABSOLUTE) { + offset = 320; + } + + value = (int32_t)(((deg - (int32_t)offset) * (int32_t)50) / (int32_t)90); + + + if (value <= (int32_t)(INT16_MIN)) { + value = (int32_t)(INT16_MIN); + } + else if (value >= (int32_t)INT16_MAX) { + value = (int32_t)INT16_MAX; + } + + return (int16_t)value; +} + +void ThermostatSignalPreProcessingSlow(uint8_t ctr_output) +{ + + if ((uptime - Thermostat[ctr_output].timestamp_temp_measured_update) > ((uint32_t)Thermostat[ctr_output].time_sens_lost * 60)) { + Thermostat[ctr_output].status.sensor_alive = IFACE_OFF; + Thermostat[ctr_output].temp_measured_gradient = 0; + Thermostat[ctr_output].temp_measured = 0; + } +} + +void ThermostatSignalPostProcessingSlow(uint8_t ctr_output) +{ + + if ((Thermostat[ctr_output].status.status_output != Thermostat[ctr_output].status.command_output) + &&(Thermostat[ctr_output].status.enable_output == IFACE_ON)) { + Thermostat[ctr_output].diag.output_inconsist_ctr++; + } + else { + Thermostat[ctr_output].diag.output_inconsist_ctr = 0; + } +} + +void ThermostatSignalProcessingFast(uint8_t ctr_output) +{ + + Thermostat[ctr_output].status.status_input = (uint32_t)ThermostatInputStatus(Thermostat[ctr_output].status.input_switch_number); + + if (Thermostat[ctr_output].status.status_input == IFACE_ON) { + Thermostat[ctr_output].timestamp_input_on = uptime; + } + + Thermostat[ctr_output].status.status_output = (uint32_t)ThermostatOutputStatus(Thermostat[ctr_output].status.output_relay_number); +} + +void ThermostatCtrState(uint8_t ctr_output) +{ +#ifdef USE_PI_AUTOTUNING + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); +#endif + + switch (Thermostat[ctr_output].status.controller_mode) { + + case CTR_HYBRID: + ThermostatHybridCtrPhase(ctr_output); + break; + + case CTR_PI: +#ifdef USE_PI_AUTOTUNING + + + + + if ((Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_ON) + &&(Thermostat[ctr_output].temp_measured == Thermostat[ctr_output].temp_target_level) + && ((flag_heating && (Thermostat[ctr_output].temp_measured_gradient < 0)) + ||(!flag_heating && (Thermostat[ctr_output].temp_measured_gradient > 0)))) + { + Thermostat[ctr_output].status.controller_mode = CTR_PI_AUTOTUNE; + ThermostatPeakDetectorInit(ctr_output); + } +#endif + break; + + case CTR_RAMP_UP: + break; +#ifdef USE_PI_AUTOTUNING + + case CTR_PI_AUTOTUNE: + + + if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) + { + Thermostat[ctr_output].status.controller_mode = CTR_PI; + } + break; +#endif + } +} + +void ThermostatHybridCtrPhase(uint8_t ctr_output) +{ + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + if (Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) { + switch (Thermostat[ctr_output].status.phase_hybrid_ctr) { + + case CTR_HYBRID_RAMP_UP: + + + if((Thermostat[ctr_output].time_ctr_checkpoint != 0) + && (uptime >= Thermostat[ctr_output].time_ctr_checkpoint)) { + + Thermostat[ctr_output].time_ctr_checkpoint = 0; + + Thermostat[ctr_output].time_ctr_changepoint = 0; + + Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; + } + break; + + case CTR_HYBRID_PI: + + + + + if (((uptime - Thermostat[ctr_output].timestamp_output_off) > (60 * (uint32_t)Thermostat[ctr_output].time_allow_rampup)) + && (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) + && ( ( (Thermostat[ctr_output].temp_target_level - Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_delta_in) + && (flag_heating)) + || ( (Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_target_level > Thermostat[ctr_output].temp_rampup_delta_in) + && (!flag_heating)))) { + Thermostat[ctr_output].timestamp_rampup_start = uptime; + Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; + Thermostat[ctr_output].temp_rampup_meas_gradient = 0; + Thermostat[ctr_output].time_rampup_deadtime = 0; + Thermostat[ctr_output].counter_rampup_cycles = 1; + Thermostat[ctr_output].time_ctr_changepoint = 0; + Thermostat[ctr_output].time_ctr_checkpoint = 0; + Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_RAMP_UP; + } +#ifdef USE_PI_AUTOTUNING + + + + + if ((Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_ON) + &&(Thermostat[ctr_output].temp_measured == Thermostat[ctr_output].temp_target_level) + && ((flag_heating && (Thermostat[ctr_output].temp_measured_gradient < 0)) + ||(!flag_heating && (Thermostat[ctr_output].temp_measured_gradient > 0)))) + { + Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI_AUTOTUNE; + ThermostatPeakDetectorInit(ctr_output); + } +#endif + break; +#ifdef USE_PI_AUTOTUNING + + case CTR_HYBRID_PI_AUTOTUNE: + + + if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) + { + Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; + } + break; +#endif + } + } +#ifdef DEBUG_THERMOSTAT + ThermostatVirtualSwitchCtrState(ctr_output); +#endif +} + +bool ThermostatStateAutoToManual(uint8_t ctr_output) +{ + bool change_state = false; + + + + + if ((Thermostat[ctr_output].status.use_input == INPUT_USED) + &&((Thermostat[ctr_output].status.status_input == IFACE_ON) + || (Thermostat[ctr_output].status.sensor_alive == IFACE_OFF))) { + change_state = true; + } + return change_state; +} + +bool ThermostatStateManualToAuto(uint8_t ctr_output) +{ + bool change_state = false; + + + + + + if ((Thermostat[ctr_output].status.status_input == IFACE_OFF) + &&(Thermostat[ctr_output].status.sensor_alive == IFACE_ON) + && ((uptime - Thermostat[ctr_output].timestamp_input_on) > ((uint32_t)Thermostat[ctr_output].time_manual_to_auto * 60))) { + change_state = true; + } + return change_state; +} + +void ThermostatEmergencyShutdown(uint8_t ctr_output) +{ + + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; + Thermostat[ctr_output].status.command_output = IFACE_OFF; + if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { + ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output); + } +} + +void ThermostatState(uint8_t ctr_output) +{ + switch (Thermostat[ctr_output].status.thermostat_mode) { + + case THERMOSTAT_OFF: + + break; + + case THERMOSTAT_AUTOMATIC_OP: + if (ThermostatStateAutoToManual(ctr_output)) { + + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_MANUAL_OP; + } + ThermostatCtrState(ctr_output); + break; + + case THERMOSTAT_MANUAL_OP: + if (ThermostatStateManualToAuto(ctr_output)) { + + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_AUTOMATIC_OP; + } + break; + } +} + +void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command) +{ + + + + if ((command == IFACE_ON) + && (Thermostat[ctr_output].status.status_output == IFACE_OFF)) { + + if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { + ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_ON, SRC_THERMOSTAT); + } + + Thermostat[ctr_output].status.status_output = IFACE_ON; +#ifdef DEBUG_THERMOSTAT + ThermostatVirtualSwitch(ctr_output); +#endif + } + + + + else if ((command == IFACE_OFF) && (Thermostat[ctr_output].status.status_output == IFACE_ON)) { + + if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { + ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT); + } + + Thermostat[ctr_output].timestamp_output_off = uptime; + Thermostat[ctr_output].status.status_output = IFACE_OFF; +#ifdef DEBUG_THERMOSTAT + ThermostatVirtualSwitch(ctr_output); +#endif + } +} + +void ThermostatCalculatePI(uint8_t ctr_output) +{ + + + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + int32_t aux_temp_error; + + + aux_temp_error = (int32_t)(Thermostat[ctr_output].temp_target_level_ctr - Thermostat[ctr_output].temp_measured) * 10; + + + if (Thermostat[ctr_output].status.climate_mode == CLIMATE_COOLING) { + aux_temp_error *= -1; + } + + + if (aux_temp_error <= (int32_t)(INT16_MIN)) { + Thermostat[ctr_output].temp_pi_error = (int16_t)(INT16_MIN); + } + else if (aux_temp_error >= (int32_t)INT16_MAX) { + Thermostat[ctr_output].temp_pi_error = (int16_t)INT16_MAX; + } + else { + Thermostat[ctr_output].temp_pi_error = (int16_t)aux_temp_error; + } + + + Thermostat[ctr_output].kP_pi = 100 / (uint16_t)(Thermostat[ctr_output].val_prop_band); + + Thermostat[ctr_output].time_proportional_pi = ((int32_t)(Thermostat[ctr_output].temp_pi_error * (int16_t)Thermostat[ctr_output].kP_pi) * ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) / 10000; + + + + + + if ((Thermostat[ctr_output].time_proportional_pi < abs(((int32_t)Thermostat[ctr_output].time_min_action * 60))) + && (Thermostat[ctr_output].time_proportional_pi > 0)) { + Thermostat[ctr_output].time_proportional_pi = ((int32_t)Thermostat[ctr_output].time_min_action * 60); + } + + if (Thermostat[ctr_output].time_proportional_pi < 0) { + Thermostat[ctr_output].time_proportional_pi = 0; + } + else if (Thermostat[ctr_output].time_proportional_pi > ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { + Thermostat[ctr_output].time_proportional_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); + } + + + Thermostat[ctr_output].kI_pi = (uint16_t)((((uint32_t)Thermostat[ctr_output].kP_pi * (uint32_t)Thermostat[ctr_output].time_pi_cycle * 6000)) / (uint32_t)Thermostat[ctr_output].time_reset); + + + + + if (abs((Thermostat[ctr_output].temp_pi_error) / 10) > Thermostat[ctr_output].temp_reset_anti_windup) { + Thermostat[ctr_output].time_integral_pi = 0; + Thermostat[ctr_output].temp_pi_accum_error = 0; + } + + + + else { +# 688 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" + aux_temp_error = (int32_t)Thermostat[ctr_output].temp_pi_accum_error + (int32_t)Thermostat[ctr_output].temp_pi_error; + + + if (aux_temp_error <= (int32_t)INT16_MIN) { + Thermostat[ctr_output].temp_pi_accum_error = INT16_MIN; + } + else if (aux_temp_error >= (int32_t)INT16_MAX) { + Thermostat[ctr_output].temp_pi_accum_error = INT16_MAX; + } + else { + Thermostat[ctr_output].temp_pi_accum_error = (int16_t)aux_temp_error; + } + + + + + if ( (Thermostat[ctr_output].temp_pi_error >= 0) + && (abs((Thermostat[ctr_output].temp_pi_error) / 10) <= (int16_t)Thermostat[ctr_output].temp_hysteresis) + && ( ((Thermostat[ctr_output].temp_measured_gradient > 0) + && (flag_heating)) + || ( (Thermostat[ctr_output].temp_measured_gradient < 0) + && (!flag_heating)))) { + + Thermostat[ctr_output].temp_pi_accum_error *= 0.8; + } + + + else if ((Thermostat[ctr_output].temp_pi_error < 0) + && ( ((Thermostat[ctr_output].temp_measured_gradient > 0) + && (flag_heating)) + || ( (Thermostat[ctr_output].temp_measured_gradient < 0) + && (!flag_heating)))) { + + Thermostat[ctr_output].temp_pi_accum_error *= 0.8; + } + + + if (Thermostat[ctr_output].temp_pi_accum_error < 0) { + Thermostat[ctr_output].temp_pi_accum_error = 0; + } + + + Thermostat[ctr_output].time_integral_pi = (((int32_t)Thermostat[ctr_output].temp_pi_accum_error * (int32_t)Thermostat[ctr_output].kI_pi) * (int32_t)((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60)) / 1000000; + + + + + if (Thermostat[ctr_output].time_integral_pi > ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { + Thermostat[ctr_output].time_integral_pi = ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); + } + } + + + Thermostat[ctr_output].time_total_pi = Thermostat[ctr_output].time_proportional_pi + Thermostat[ctr_output].time_integral_pi; + + + + + if (Thermostat[ctr_output].time_total_pi >= ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { + + Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); + } + else if (Thermostat[ctr_output].time_total_pi < 0) { + Thermostat[ctr_output].time_total_pi = 0; + } + + + + if (Thermostat[ctr_output].temp_pi_error <= 0) { + + if ((abs((Thermostat[ctr_output].temp_pi_error) / 10) > Thermostat[ctr_output].temp_hysteresis) + || ( ((Thermostat[ctr_output].temp_measured_gradient >= 0) + && (flag_heating)) + || ( (Thermostat[ctr_output].temp_measured_gradient <= 0) + && (!flag_heating)))){ + Thermostat[ctr_output].time_total_pi = 0; + } + } + + + + + else if ((Thermostat[ctr_output].temp_pi_error > 0) + && (abs((Thermostat[ctr_output].temp_pi_error) / 10) <= Thermostat[ctr_output].temp_hysteresis) + && (((Thermostat[ctr_output].temp_measured_gradient > 0) + && (flag_heating)) + || ( (Thermostat[ctr_output].temp_measured_gradient < 0) + && (!flag_heating)))) { + Thermostat[ctr_output].time_total_pi = 0; + } + + + + if ((Thermostat[ctr_output].time_total_pi <= abs(((uint32_t)Thermostat[ctr_output].time_min_action * 60))) + && (Thermostat[ctr_output].time_total_pi != 0)) { + Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_min_action * 60); + } + + + else if (Thermostat[ctr_output].time_total_pi > abs(((int32_t)Thermostat[ctr_output].time_max_action * 60))) { + Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_max_action * 60); + } + + else if (Thermostat[ctr_output].time_total_pi > (((int32_t)Thermostat[ctr_output].time_pi_cycle * 60) - ((int32_t)Thermostat[ctr_output].time_min_turnoff_action * 60))) { + Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); + } + + + Thermostat[ctr_output].time_ctr_changepoint = uptime + (uint32_t)Thermostat[ctr_output].time_total_pi; + + Thermostat[ctr_output].time_ctr_checkpoint = uptime + ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); +} + +void ThermostatWorkAutomaticPI(uint8_t ctr_output) +{ + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + if ( (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) + || (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) + || ( (( (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level) + && (Thermostat[ctr_output].temp_measured_gradient < 0) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level) + && (Thermostat[ctr_output].temp_measured_gradient > 0) + && (!flag_heating))) + && (Thermostat[ctr_output].status.status_cycle_active == CYCLE_OFF))) { + Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; + ThermostatCalculatePI(ctr_output); + + Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; + } + if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { + Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; + Thermostat[ctr_output].status.command_output = IFACE_ON; + } + else { + Thermostat[ctr_output].status.command_output = IFACE_OFF; + } +} + +void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) +{ + uint32_t time_in_rampup; + int16_t aux_temp_delta; + int16_t temp_delta_rampup; + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + + + + if ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_rampup_start) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_start) + && (!flag_heating))) + { + Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; + } + + + time_in_rampup = uptime - Thermostat[ctr_output].timestamp_rampup_start; + temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_start; + + Thermostat[ctr_output].status.command_output = IFACE_ON; + + Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; + + + + if ((time_in_rampup <= (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max)) + && ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level) + && (!flag_heating)))){ + + + + if ( (abs(temp_delta_rampup) >= Thermostat[ctr_output].temp_rampup_delta_out) + && (Thermostat[ctr_output].time_rampup_deadtime == 0)) { + + + int32_t time_aux; + time_aux = ((time_in_rampup / 2) - Thermostat[ctr_output].time_output_delay); + if (time_aux >= Thermostat[ctr_output].time_output_delay) { + Thermostat[ctr_output].time_rampup_deadtime = (uint32_t)time_aux; + } + else { + Thermostat[ctr_output].time_rampup_deadtime = Thermostat[ctr_output].time_output_delay; + } + + Thermostat[ctr_output].temp_rampup_meas_gradient = (int32_t)((360000 * (int32_t)temp_delta_rampup) / (int32_t)time_in_rampup); + Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + + Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; + Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max); + Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; + } + + else if ((Thermostat[ctr_output].time_rampup_deadtime > 0) && (uptime >= Thermostat[ctr_output].time_rampup_nextcycle)) { + + + temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_cycle; + uint32_t time_total_rampup = (uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60 * Thermostat[ctr_output].counter_rampup_cycles; + + Thermostat[ctr_output].temp_rampup_meas_gradient = int32_t((360000 * (int32_t)temp_delta_rampup) / (int32_t)time_total_rampup); + if ( ((Thermostat[ctr_output].temp_rampup_meas_gradient > 0) + && ((flag_heating))) + || ((Thermostat[ctr_output].temp_rampup_meas_gradient < 0) + && ((!flag_heating)))) { + + + + + aux_temp_delta =Thermostat[ctr_output].temp_target_level_ctr - Thermostat[ctr_output].temp_rampup_cycle; + Thermostat[ctr_output].time_ctr_changepoint = (uint32_t)(uint32_t)(((uint32_t)(aux_temp_delta) * (uint32_t)(time_total_rampup)) / (uint32_t)temp_delta_rampup) + (uint32_t)Thermostat[ctr_output].time_rampup_nextcycle - (uint32_t)time_total_rampup - (uint32_t)Thermostat[ctr_output].time_rampup_deadtime; + + + + Thermostat[ctr_output].temp_rampup_output_off = (int16_t)(((int32_t)temp_delta_rampup * (int32_t)(Thermostat[ctr_output].time_ctr_changepoint - (uptime - (time_total_rampup)))) / (int32_t)(time_total_rampup * Thermostat[ctr_output].counter_rampup_cycles)) + Thermostat[ctr_output].temp_rampup_cycle; + + Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; + + Thermostat[ctr_output].counter_rampup_cycles = 1; + } + else { + + Thermostat[ctr_output].counter_rampup_cycles++; + + Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + + Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max) - time_in_rampup; + Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; + } + + Thermostat[ctr_output].time_ctr_checkpoint = Thermostat[ctr_output].time_ctr_changepoint + Thermostat[ctr_output].time_rampup_deadtime; + } + + + + + + + if ((Thermostat[ctr_output].time_rampup_deadtime == 0) + || (Thermostat[ctr_output].time_ctr_checkpoint == 0) + || (uptime < Thermostat[ctr_output].time_ctr_changepoint) + || ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_rampup_output_off) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_output_off) + && (!flag_heating))) + || ( ((Thermostat[ctr_output].temp_rampup_meas_gradient <= 0) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_rampup_meas_gradient >= 0) + && (!flag_heating)))) { + Thermostat[ctr_output].status.command_output = IFACE_ON; + } + else { + Thermostat[ctr_output].status.command_output = IFACE_OFF; + } + } + else { + + if ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level_ctr) + && (flag_heating)) + || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level_ctr) + && (!flag_heating))) { + Thermostat[ctr_output].temp_pi_accum_error = Thermostat[ctr_output].temp_rampup_pi_acc_error; + } + + Thermostat[ctr_output].time_ctr_checkpoint = uptime; + + Thermostat[ctr_output].status.command_output = IFACE_OFF; + } +} + +#ifdef USE_PI_AUTOTUNING + +void ThermostatPeakDetectorInit(uint8_t ctr_output) +{ + for (uint8_t i = 0; i < THERMOSTAT_PEAKNUMBER_AUTOTUNE; i++) { + Thermostat[ctr_output].temp_peaks_atune[i] = 0; + } + Thermostat[ctr_output].pU_pi_atune = 0; + Thermostat[ctr_output].kP_pi_atune = 0; + Thermostat[ctr_output].kI_pi_atune = 0; + Thermostat[ctr_output].kU_pi_atune = 0; + Thermostat[ctr_output].peak_ctr = 0; + Thermostat[ctr_output].temp_abs_max_atune = 0; + Thermostat[ctr_output].temp_abs_min_atune = 100; + Thermostat[ctr_output].time_ctr_checkpoint = uptime + THERMOSTAT_TIME_MAX_AUTOTUNE; +} + +void ThermostatPeakDetector(uint8_t ctr_output) +{ + uint8_t peak_num = Thermostat[ctr_output].peak_ctr; + int16_t peak_avg = 0; + bool peak_transition = false; + + if (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_abs_max_atune) { + Thermostat[ctr_output].temp_abs_max_atune = Thermostat[ctr_output].temp_measured; + } + if (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_abs_min_atune) { + Thermostat[ctr_output].temp_abs_min_atune = Thermostat[ctr_output].temp_measured; + } + + + if (peak_num < THERMOSTAT_PEAKNUMBER_AUTOTUNE) { + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + bool cond_peak_1 = ( (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_peaks_atune[peak_num]) + && (flag_heating) + || (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_peaks_atune[peak_num]) + && (!flag_heating)); + bool cond_peak_2 = ( (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_peaks_atune[peak_num]) + && (flag_heating) + || (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_peaks_atune[peak_num]) + && (!flag_heating)); + bool cond_gradient_1 = ( (Thermostat[ctr_output].temp_measured_gradient > 0) + && (flag_heating) + || (Thermostat[ctr_output].temp_measured_gradient < 0) + && (!flag_heating)); + bool cond_gradient_2 = ( (Thermostat[ctr_output].temp_measured_gradient < 0) + && (flag_heating) + || (Thermostat[ctr_output].temp_measured_gradient > 0) + && (!flag_heating)); + + if ((peak_num % 2) == 0) { + + + + if (cond_peak_1 && cond_gradient_1) { + Thermostat[ctr_output].temp_peaks_atune[peak_num] = Thermostat[ctr_output].temp_measured; + } + + + + if ( (cond_peak_2) + && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { + + Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); + Thermostat[ctr_output].peak_ctr++; + peak_transition = true; + } + } + + else { + + + + if (cond_peak_2 && cond_gradient_2) { + Thermostat[ctr_output].temp_peaks_atune[peak_num] = Thermostat[ctr_output].temp_measured; + } + + + + if ( (cond_peak_1) + && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { + + + Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); + Thermostat[ctr_output].peak_ctr++; + peak_transition = true; + } + } + } + else { + + ThermostatAutotuneParamCalc(ctr_output); + Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; + } + + + if ((Thermostat[ctr_output].peak_ctr > 2) && (peak_transition)) { + + peak_num = Thermostat[ctr_output].peak_ctr; + + peak_avg = (abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 1] + - Thermostat[ctr_output].temp_peaks_atune[peak_num - 2]) + + abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 2] + - Thermostat[ctr_output].temp_peaks_atune[peak_num - 3])) / 2; + + if ((20 * (int32_t)peak_avg) < (int32_t)(Thermostat[ctr_output].temp_abs_max_atune - Thermostat[ctr_output].temp_abs_min_atune)) { + + for (uint8_t i = 0; i < peak_num; i++) { + peak_avg += Thermostat[ctr_output].temp_peaks_atune[i]; + } + peak_avg /= peak_num; + + if (10 * abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 1] - Thermostat[ctr_output].temp_peaks_atune[peak_num - 2]) < (Thermostat[ctr_output].temp_abs_max_atune - peak_avg)) { + + ThermostatAutotuneParamCalc(ctr_output); + Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; + } + } + } + peak_transition = false; +} + +void ThermostatAutotuneParamCalc(uint8_t ctr_output) +{ + uint8_t peak_num = Thermostat[ctr_output].peak_ctr; + + + + Thermostat[ctr_output].kU_pi_atune = (uint16_t)(100 * ((uint32_t)400000 * (uint32_t)(Thermostat[ctr_output].dutycycle_step_autotune)) / ((uint32_t)(Thermostat[ctr_output].temp_abs_max_atune - Thermostat[ctr_output].temp_abs_min_atune) * (uint32_t)314159)); + Thermostat[ctr_output].pU_pi_atune = (Thermostat[ctr_output].time_peak_timestamps_atune[peak_num - 1] - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num - 2]); + + switch (Thermostat[ctr_output].status.autotune_perf_mode) { + case AUTOTUNE_PERF_FAST: + + Thermostat[ctr_output].kP_pi_atune = (4 * Thermostat[ctr_output].kU_pi_atune) / 10; + break; + case AUTOTUNE_PERF_NORMAL: + + Thermostat[ctr_output].kP_pi_atune = (18 * Thermostat[ctr_output].kU_pi_atune) / 100; + break; + case AUTOTUNE_PERF_SLOW: + + Thermostat[ctr_output].kP_pi_atune = (13 * Thermostat[ctr_output].kU_pi_atune) / 100; + break; + } + + + Thermostat[ctr_output].kI_pi_atune = (12 * (6000 * Thermostat[ctr_output].kU_pi_atune / Thermostat[ctr_output].pU_pi_atune)) / 10; + + + Thermostat[ctr_output].val_prop_band_atune = 100 / Thermostat[ctr_output].kP_pi_atune; + + Thermostat[ctr_output].time_reset_atune = (uint32_t)((((uint32_t)Thermostat[ctr_output].kP_pi_atune * (uint32_t)Thermostat[ctr_output].time_pi_cycle * 6000)) / (uint32_t)Thermostat[ctr_output].kI_pi_atune); +} + +void ThermostatWorkAutomaticPIAutotune(uint8_t ctr_output) +{ + bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); + + + if ((uptime < Thermostat[ctr_output].time_ctr_checkpoint) + &&(Thermostat[ctr_output].temp_target_level_ctr == Thermostat[ctr_output].temp_target_level)) { + if (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) { + Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; + + Thermostat[ctr_output].time_ctr_changepoint = uptime + (((uint32_t)Thermostat[ctr_output].time_pi_cycle * (uint32_t)Thermostat[ctr_output].dutycycle_step_autotune) / (uint32_t)100); + + Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; + } + + if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { + Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; + Thermostat[ctr_output].status.command_output = IFACE_ON; + } + else { + Thermostat[ctr_output].status.command_output = IFACE_OFF; + } + + ThermostatPeakDetector(ctr_output); + } + else { + + Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; + } + + if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) { + + Thermostat[ctr_output].status.command_output = IFACE_OFF; + } +} +#endif + +void ThermostatCtrWork(uint8_t ctr_output) +{ + switch (Thermostat[ctr_output].status.controller_mode) { + + case CTR_HYBRID: + switch (Thermostat[ctr_output].status.phase_hybrid_ctr) { + case CTR_HYBRID_RAMP_UP: + ThermostatWorkAutomaticRampUp(ctr_output); + break; + case CTR_HYBRID_PI: + ThermostatWorkAutomaticPI(ctr_output); + break; +#ifdef USE_PI_AUTOTUNING + + case CTR_HYBRID_PI_AUTOTUNE: + ThermostatWorkAutomaticPIAutotune(ctr_output); + break; +#endif + } + break; + + case CTR_PI: + ThermostatWorkAutomaticPI(ctr_output); + break; + + case CTR_RAMP_UP: + ThermostatWorkAutomaticRampUp(ctr_output); + break; +#ifdef USE_PI_AUTOTUNING + + case CTR_PI_AUTOTUNE: + ThermostatWorkAutomaticPIAutotune(ctr_output); + break; +#endif + } +} + +void ThermostatWork(uint8_t ctr_output) +{ + switch (Thermostat[ctr_output].status.thermostat_mode) { + + case THERMOSTAT_OFF: + Thermostat[ctr_output].status.command_output = IFACE_OFF; + break; + + case THERMOSTAT_AUTOMATIC_OP: + ThermostatCtrWork(ctr_output); + + break; + + case THERMOSTAT_MANUAL_OP: + Thermostat[ctr_output].time_ctr_checkpoint = 0; + Thermostat[ctr_output].status.command_output = Thermostat[ctr_output].status.status_input; + break; + } + ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output); +} + +void ThermostatDiagnostics(uint8_t ctr_output) +{ + + if ((Thermostat[ctr_output].diag.diagnostic_mode == DIAGNOSTIC_ON) + &&(Thermostat[ctr_output].diag.output_inconsist_ctr >= THERMOSTAT_TIME_MAX_OUTPUT_INCONSIST)) { + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; + Thermostat[ctr_output].diag.state_emergency = EMERGENCY_ON; + } + + + + + + if (Thermostat[ctr_output].diag.state_emergency == EMERGENCY_ON) { + ThermostatEmergencyShutdown(ctr_output); + } +} + +void ThermostatController(uint8_t ctr_output) +{ + ThermostatState(ctr_output); + ThermostatWork(ctr_output); +} + +bool ThermostatTimerArm(uint8_t ctr_output, int16_t tempVal) +{ + bool result = false; + + if ((tempVal >= -1000) + && (tempVal <= 1000) + && (tempVal >= (int16_t)Thermostat[ctr_output].temp_frost_protect)) { + Thermostat[ctr_output].temp_target_level = tempVal; + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_AUTOMATIC_OP; + result = true; + } + + return result; +} + +void ThermostatTimerDisarm(uint8_t ctr_output) +{ + Thermostat[ctr_output].temp_target_level = THERMOSTAT_TEMP_INIT; + Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; +} + +#ifdef DEBUG_THERMOSTAT +void ThermostatVirtualSwitch(uint8_t ctr_output) +{ + char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; + if (ctr_output < DOMOTICZ_MAX_IDX) { + Response_P(DOMOTICZ_MES, Domoticz_Virtual_Switches[ctr_output], (0 == Thermostat[ctr_output].status.command_output) ? 0 : 1, ""); + MqttPublish(domoticz_in_topic); + } +} + +void ThermostatVirtualSwitchCtrState(uint8_t ctr_output) +{ + char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; + Response_P(DOMOTICZ_MES, DOMOTICZ_IDX2, (0 == Thermostat[0].status.phase_hybrid_ctr) ? 0 : 1, ""); + MqttPublish(domoticz_in_topic); +} + +void ThermostatDebug(uint8_t ctr_output) +{ + char result_chr[FLOATSZ]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("------ Thermostat Start ------")); + dtostrfd(Thermostat[ctr_output].status.counter_seconds, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.counter_seconds: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.thermostat_mode, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.thermostat_mode: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].diag.state_emergency, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].diag.state_emergency: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].diag.output_inconsist_ctr, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].diag.output_inconsist_ctr: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.controller_mode, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.controller_mode: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.command_output, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.command_output: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.status_output, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_output: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.status_input, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_input: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.phase_hybrid_ctr, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.phase_hybrid_ctr: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.sensor_alive, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.sensor_alive: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].status.status_cycle_active, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_cycle_active: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].temp_pi_error, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_pi_error: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].temp_pi_accum_error, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_pi_accum_error: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_proportional_pi, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_proportional_pi: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_integral_pi, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_integral_pi: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_total_pi, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_total_pi: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].temp_measured_gradient, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_measured_gradient: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_rampup_deadtime, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_rampup_deadtime: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].temp_rampup_meas_gradient, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_rampup_meas_gradient: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_ctr_changepoint, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_ctr_changepoint: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].temp_rampup_output_off, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_rampup_output_off: %s"), result_chr); + dtostrfd(Thermostat[ctr_output].time_ctr_checkpoint, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_ctr_checkpoint: %s"), result_chr); + dtostrfd(uptime, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("uptime: %s"), result_chr); + dtostrfd(power, 0, result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("power: %s"), result_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("------ Thermostat End ------")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("")); +} +#endif + +void ThermostatGetLocalSensor(uint8_t ctr_output) { + String buf = mqtt_data; + JsonParser parser((char*)buf.c_str()); + JsonParserObject root = parser.getRootObject(); + if (root) { + JsonParserToken value_token = root[PSTR(THERMOSTAT_SENSOR_NAME)].getObject()[PSTR("Temperature")]; + if (value_token.isNum()) { + int16_t value = value_token.getFloat() * 10; + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatFahrenheitToCelsius(value, TEMP_CONV_ABSOLUTE); + } + if ( (value >= -1000) + && (value <= 1000) + && (Thermostat[ctr_output].status.sensor_type == SENSOR_LOCAL)) { + uint32_t timestamp = uptime; + + if (value != Thermostat[ctr_output].temp_measured) { + int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); + uint32_t time_delta = (timestamp - Thermostat[ctr_output].timestamp_temp_meas_change_update); + Thermostat[ctr_output].temp_measured_gradient = (int32_t)((360000 * temp_delta) / ((int32_t)time_delta)); + Thermostat[ctr_output].temp_measured = value; + Thermostat[ctr_output].timestamp_temp_meas_change_update = timestamp; + } + Thermostat[ctr_output].timestamp_temp_measured_update = timestamp; + Thermostat[ctr_output].status.sensor_alive = IFACE_ON; + } + } + } +} + + + + + +void CmndThermostatModeSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); + if ((value >= THERMOSTAT_OFF) && (value < THERMOSTAT_MODES_MAX)) { + Thermostat[ctr_output].status.thermostat_mode = value; + Thermostat[ctr_output].timestamp_input_on = 0; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.thermostat_mode); + } +} + +void CmndClimateModeSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); + if ((value >= CLIMATE_HEATING) && (value < CLIMATE_MODES_MAX)) { + Thermostat[ctr_output].status.climate_mode = value; + + Thermostat[ctr_output].time_ctr_checkpoint = uptime; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.climate_mode); + } +} + +void CmndTempFrostProtectSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + int16_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (int16_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); + } + else { + value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= 0) + && (value <= 127)) { + Thermostat[ctr_output].temp_frost_protect = (uint8_t)value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_frost_protect, TEMP_CONV_ABSOLUTE); + } + else { + value = (int16_t)Thermostat[ctr_output].temp_frost_protect; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndControllerModeSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= CTR_HYBRID) && (value < CTR_MODES_MAX)) { + Thermostat[ctr_output].status.controller_mode = value; + + Thermostat[ctr_output].timestamp_rampup_start = uptime; + Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; + Thermostat[ctr_output].temp_rampup_meas_gradient = 0; + Thermostat[ctr_output].time_rampup_deadtime = 0; + Thermostat[ctr_output].counter_rampup_cycles = 1; + Thermostat[ctr_output].time_ctr_changepoint = 0; + Thermostat[ctr_output].time_ctr_checkpoint = 0; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.controller_mode); + } +} + +void CmndInputSwitchSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if (ThermostatSwitchIdValid(value)) { + Thermostat[ctr_output].status.input_switch_number = value; + Thermostat[ctr_output].timestamp_input_on = uptime; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.input_switch_number); + } +} + +void CmndInputSwitchUse(void) +{ + if ((XdrvMailbox.index >= INPUT_NOT_USED) && (XdrvMailbox.index <= INPUT_USED)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + Thermostat[ctr_output].status.use_input = (uint32_t)(XdrvMailbox.payload); + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.use_input); + } +} + +void CmndSensorInputSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= SENSOR_MQTT) && (value < SENSOR_MAX)) { + Thermostat[ctr_output].status.sensor_type = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.sensor_type); + } +} + +void CmndOutputRelaySet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if (ThermostatRelayIdValid(value)) { + Thermostat[ctr_output].status.output_relay_number = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.output_relay_number); + } +} + +void CmndTimeAllowRampupSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value < 1440)) { + Thermostat[ctr_output].time_allow_rampup = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_allow_rampup)); + } +} + +void CmndTempFormatSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= TEMP_FAHRENHEIT)) { + Thermostat[ctr_output].status.temp_format = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.temp_format); + } +} + +void CmndTempMeasuredSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + int16_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); + } + else { + value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= -1000) + && (value <= 1000) + && (Thermostat[ctr_output].status.sensor_type == SENSOR_MQTT)) { + uint32_t timestamp = uptime; + + if (value != Thermostat[ctr_output].temp_measured) { + int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); + uint32_t time_delta = (timestamp - Thermostat[ctr_output].timestamp_temp_meas_change_update); + Thermostat[ctr_output].temp_measured_gradient = (int32_t)((360000 * temp_delta) / ((int32_t)time_delta)); + Thermostat[ctr_output].temp_measured = value; + Thermostat[ctr_output].timestamp_temp_meas_change_update = timestamp; + } + Thermostat[ctr_output].timestamp_temp_measured_update = timestamp; + Thermostat[ctr_output].status.sensor_alive = IFACE_ON; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_measured, TEMP_CONV_ABSOLUTE); + } + else { + value = Thermostat[ctr_output].temp_measured; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndTempTargetSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + int16_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); + } + else { + value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= -1000) + && (value <= 1000) + && (value >= (int16_t)Thermostat[ctr_output].temp_frost_protect)) { + Thermostat[ctr_output].temp_target_level = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_target_level, TEMP_CONV_ABSOLUTE); + } + else { + value = Thermostat[ctr_output].temp_target_level; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndTempMeasuredGrdRead(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + int16_t value; + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_measured_gradient, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_measured_gradient; + } + ResponseCmndFloat(((float)value) / 1000, 1); + } +} + +void CmndStateEmergencySet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1)) { + Thermostat[ctr_output].diag.state_emergency = (uint16_t)value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].diag.state_emergency); + } +} + +void CmndTimeManualToAutoSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_manual_to_auto = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_manual_to_auto)); + } +} + +void CmndPropBandSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 20)) { + Thermostat[ctr_output].val_prop_band = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].val_prop_band); + } +} + +void CmndTimeResetSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 86400)) { + Thermostat[ctr_output].time_reset = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].time_reset); + } +} + +void CmndTimePiProportRead(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + ResponseCmndNumber((int)Thermostat[ctr_output].time_proportional_pi); + } +} + +void CmndTimePiIntegrRead(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + ResponseCmndNumber((int)Thermostat[ctr_output].time_integral_pi); + } +} + +void CmndTimePiCycleSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_pi_cycle = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_pi_cycle)); + } +} + +void CmndTempAntiWindupResetSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + uint8_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); + } + else { + value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= 0) + && (value <= 100)) { + Thermostat[ctr_output].temp_reset_anti_windup = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_reset_anti_windup, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_reset_anti_windup; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndTempHystSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + int8_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (int8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); + } + else { + value = (int8_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= -100) + && (value <= 100)) { + Thermostat[ctr_output].temp_hysteresis = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_hysteresis, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_hysteresis; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +#ifdef USE_PI_AUTOTUNING +void CmndPerfLevelAutotune(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= AUTOTUNE_PERF_MAX)) { + Thermostat[ctr_output].status.autotune_perf_mode = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.autotune_perf_mode); + } +} +#endif + +void CmndTimeMaxActionSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_max_action = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_max_action)); + } +} + +void CmndTimeMinActionSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_min_action = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_min_action)); + } +} + +void CmndTimeSensLostSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_sens_lost = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_sens_lost)); + } +} + +void CmndTimeMinTurnoffActionSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_min_turnoff_action = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_min_turnoff_action)); + } +} + +void CmndTempRupDeltInSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + uint8_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); + } + else { + value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= 0) + && (value <= 100)) { + Thermostat[ctr_output].temp_rampup_delta_in = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_delta_in, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_rampup_delta_in; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndTempRupDeltOutSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + uint8_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); + } + else { + value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); + } + if ( (value >= 0) + && (value <= 100)) { + Thermostat[ctr_output].temp_rampup_delta_out = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_delta_out, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_rampup_delta_out; + } + ResponseCmndFloat((float)value / 10, 1); + } +} + +void CmndTimeRampupMaxSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_rampup_max = (uint16_t)value; + } + } + ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_rampup_max)); + } +} + +void CmndTimeRampupCycleSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint32_t value = (uint32_t)(XdrvMailbox.payload); + if ((value >= 0) && (value <= 1440)) { + Thermostat[ctr_output].time_rampup_cycle = (uint16_t)value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].time_rampup_cycle); + } +} + +void CmndTempRampupPiAccErrSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + uint16_t value; + if (XdrvMailbox.data_len > 0) { + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = (uint16_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 100), TEMP_CONV_RELATIVE); + } + else { + value = (uint16_t)(CharToFloat(XdrvMailbox.data) * 100); + } + if ( (value >= 0) + && (value <= 2500)) { + Thermostat[ctr_output].temp_rampup_pi_acc_error = value; + } + } + if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { + value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_pi_acc_error, TEMP_CONV_RELATIVE); + } + else { + value = Thermostat[ctr_output].temp_rampup_pi_acc_error; + } + ResponseCmndFloat((float)value / 100, 1); + } +} + +void CmndDiagnosticModeSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); + if ((value >= DIAGNOSTIC_OFF) && (value <= DIAGNOSTIC_ON)) { + Thermostat[ctr_output].diag.diagnostic_mode = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].diag.diagnostic_mode); + } +} + +void CmndCtrDutyCycleRead(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + uint8_t value = 0; + if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { + value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; + } + else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) + || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) + &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { + if (Thermostat[ctr_output].status.status_output == IFACE_ON) { + value = 100; + } + else { + value = 0; + } + } + ResponseCmndNumber((int)value); + } +} + +void CmndEnableOutputSet(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { + uint8_t ctr_output = XdrvMailbox.index - 1; + if (XdrvMailbox.data_len > 0) { + uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); + if ((value >= IFACE_OFF) && (value <= IFACE_ON)) { + Thermostat[ctr_output].status.enable_output = value; + } + } + ResponseCmndNumber((int)Thermostat[ctr_output].status.enable_output); + } +} + + + + + +bool Xdrv39(uint8_t function) +{ + bool result = false; + uint8_t ctr_output; + + switch (function) { + case FUNC_INIT: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + ThermostatInit(ctr_output); + } + break; + case FUNC_LOOP: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + if (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF) { + ThermostatSignalProcessingFast(ctr_output); + ThermostatDiagnostics(ctr_output); + } + } + break; + case FUNC_SERIAL: + break; + case FUNC_EVERY_SECOND: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + if ((ThermostatMinuteCounter(ctr_output)) + && (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF)) { + ThermostatSignalPreProcessingSlow(ctr_output); + ThermostatController(ctr_output); + ThermostatSignalPostProcessingSlow(ctr_output); +#ifdef DEBUG_THERMOSTAT + ThermostatDebug(ctr_output); +#endif + } + } + break; + case FUNC_SHOW_SENSOR: + for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { + if (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF) { + ThermostatGetLocalSensor(ctr_output); + } + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kThermostatCommands, ThermostatCommand); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" +#ifdef USE_TELEGRAM +# 41 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" +#define XDRV_40 40 + +#ifndef TELEGRAM_LOOP_WAIT +#define TELEGRAM_LOOP_WAIT 10 +#endif + +#define TELEGRAM_SEND_RETRY 4 +#define TELEGRAM_MAX_MESSAGES 2 + +#ifdef USE_MQTT_TLS_CA_CERT + static const uint32_t tls_rx_size = 2048; + static const uint32_t tls_tx_size = 1024; +#else + static const uint32_t tls_rx_size = 1024; + static const uint32_t tls_tx_size = 1024; +#endif + +#include "WiFiClientSecureLightBearSSL.h" +BearSSL::WiFiClientSecure_light *telegramClient = nullptr; + +static const uint8_t Telegram_Fingerprint[] PROGMEM = USE_TELEGRAM_FINGERPRINT; + +typedef struct { + String text; + + + + uint32_t update_id = 0; + uint32_t chat_id = 0; +} TelegramMessage; + +struct { + TelegramMessage message[TELEGRAM_MAX_MESSAGES]; + uint32_t next_update_id = 0; + uint8_t message_count = 0; + uint8_t state = 0; + uint8_t index = 0; + uint8_t retry = 0; + uint8_t poll = TELEGRAM_LOOP_WAIT; + uint8_t wait = 0; + bool send_enable = false; + bool recv_enable = false; + bool echo_enable = false; + bool recv_busy = false; + bool skip = true; +} Telegram; + +bool TelegramInit(void) { + bool init_done = false; + if (strlen(SettingsText(SET_TELEGRAM_TOKEN))) { + if (!telegramClient) { + telegramClient = new BearSSL::WiFiClientSecure_light(tls_rx_size, tls_tx_size); +#ifdef USE_MQTT_TLS_CA_CERT + telegramClient->setTrustAnchor(&GoDaddyCAG2_TA, 1); +#else + telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); +#endif + Telegram.message_count = 0; + Telegram.next_update_id = 0; + Telegram.message[0].text = ""; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("TGM: Started")); + } + init_done = true; + } + return init_done; +} + +String TelegramConnectToTelegram(String command) { + + + if (!TelegramInit()) { return ""; } + + String response = ""; + uint32_t tls_connect_time = millis(); + if (telegramClient->connect("api.telegram.org", 443)) { + + + + telegramClient->println("GET /"+command); + + char c; + int ch_count=0; + uint32_t now = millis(); + bool avail = false; + while (millis() -now < 1500) { + while (telegramClient->available()) { + char c = telegramClient->read(); + if (ch_count < 700) { + response = response + c; + ch_count++; + } + avail = true; + } + if (avail) { + break; + } + } + + telegramClient->stop(); + } + + return response; +} + +void TelegramGetUpdates(uint32_t offset) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: getUpdates")); + + if (!TelegramInit()) { return; } + + String _token = SettingsText(SET_TELEGRAM_TOKEN); + String command = "bot" + _token + "/getUpdates?offset=" + String(offset); + String response = TelegramConnectToTelegram(command); +# 207 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: Response %s"), response.c_str()); + + JsonParser parser((char*)response.c_str()); + JsonParserObject root = parser.getRootObject(); + if (root) { + + + + JsonParserArray arr = root[PSTR("result")]; + uint32_t max_updates = arr.size(); + + if (max_updates > 1) { max_updates = 1; } + Telegram.message_count = 0; + if (max_updates) { + for (uint32_t i = 0; i < max_updates; i++) { + Telegram.message[i].text = ""; + JsonParserObject result = arr[i].getObject(); + if (result) { + + + + + + + Telegram.message_count++; + Telegram.message[i].update_id = result["update_id"].getUInt(); + + + + Telegram.message[i].chat_id = result["message"].getObject()["chat"].getObject()["id"].getUInt(); + Telegram.message[i].text = result["message"].getObject()["text"].getStr(); + } + Telegram.next_update_id = Telegram.message[i].update_id +1; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: Parsed update_id %d, chat_id %d, text \"%s\""), Telegram.message[i].update_id, Telegram.message[i].chat_id, Telegram.message[i].text.c_str()); + } + } else { + + } + } else { + + } +} + +bool TelegramSendMessage(uint32_t chat_id, String text) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: sendMessage")); + + if (!TelegramInit()) { return false; } + + bool sent = false; + if (text != "") { + String _token = SettingsText(SET_TELEGRAM_TOKEN); + String command = "bot" + _token + "/sendMessage?chat_id=" + String(chat_id) + "&text=" + text; + String response = TelegramConnectToTelegram(command); + + + + if (response.startsWith("{\"ok\":true")) { + + sent = true; + } + } + + return sent; +} +# 289 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" +String TelegramExecuteCommand(const char *svalue) { + String response = ""; + + uint32_t curridx = web_log_index; + ExecuteCommand(svalue, SRC_CHAT); + if (web_log_index != curridx) { + uint32_t counter = curridx; + response = F("{"); + 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); + if (cflg) { response += F(","); } + response += stemp; + cflg = true; + } + } + counter++; + counter &= 0xFF; + if (!counter) counter++; + } while (counter != web_log_index); + response += F("}"); + } else { + response = F("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"); + } + + return response; +} + +void TelegramLoop(void) { + if (!global_state.network_down && (Telegram.recv_enable || Telegram.echo_enable)) { + switch (Telegram.state) { + case 0: + TelegramInit(); + Telegram.state++; + break; + case 1: + TelegramGetUpdates(Telegram.next_update_id); + Telegram.index = 0; + Telegram.retry = TELEGRAM_SEND_RETRY; + Telegram.state++; + break; + case 2: + if (Telegram.echo_enable) { + if (Telegram.retry && (Telegram.index < Telegram.message_count)) { + if (TelegramSendMessage(Telegram.message[Telegram.index].chat_id, Telegram.message[Telegram.index].text)) { + Telegram.index++; + Telegram.retry = TELEGRAM_SEND_RETRY; + } else { + Telegram.retry--; + } + } else { + Telegram.message_count = 0; + Telegram.wait = Telegram.poll; + Telegram.state++; + } + } else { + if (Telegram.skip) { + Telegram.skip = false; + } else { + if (Telegram.message_count && (Telegram.message[Telegram.index].text.length() > 0)) { + String logging = TelegramExecuteCommand(Telegram.message[Telegram.index].text.c_str()); + if (logging.length() > 0) { + TelegramSendMessage(Telegram.message[Telegram.index].chat_id, logging); + } + } + } + Telegram.message_count = 0; + Telegram.wait = Telegram.poll; + Telegram.state++; + } + break; + case 3: + if (Telegram.wait) { + Telegram.wait--; + } else { + Telegram.state = 1; + } + } + } +} + + + + + +#define D_CMND_TMSTATE "State" +#define D_CMND_TMPOLL "Poll" +#define D_CMND_TMSEND "Send" +#define D_CMND_TMTOKEN "Token" +#define D_CMND_TMCHATID "ChatId" + +const char kTelegramCommands[] PROGMEM = "Tm|" + D_CMND_TMSTATE "|" D_CMND_TMPOLL "|" D_CMND_TMTOKEN "|" D_CMND_TMCHATID "|" D_CMND_TMSEND; + +void (* const TelegramCommand[])(void) PROGMEM = { + &CmndTmState, &CmndTmPoll, &CmndTmToken, &CmndTmChatId, &CmndTmSend }; + +void CmndTmState(void) { + if (XdrvMailbox.data_len > 0) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + Telegram.send_enable = XdrvMailbox.payload &1; + break; + case 2: + case 3: + Telegram.recv_enable = XdrvMailbox.payload &1; + break; + case 4: + case 5: + Telegram.echo_enable = XdrvMailbox.payload &1; + break; + } + } + } + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"), + XdrvMailbox.command, GetStateText(Telegram.send_enable), GetStateText(Telegram.recv_enable), GetStateText(Telegram.echo_enable)); +} + +void CmndTmPoll(void) { + if ((XdrvMailbox.payload >= 4) && (XdrvMailbox.payload <= 300)) { + Telegram.poll = XdrvMailbox.payload; + if (Telegram.poll < Telegram.wait) { + Telegram.wait = Telegram.poll; + } + } + ResponseCmndNumber(Telegram.poll); +} + +void CmndTmToken(void) { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_TELEGRAM_TOKEN, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_TELEGRAM_TOKEN)); +} + +void CmndTmChatId(void) { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_TELEGRAM_CHATID, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_TELEGRAM_CHATID)); +} + +void CmndTmSend(void) { + if (!Telegram.send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) { + ResponseCmndChar(D_JSON_FAILED); + return; + } + if (XdrvMailbox.data_len > 0) { + String message = XdrvMailbox.data; + String chat_id = SettingsText(SET_TELEGRAM_CHATID); + if (!TelegramSendMessage(chat_id.toInt(), message)) { + ResponseCmndChar(D_JSON_FAILED); + return; + } + } + ResponseCmndDone(); +} + + + + + +bool Xdrv40(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + TelegramLoop(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTelegramCommands, TelegramCommand); + break; + } + return result; +} +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" +#ifdef USE_TCP_BRIDGE + +#define XDRV_41 41 + +#ifndef TCP_BRIDGE_CONNECTIONS +#define TCP_BRIDGE_CONNECTIONS 2 +#endif + +#ifndef TCP_BRIDGE_BUF_SIZE +#define TCP_BRIDGE_BUF_SIZE 255 +#endif + + +WiFiServer *server_tcp = nullptr; + +WiFiClient client_tcp[TCP_BRIDGE_CONNECTIONS]; +uint8_t client_next = 0; +uint8_t *tcp_buf = nullptr; + +#include +TasmotaSerial *TCPSerial = nullptr; + +const char kTCPCommands[] PROGMEM = "TCP" "|" + "Start" "|" "Baudrate" + ; + +void (* const TCPCommand[])(void) PROGMEM = { + &CmndTCPStart, &CmndTCPBaudrate + }; + + + + +void TCPLoop(void) +{ + uint8_t c; + bool busy; + int32_t buf_len; + + if (!TCPSerial) return; + + + if ((server_tcp) && (server_tcp->hasClient())) { + + uint32_t i; + for (i=0; iavailable(); + break; + } + } + if (i >= ARRAY_SIZE(client_tcp)) { + i = client_next++ % ARRAY_SIZE(client_tcp); + WiFiClient &client = client_tcp[i]; + client.stop(); + client = server_tcp->available(); + } + } + + do { + busy = false; + + + buf_len = 0; + while ((buf_len < TCP_BRIDGE_BUF_SIZE) && (TCPSerial->available())) { + c = TCPSerial->read(); + if (c >= 0) { + tcp_buf[buf_len++] = c; + busy = true; + } + } + if (buf_len > 0) { + char hex_char[TCP_BRIDGE_BUF_SIZE+1]; + ToHex_P(tcp_buf, buf_len, hex_char, 256); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "from MCU: %s"), hex_char); + + for (uint32_t i=0; i= 0) { + tcp_buf[buf_len++] = c; + busy = true; + } + } + if (buf_len > 0) { + char hex_char[TCP_BRIDGE_BUF_SIZE+1]; + ToHex_P(tcp_buf, buf_len, hex_char, 256); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "to MCU/%d: %s"), i+1, hex_char); + TCPSerial->write(tcp_buf, buf_len); + } + } + + yield(); + } while (busy); +} + + +void TCPInit(void) { + if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) { + tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE); + if (!tcp_buf) { AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; } + + if (!Settings.tcp_baudrate) { Settings.tcp_baudrate = 115200 / 1200; } + TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); + TCPSerial->begin(Settings.tcp_baudrate * 1200); + if (TCPSerial->hardwareSerial()) { + ClaimSerial(); + } + } +} +# 148 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" +void CmndTCPStart(void) { + + if (!TCPSerial) { return; } + int32_t tcp_port = XdrvMailbox.payload; + + if (server_tcp) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Stopping TCP server")); + server_tcp->stop(); + delete server_tcp; + server_tcp = nullptr; + + for (uint32_t i=0; i 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Starting TCP server on port %d"), tcp_port); + server_tcp = new WiFiServer(tcp_port); + server_tcp->begin(); + server_tcp->setNoDelay(true); + } + + ResponseCmndDone(); +} + +void CmndTCPBaudrate(void) { + if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) { + XdrvMailbox.payload /= 1200; + Settings.tcp_baudrate = XdrvMailbox.payload; + TCPSerial->begin(Settings.tcp_baudrate * 1200); + } + ResponseCmndNumber(Settings.tcp_baudrate * 1200); +} + + + + + +bool Xdrv41(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + TCPLoop(); + break; + case FUNC_PRE_INIT: + TCPInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTCPCommands, TCPCommand); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_42_i2s_audio.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_42_i2s_audio.ino" +#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) +#include "AudioFileSourcePROGMEM.h" +#include "AudioFileSourceID3.h" +#include "AudioGeneratorMP3.h" +#include "AudioOutputI2S.h" +#include +#include "AudioFileSourceFS.h" +#ifdef SAY_TIME +#include "AudioGeneratorTalkie.h" +#endif +#include "AudioFileSourceICYStream.h" +#include "AudioFileSourceBuffer.h" +#include "AudioGeneratorAAC.h" + +#ifdef USE_TTGO_WATCH +#undef TTGO_PWR_ON +#undef TTGO_PWR_OFF +#define TTGO_PWR_ON TTGO_audio_power(true); +#define TTGO_PWR_OFF TTGO_audio_power(false); +#else +#undef TTGO_PWR_ON +#undef TTGO_PWR_OFF +#define TTGO_PWR_ON +#define TTGO_PWR_OFF +#endif + +#define EXTERNAL_DAC_PLAY 1 + +#define XDRV_42 42 + +AudioGeneratorMP3 *mp3 = nullptr; +AudioFileSourceFS *file; +AudioOutputI2S *out; +AudioFileSourceID3 *id3; +AudioGeneratorMP3 *decoder = NULL; +void *mp3ram = NULL; + +#define I2SAUDIO_TASK_STACK_SIZE 8192 + + +#ifdef ESP8266 +const int preallocateBufferSize = 5*1024; +const int preallocateCodecSize = 29192; +#else +const int preallocateBufferSize = 16*1024; +const int preallocateCodecSize = 29192; + +#endif + +#ifdef USE_WEBRADIO +AudioFileSourceICYStream *ifile = NULL; +AudioFileSourceBuffer *buff = NULL; +char wr_title[64]; + + +void *preallocateBuffer = NULL; +void *preallocateCodec = NULL; +uint32_t retryms = 0; +#endif + +#ifdef SAY_TIME +AudioGeneratorTalkie *talkie = nullptr; +#endif + + +#ifdef ESP32 +#undef TWATCH_DAC_IIS_BCK +#undef TWATCH_DAC_IIS_WS +#undef TWATCH_DAC_IIS_DOUT +#define TWATCH_DAC_IIS_BCK 26 +#define TWATCH_DAC_IIS_WS 25 +#define TWATCH_DAC_IIS_DOUT 33 +#else +#undef TWATCH_DAC_IIS_BCK +#undef TWATCH_DAC_IIS_WS +#undef TWATCH_DAC_IIS_DOUT +#define TWATCH_DAC_IIS_BCK 15 +#define TWATCH_DAC_IIS_WS 2 +#define TWATCH_DAC_IIS_DOUT 3 +#endif + + +#ifdef SAY_TIME +long timezone = 2; +byte daysavetime = 1; + +uint8_t spTHE[] PROGMEM = {0x08,0xE8,0x3E,0x55,0x01,0xC3,0x86,0x27,0xAF,0x72,0x0D,0x4D,0x97,0xD5,0xBC,0x64,0x3C,0xF2,0x5C,0x51,0xF1,0x93,0x36,0x8F,0x4F,0x59,0x2A,0x42,0x7A,0x32,0xC3,0x64,0xFF,0x3F}; +uint8_t spTIME[] PROGMEM = {0x0E,0x28,0xAC,0x2D,0x01,0x5D,0xB6,0x0D,0x33,0xF3,0x54,0xB3,0x60,0xBA,0x8C,0x54,0x5C,0xCD,0x2D,0xD4,0x32,0x73,0x0F,0x8E,0x34,0x33,0xCB,0x4A,0x25,0xD4,0x25,0x83,0x2C,0x2B,0xD5,0x50,0x97,0x08,0x32,0xEC,0xD4,0xDC,0x4C,0x33,0xC8,0x70,0x73,0x0F,0x33,0xCD,0x20,0xC3,0xCB,0x43,0xDD,0x3C,0xCD,0x8C,0x20,0x77,0x89,0xF4,0x94,0xB2,0xE2,0xE2,0x35,0x22,0x5D,0xD6,0x4A,0x8A,0x96,0xCC,0x36,0x25,0x2D,0xC9,0x9A,0x7B,0xC2,0x18,0x87,0x24,0x4B,0x1C,0xC9,0x50,0x19,0x92,0x2C,0x71,0x34,0x4B,0x45,0x8A,0x8B,0xC4,0x96,0xB6,0x5A,0x29,0x2A,0x92,0x5A,0xCA,0x53,0x96,0x20,0x05,0x09,0xF5,0x92,0x5D,0xBC,0xE8,0x58,0x4A,0xDD,0xAE,0x73,0xBD,0x65,0x4B,0x8D,0x78,0xCA,0x2B,0x4E,0xD8,0xD9,0xED,0x22,0x20,0x06,0x75,0x00,0x00,0x80,0xFF,0x07}; +uint8_t spIS[] PROGMEM = {0x21,0x18,0x96,0x38,0xB7,0x14,0x8D,0x60,0x3A,0xA6,0xE8,0x51,0xB4,0xDC,0x2E,0x48,0x7B,0x5A,0xF1,0x70,0x1B,0xA3,0xEC,0x09,0xC6,0xCB,0xEB,0x92,0x3D,0xA7,0x69,0x1F,0xAF,0x71,0x89,0x9C,0xA2,0xB3,0xFC,0xCA,0x35,0x72,0x9A,0xD1,0xF0,0xAB,0x12,0xB3,0x2B,0xC6,0xCD,0x4F,0xCC,0x32,0x26,0x19,0x07,0xDF,0x0B,0x8F,0xB8,0xA4,0xED,0x7C,0xCF,0x23,0x62,0x8B,0x8E,0xF1,0x23,0x0A,0x8B,0x6E,0xCB,0xCE,0xEF,0x54,0x44,0x3C,0xDC,0x08,0x60,0x0B,0x37,0x01,0x1C,0x53,0x26,0x80,0x15,0x4E,0x14,0xB0,0x54,0x2B,0x02,0xA4,0x69,0xFF,0x7F}; +uint8_t spA_M_[] PROGMEM = {0xCD,0xEF,0x86,0xAB,0x57,0x6D,0x0F,0xAF,0x71,0xAD,0x49,0x55,0x3C,0xFC,0x2E,0xC5,0xB7,0x5C,0xF1,0xF2,0x87,0x66,0xDD,0x4E,0xC5,0xC3,0xEF,0x92,0xE2,0x3A,0x65,0xB7,0xA0,0x09,0xAA,0x1B,0x97,0x54,0x82,0x2E,0x28,0x77,0x5C,0x52,0x09,0x1A,0xA3,0xB8,0x76,0x49,0x25,0x68,0x8C,0x73,0xDB,0x24,0x95,0xA0,0x32,0xA9,0x6B,0xA7,0xD9,0x82,0x26,0xA9,0x76,0x42,0xD6,0x08,0xBA,0xE1,0xE8,0x0E,0x5A,0x2B,0xEA,0x9E,0x3D,0x27,0x18,0xAD,0xA8,0x07,0xF1,0x98,0x90,0x35,0xA2,0x96,0x44,0xA3,0x5D,0x66,0x8B,0x6B,0x12,0xCD,0x32,0x85,0x25,0xC9,0x81,0x2D,0xC3,0x64,0x85,0x34,0x58,0x89,0x94,0x52,0x1C,0x52,0x2F,0x35,0xDA,0xC7,0x51,0x48,0x23,0x97,0xCC,0x2C,0x97,0x2E,0xF3,0x5C,0xF3,0xA2,0x14,0xBA,0x2C,0x48,0xCE,0xCA,0x76,0xE8,0x32,0x2F,0x34,0xB2,0xDB,0x85,0xC9,0x83,0x90,0xA8,0x2C,0x57,0x26,0x8F,0x9C,0xBD,0xA2,0x53,0xD9,0xC2,0x54,0x59,0x28,0x99,0x4B,0x2C,0x5D,0xFF,0x3F}; +uint8_t spP_M_[] PROGMEM = {0x0E,0x98,0x41,0x54,0x00,0x43,0xA0,0x05,0xAB,0x42,0x8E,0x1D,0xA3,0x15,0xEC,0x4E,0x58,0xF7,0x92,0x66,0x70,0x1B,0x66,0xDB,0x73,0x99,0xC1,0xEB,0x98,0xED,0xD6,0x25,0x25,0x6F,0x70,0x92,0xDD,0x64,0xD8,0xFC,0x61,0xD0,0x66,0x83,0xD6,0x0A,0x86,0x23,0xAB,0x69,0xDA,0x2B,0x18,0x9E,0x3D,0x37,0x69,0x9D,0xA8,0x07,0x71,0x9F,0xA0,0xBD,0xA2,0x16,0xD5,0x7C,0x54,0xF6,0x88,0x6B,0x54,0x8B,0x34,0x49,0x2D,0x29,0x49,0x3C,0x34,0x64,0xA5,0x24,0x1B,0x36,0xD7,0x72,0x13,0x92,0xA4,0xC4,0x2D,0xC3,0xB3,0x4B,0xA3,0x62,0x0F,0x2B,0x37,0x6E,0x8B,0x5A,0xD4,0x3D,0xDD,0x9A,0x2D,0x50,0x93,0xF6,0x4C,0xAA,0xB6,0xC4,0x85,0x3B,0xB2,0xB1,0xD8,0x93,0x20,0x4D,0x8F,0x24,0xFF,0x0F}; +uint8_t spOH[] PROGMEM = {0xC6,0xC9,0x71,0x5A,0xA2,0x92,0x14,0x2F,0x6E,0x97,0x9C,0x46,0x9D,0xDC,0xB0,0x4D,0x62,0x1B,0x55,0x70,0xDD,0x55,0xBE,0x0E,0x36,0xC1,0x33,0x37,0xA9,0xA7,0x51,0x1B,0xCF,0x3C,0xA5,0x9E,0x44,0xAC,0x3C,0x7D,0x98,0x7B,0x52,0x96,0x72,0x65,0x4B,0xF6,0x1A,0xD9,0xCA,0xF5,0x91,0x2D,0xA2,0x2A,0x4B,0xF7,0xFF,0x01}; +uint8_t spOCLOCK[] PROGMEM = {0x21,0x4E,0x3D,0xB8,0x2B,0x19,0xBB,0x24,0x0E,0xE5,0xEC,0x60,0xE4,0xF2,0x90,0x13,0xD4,0x2A,0x11,0x80,0x00,0x42,0x69,0x26,0x40,0xD0,0x2B,0x04,0x68,0xE0,0x4D,0x00,0x3A,0x35,0x35,0x33,0xB6,0x51,0xD9,0x64,0x34,0x82,0xB4,0x9A,0x63,0x92,0x55,0x89,0x52,0x5B,0xCA,0x2E,0x34,0x25,0x4E,0x63,0x28,0x3A,0x50,0x95,0x26,0x8D,0xE6,0xAA,0x64,0x58,0xEA,0x92,0xCE,0xC2,0x46,0x15,0x9B,0x86,0xCD,0x2A,0x2E,0x37,0x00,0x00,0x00,0x0C,0xC8,0xDD,0x05,0x01,0xB9,0x33,0x21,0xA0,0x74,0xD7,0xFF,0x07}; +uint8_t spONE[] PROGMEM = {0xCC,0x67,0x75,0x42,0x59,0x5D,0x3A,0x4F,0x9D,0x36,0x63,0xB7,0x59,0xDC,0x30,0x5B,0x5C,0x23,0x61,0xF3,0xE2,0x1C,0xF1,0xF0,0x98,0xC3,0x4B,0x7D,0x39,0xCA,0x1D,0x2C,0x2F,0xB7,0x15,0xEF,0x70,0x79,0xBC,0xD2,0x46,0x7C,0x52,0xE5,0xF1,0x4A,0x6A,0xB3,0x71,0x47,0xC3,0x2D,0x39,0x34,0x4B,0x23,0x35,0xB7,0x7A,0x55,0x33,0x8F,0x59,0xDC,0xA2,0x44,0xB5,0xBC,0x66,0x72,0x8B,0x64,0xF5,0xF6,0x98,0xC1,0x4D,0x42,0xD4,0x27,0x62,0x38,0x2F,0x4A,0xB6,0x9C,0x88,0x68,0xBC,0xA6,0x95,0xF8,0x5C,0xA1,0x09,0x86,0x77,0x91,0x11,0x5B,0xFF,0x0F}; +uint8_t spTWO[] PROGMEM = {0x0E,0x38,0x6E,0x25,0x00,0xA3,0x0D,0x3A,0xA0,0x37,0xC5,0xA0,0x05,0x9E,0x56,0x35,0x86,0xAA,0x5E,0x8C,0xA4,0x82,0xB2,0xD7,0x74,0x31,0x22,0x69,0xAD,0x1C,0xD3,0xC1,0xD0,0xFA,0x28,0x2B,0x2D,0x47,0xC3,0x1B,0xC2,0xC4,0xAE,0xC6,0xCD,0x9C,0x48,0x53,0x9A,0xFF,0x0F}; +uint8_t spTHREE[] PROGMEM = {0x02,0xD8,0x2E,0x9C,0x01,0xDB,0xA6,0x33,0x60,0xFB,0x30,0x01,0xEC,0x20,0x12,0x8C,0xE4,0xD8,0xCA,0x32,0x96,0x73,0x63,0x41,0x39,0x89,0x98,0xC1,0x4D,0x0D,0xED,0xB0,0x2A,0x05,0x37,0x0F,0xB4,0xA5,0xAE,0x5C,0xDC,0x36,0xD0,0x83,0x2F,0x4A,0x71,0x7B,0x03,0xF7,0x38,0x59,0xCD,0xED,0x1E,0xB4,0x6B,0x14,0x35,0xB7,0x6B,0x94,0x99,0x91,0xD5,0xDC,0x26,0x48,0x77,0x4B,0x66,0x71,0x1B,0x21,0xDB,0x2D,0x8A,0xC9,0x6D,0x88,0xFC,0x26,0x28,0x3A,0xB7,0x21,0xF4,0x1F,0xA3,0x65,0xBC,0x02,0x38,0xBB,0x3D,0x8E,0xF0,0x2B,0xE2,0x08,0xB7,0x34,0xFF,0x0F}; +uint8_t spFOUR[] PROGMEM = {0x0C,0x18,0xB6,0x9A,0x01,0xC3,0x75,0x09,0x60,0xD8,0x0E,0x09,0x30,0xA0,0x9B,0xB6,0xA0,0xBB,0xB0,0xAA,0x16,0x4E,0x82,0xEB,0xEA,0xA9,0xFA,0x59,0x49,0x9E,0x59,0x23,0x9A,0x27,0x3B,0x78,0x66,0xAE,0x4A,0x9C,0x9C,0xE0,0x99,0xD3,0x2A,0xBD,0x72,0x92,0xEF,0xE6,0x88,0xE4,0x45,0x4D,0x7E,0x98,0x2D,0x62,0x67,0x37,0xF9,0xA1,0x37,0xA7,0x6C,0x94,0xE4,0xC7,0x1E,0xDC,0x3C,0xA5,0x83,0x1F,0x8B,0xEB,0x52,0x0E,0x0E,0x7E,0x2E,0x4E,0xC7,0x31,0xD2,0x79,0xA5,0x3A,0x0D,0xD9,0xC4,0xFF,0x07}; +uint8_t spFIVE[] PROGMEM = {0x02,0xE8,0x3E,0x8C,0x01,0xDD,0x65,0x08,0x60,0x98,0x4C,0x06,0x34,0x93,0xCE,0x80,0xE6,0xDA,0x9A,0x14,0x6B,0xAA,0x47,0xD1,0x5E,0x56,0xAA,0x6D,0x56,0xCD,0x78,0xD9,0xA9,0x1C,0x67,0x05,0x83,0xE1,0xA4,0xBA,0x38,0xEE,0x16,0x86,0x9B,0xFA,0x60,0x87,0x5B,0x18,0x6E,0xEE,0x8B,0x1D,0x6E,0x61,0xB9,0x69,0x36,0x65,0xBA,0x8D,0xE5,0xE5,0x3E,0x1C,0xE9,0x0E,0x96,0x9B,0x5B,0xAB,0x95,0x2B,0x58,0x6E,0xCE,0xE5,0x3A,0x6A,0xF3,0xB8,0x35,0x84,0x7B,0x05,0xA3,0xE3,0x36,0xEF,0x92,0x19,0xB4,0x86,0xDB,0xB4,0x69,0xB4,0xD1,0x2A,0x4E,0x65,0x9A,0x99,0xCE,0x28,0xD9,0x85,0x71,0x4C,0x18,0x6D,0x67,0x47,0xC6,0x5E,0x53,0x4A,0x9C,0xB5,0xE2,0x85,0x45,0x26,0xFE,0x7F}; +uint8_t spSIX[] PROGMEM = {0x0E,0xD8,0xAE,0xDD,0x03,0x0E,0x38,0xA6,0xD2,0x01,0xD3,0xB4,0x2C,0xAD,0x6A,0x35,0x9D,0xB1,0x7D,0xDC,0xEE,0xC4,0x65,0xD7,0xF1,0x72,0x47,0x24,0xB3,0x19,0xD9,0xD9,0x05,0x70,0x40,0x49,0xEA,0x02,0x98,0xBE,0x42,0x01,0xDF,0xA4,0x69,0x40,0x00,0xDF,0x95,0xFC,0x3F}; +uint8_t spSEVEN[] PROGMEM = {0x02,0xB8,0x3A,0x8C,0x01,0xDF,0xA4,0x73,0x40,0x01,0x47,0xB9,0x2F,0x33,0x3B,0x73,0x5F,0x53,0x7C,0xEC,0x9A,0xC5,0x63,0xD5,0xD1,0x75,0xAE,0x5B,0xFC,0x64,0x5C,0x35,0x87,0x91,0xF1,0x83,0x36,0xB5,0x68,0x55,0xC5,0x6F,0xDA,0x45,0x2D,0x1C,0x2D,0xB7,0x38,0x37,0x9F,0x60,0x3C,0xBC,0x9A,0x85,0xA3,0x25,0x66,0xF7,0x8A,0x57,0x1C,0xA9,0x67,0x56,0xCA,0x5E,0xF0,0xB2,0x16,0xB2,0xF1,0x89,0xCE,0x8B,0x92,0x25,0xC7,0x2B,0x33,0xCF,0x48,0xB1,0x99,0xB4,0xF3,0xFF}; +uint8_t spEIGHT[] PROGMEM = {0xC3,0x6C,0x86,0xB3,0x27,0x6D,0x0F,0xA7,0x48,0x99,0x4E,0x55,0x3C,0xBC,0x22,0x65,0x36,0x4D,0xD1,0xF0,0x32,0xD3,0xBE,0x34,0xDA,0xC3,0xEB,0x82,0xE2,0xDA,0x65,0x35,0xAF,0x31,0xF2,0x6B,0x97,0x95,0xBC,0x86,0xD8,0x6F,0x82,0xA6,0x73,0x0B,0xC6,0x9E,0x72,0x99,0xCC,0xCB,0x02,0xAD,0x3C,0x9A,0x10,0x60,0xAB,0x62,0x05,0x2C,0x37,0x84,0x00,0xA9,0x73,0x00,0x00,0xFE,0x1F}; +uint8_t spNINE[] PROGMEM = {0xCC,0xA1,0x26,0xBB,0x83,0x93,0x18,0xCF,0x4A,0xAD,0x2E,0x31,0xED,0x3C,0xA7,0x24,0x26,0xC3,0x54,0xF1,0x92,0x64,0x8B,0x8A,0x98,0xCB,0x2B,0x2E,0x34,0x53,0x2D,0x0E,0x2F,0x57,0xB3,0x0C,0x0D,0x3C,0xBC,0x3C,0x4C,0x4B,0xCA,0xF4,0xF0,0x72,0x0F,0x6E,0x49,0x53,0xCD,0xCB,0x53,0x2D,0x35,0x4D,0x0F,0x2F,0x0F,0xD7,0x0C,0x0D,0x3D,0xBC,0xDC,0x4D,0xD3,0xDD,0xC2,0xF0,0x72,0x52,0x4F,0x57,0x9B,0xC3,0xAB,0x89,0xBD,0x42,0x2D,0x0F,0xAF,0x5A,0xD1,0x71,0x91,0x55,0xBC,0x2C,0xC5,0x3B,0xD8,0x65,0xF2,0x82,0x94,0x18,0x4E,0x3B,0xC1,0x73,0x42,0x32,0x33,0x15,0x45,0x4F,0x79,0x52,0x6A,0x55,0xA6,0xA3,0xFF,0x07}; +uint8_t spTEN[] PROGMEM = {0x0E,0xD8,0xB1,0xDD,0x01,0x3D,0xA8,0x24,0x7B,0x04,0x27,0x76,0x77,0xDC,0xEC,0xC2,0xC5,0x23,0x84,0xCD,0x72,0x9A,0x51,0xF7,0x62,0x45,0xC7,0xEB,0x4E,0x35,0x4A,0x14,0x2D,0xBF,0x45,0xB6,0x0A,0x75,0xB8,0xFC,0x16,0xD9,0x2A,0xD9,0xD6,0x0A,0x5A,0x10,0xCD,0xA2,0x48,0x23,0xA8,0x81,0x35,0x4B,0x2C,0xA7,0x20,0x69,0x0A,0xAF,0xB6,0x15,0x82,0xA4,0x29,0x3C,0xC7,0x52,0x08,0xA2,0x22,0xCF,0x68,0x4B,0x2E,0xF0,0x8A,0xBD,0xA3,0x2C,0xAB,0x40,0x1B,0xCE,0xAA,0xB2,0x6C,0x82,0x40,0x4D,0x7D,0xC2,0x89,0x88,0x8A,0x61,0xCC,0x74,0xD5,0xFF,0x0F}; +uint8_t spELEVEN[] PROGMEM = {0xC3,0xCD,0x76,0x5C,0xAE,0x14,0x0F,0x37,0x9B,0x71,0xDE,0x92,0x55,0xBC,0x2C,0x27,0x70,0xD3,0x76,0xF0,0x83,0x5E,0xA3,0x5E,0x5A,0xC1,0xF7,0x61,0x58,0xA7,0x19,0x35,0x3F,0x99,0x31,0xDE,0x52,0x74,0xFC,0xA2,0x26,0x64,0x4B,0xD1,0xF1,0xAB,0xAE,0xD0,0x2D,0xC5,0xC7,0x2F,0x36,0xDD,0x27,0x15,0x0F,0x3F,0xD9,0x08,0x9F,0x62,0xE4,0xC2,0x2C,0xD4,0xD8,0xD3,0x89,0x0B,0x1B,0x57,0x11,0x0B,0x3B,0xC5,0xCF,0xD6,0xCC,0xC6,0x64,0x35,0xAF,0x18,0x73,0x1F,0xA1,0x5D,0xBC,0x62,0x45,0xB3,0x45,0x51,0xF0,0xA2,0x62,0xAB,0x4A,0x5B,0xC9,0x4B,0x8A,0x2D,0xB3,0x6C,0x06,0x2F,0x29,0xB2,0xAC,0x8A,0x18,0xBC,0x28,0xD9,0xAA,0xD2,0x92,0xF1,0xBC,0xE0,0x98,0x8C,0x48,0xCC,0x17,0x52,0xA3,0x27,0x6D,0x93,0xD0,0x4B,0x8E,0x0E,0x77,0x02,0x00,0xFF,0x0F}; +uint8_t spTWELVE[] PROGMEM = {0x06,0x28,0x46,0xD3,0x01,0x25,0x06,0x13,0x20,0xBA,0x70,0x70,0xB6,0x79,0xCA,0x36,0xAE,0x28,0x38,0xE1,0x29,0xC5,0x35,0xA3,0xE6,0xC4,0x16,0x6A,0x53,0x8C,0x97,0x9B,0x72,0x86,0x4F,0x28,0x1A,0x6E,0x0A,0x59,0x36,0xAE,0x68,0xF8,0x29,0x67,0xFA,0x06,0xA3,0x16,0xC4,0x96,0xE6,0x53,0xAC,0x5A,0x9C,0x56,0x72,0x77,0x31,0x4E,0x49,0x5C,0x8D,0x5B,0x29,0x3B,0x24,0x61,0x1E,0x6C,0x9B,0x6C,0x97,0xF8,0xA7,0x34,0x19,0x92,0x4C,0x62,0x9E,0x72,0x65,0x58,0x12,0xB1,0x7E,0x09,0xD5,0x2E,0x53,0xC5,0xBA,0x36,0x6B,0xB9,0x2D,0x17,0x05,0xEE,0x9A,0x6E,0x8E,0x05,0x50,0x6C,0x19,0x07,0x18,0x50,0xBD,0x3B,0x01,0x92,0x08,0x41,0x40,0x10,0xA6,0xFF,0x0F}; +uint8_t spTHIRTEEN[] PROGMEM = {0x08,0xE8,0x2C,0x15,0x01,0x43,0x07,0x13,0xE0,0x98,0xB4,0xA6,0x35,0xA9,0x1E,0xDE,0x56,0x8E,0x53,0x9C,0x7A,0xE7,0xCA,0x5E,0x76,0x8D,0x94,0xE5,0x2B,0xAB,0xD9,0xB5,0x62,0xA4,0x9C,0xE4,0xE6,0xB4,0x41,0x1E,0x7C,0xB6,0x93,0xD7,0x16,0x99,0x5A,0xCD,0x61,0x76,0x55,0xC2,0x91,0x61,0x1B,0xC0,0x01,0x5D,0x85,0x05,0xE0,0x68,0x51,0x07,0x1C,0xA9,0x64,0x80,0x1D,0x4C,0x9C,0x95,0x88,0xD4,0x04,0x3B,0x4D,0x4E,0x21,0x5C,0x93,0xA8,0x26,0xB9,0x05,0x4B,0x6E,0xA0,0xE2,0xE4,0x57,0xC2,0xB9,0xC1,0xB2,0x93,0x5F,0x09,0xD7,0x24,0xCB,0x4E,0x41,0x25,0x54,0x1D,0x62,0x3B,0x05,0x8D,0x52,0x57,0xAA,0xAD,0x10,0x24,0x26,0xE3,0xE1,0x36,0x5D,0x10,0x85,0xB4,0x97,0x85,0x72,0x41,0x14,0x52,0x5E,0x1A,0xCA,0xF9,0x91,0x6B,0x7A,0x5B,0xC4,0xE0,0x17,0x2D,0x54,0x1D,0x92,0x8C,0x1F,0x25,0x4B,0x8F,0xB2,0x16,0x41,0xA1,0x4A,0x3E,0xE6,0xFA,0xFF,0x01}; +uint8_t spFOURTEEN[] PROGMEM = {0x0C,0x58,0xAE,0x5C,0x01,0xD9,0x87,0x07,0x51,0xB7,0x25,0xB3,0x8A,0x15,0x2C,0xF7,0x1C,0x35,0x87,0x4D,0xB2,0xDD,0x53,0xCE,0x28,0x2B,0xC9,0x0E,0x97,0x2D,0xBD,0x2A,0x17,0x27,0x76,0x8E,0xD2,0x9A,0x6C,0x80,0x94,0x71,0x00,0x00,0x02,0xB0,0x58,0x58,0x00,0x9E,0x0B,0x0A,0xC0,0xB2,0xCE,0xC1,0xC8,0x98,0x7A,0x52,0x95,0x24,0x2B,0x11,0xED,0x36,0xD4,0x92,0xDC,0x4C,0xB5,0xC7,0xC8,0x53,0xF1,0x2A,0xE5,0x1A,0x17,0x55,0xC5,0xAF,0x94,0xBB,0xCD,0x1C,0x26,0xBF,0x52,0x9A,0x72,0x53,0x98,0xFC,0xC2,0x68,0xD2,0x4D,0x61,0xF0,0xA3,0x90,0xB6,0xD6,0x50,0xC1,0x8F,0x42,0xDA,0x4A,0x43,0x39,0x3F,0x48,0x2D,0x6B,0x33,0xF9,0xFF}; +uint8_t spFIFTEEN[] PROGMEM = {0x08,0xE8,0x2A,0x0D,0x01,0xDD,0xBA,0x31,0x60,0x6A,0xF7,0xA0,0xAE,0x54,0xAA,0x5A,0x76,0x97,0xD9,0x34,0x69,0xEF,0x32,0x1E,0x66,0xE1,0xE2,0xB3,0x43,0xA9,0x18,0x55,0x92,0x4E,0x37,0x2D,0x67,0x6F,0xDF,0xA2,0x5A,0xB6,0x04,0x30,0x55,0xA8,0x00,0x86,0x09,0xE7,0x00,0x01,0x16,0x17,0x05,0x70,0x40,0x57,0xE5,0x01,0xF8,0x21,0x34,0x00,0xD3,0x19,0x33,0x80,0x89,0x9A,0x62,0x34,0x4C,0xD5,0x49,0xAE,0x8B,0x53,0x09,0xF7,0x26,0xD9,0x6A,0x7E,0x23,0x5C,0x13,0x12,0xB3,0x04,0x9D,0x50,0x4F,0xB1,0xAD,0x14,0x15,0xC2,0xD3,0xA1,0xB6,0x42,0x94,0xA8,0x8C,0x87,0xDB,0x74,0xB1,0x70,0x59,0xE1,0x2E,0xC9,0xC5,0x81,0x5B,0x55,0xA4,0x4C,0x17,0x47,0xC1,0x6D,0xE3,0x81,0x53,0x9C,0x84,0x6A,0x46,0xD9,0x4C,0x51,0x31,0x42,0xD9,0x66,0xC9,0x44,0x85,0x29,0x6A,0x9B,0xAD,0xFF,0x07}; +uint8_t spSIXTEEN[] PROGMEM = {0x0A,0x58,0x5A,0x5D,0x00,0x93,0x97,0x0B,0x60,0xA9,0x48,0x05,0x0C,0x15,0xAE,0x80,0xAD,0x3D,0x14,0x30,0x7D,0xD9,0x50,0x92,0x92,0xAC,0x0D,0xC5,0xCD,0x2A,0x82,0xAA,0x3B,0x98,0x04,0xB3,0x4A,0xC8,0x9A,0x90,0x05,0x09,0x68,0x51,0xD4,0x01,0x23,0x9F,0x1A,0x60,0xA9,0x12,0x03,0xDC,0x50,0x81,0x80,0x22,0xDC,0x20,0x00,0xCB,0x06,0x3A,0x60,0x16,0xE3,0x64,0x64,0x42,0xDD,0xCD,0x6A,0x8A,0x5D,0x28,0x75,0x07,0xA9,0x2A,0x5E,0x65,0x34,0xED,0x64,0xBB,0xF8,0x85,0xF2,0x94,0x8B,0xAD,0xE4,0x37,0x4A,0x5B,0x21,0xB6,0x52,0x50,0x19,0xAD,0xA7,0xD8,0x4A,0x41,0x14,0xDA,0x5E,0x12,0x3A,0x04,0x91,0x4B,0x7B,0x69,0xA8,0x10,0x24,0x2E,0xE5,0xA3,0x81,0x52,0x90,0x94,0x5A,0x55,0x98,0x32,0x41,0x50,0xCC,0x93,0x2E,0x47,0x85,0x89,0x1B,0x5B,0x5A,0x62,0x04,0x44,0xE3,0x02,0x80,0x80,0x64,0xDD,0xFF,0x1F}; +uint8_t spSEVENTEEN[] PROGMEM = {0x02,0x98,0x3A,0x42,0x00,0x5B,0xA6,0x09,0x60,0xDB,0x52,0x06,0x1C,0x93,0x29,0x80,0xA9,0x52,0x87,0x9A,0xB5,0x99,0x4F,0xC8,0x3E,0x46,0xD6,0x5E,0x7E,0x66,0xFB,0x98,0xC5,0x5A,0xC6,0x9A,0x9C,0x63,0x15,0x6B,0x11,0x13,0x8A,0x9C,0x97,0xB9,0x9A,0x5A,0x39,0x71,0xEE,0xD2,0x29,0xC2,0xA6,0xB8,0x58,0x59,0x99,0x56,0x14,0xA3,0xE1,0x26,0x19,0x19,0xE3,0x8C,0x93,0x17,0xB4,0x46,0xB5,0x88,0x71,0x9E,0x97,0x9E,0xB1,0x2C,0xC5,0xF8,0x56,0xC4,0x58,0xA3,0x1C,0xE1,0x33,0x9D,0x13,0x41,0x8A,0x43,0x58,0xAD,0x95,0xA9,0xDB,0x36,0xC0,0xD1,0xC9,0x0E,0x58,0x4E,0x45,0x01,0x23,0xA9,0x04,0x37,0x13,0xAE,0x4D,0x65,0x52,0x82,0xCA,0xA9,0x37,0x99,0x4D,0x89,0xBA,0xC0,0xBC,0x14,0x36,0x25,0xEA,0x1C,0x73,0x52,0x1D,0x97,0xB8,0x33,0xAC,0x0E,0x75,0x9C,0xE2,0xCE,0xB0,0xDA,0xC3,0x51,0x4A,0x1A,0xA5,0xCA,0x70,0x5B,0x21,0xCE,0x4C,0x26,0xD2,0x6C,0xBA,0x38,0x71,0x2E,0x1F,0x2D,0xED,0xE2,0x24,0xB8,0xBC,0x3D,0x52,0x88,0xAB,0x50,0x8E,0xA8,0x48,0x22,0x4E,0x42,0xA0,0x26,0x55,0xFD,0x3F}; +uint8_t spEIGHTEEN[] PROGMEM = {0x2E,0x9C,0xD1,0x4D,0x54,0xEC,0x2C,0xBF,0x1B,0x8A,0x99,0x70,0x7C,0xFC,0x2E,0x29,0x6F,0x52,0xF6,0xF1,0xBA,0x20,0xBF,0x36,0xD9,0xCD,0xED,0x0C,0xF3,0x27,0x64,0x17,0x73,0x2B,0xA2,0x99,0x90,0x65,0xEC,0xED,0x40,0x73,0x32,0x12,0xB1,0xAF,0x30,0x35,0x0B,0xC7,0x00,0xE0,0x80,0xAE,0xDD,0x1C,0x70,0x43,0xAA,0x03,0x86,0x51,0x36,0xC0,0x30,0x64,0xCE,0x4C,0x98,0xFB,0x5C,0x65,0x07,0xAF,0x10,0xEA,0x0B,0x66,0x1B,0xFC,0x46,0xA8,0x3E,0x09,0x4D,0x08,0x2A,0xA6,0x3E,0x67,0x36,0x21,0x2A,0x98,0x67,0x9D,0x15,0xA7,0xA8,0x60,0xEE,0xB6,0x94,0x99,0xA2,0x4A,0x78,0x22,0xC2,0xA6,0x8B,0x8C,0x8E,0xCC,0x4C,0x8A,0x2E,0x8A,0x4C,0xD3,0x57,0x03,0x87,0x28,0x71,0x09,0x1F,0x2B,0xE4,0xA2,0xC4,0xC5,0x6D,0xAD,0x54,0x88,0xB2,0x63,0xC9,0xF2,0x50,0x2E,0x8A,0x4A,0x38,0x4A,0xEC,0x88,0x28,0x08,0xE3,0x28,0x49,0xF3,0xFF}; +uint8_t spNINETEEN[] PROGMEM = {0xC2,0xEA,0x8A,0x95,0x2B,0x6A,0x05,0x3F,0x71,0x71,0x5F,0x0D,0x12,0xFC,0x28,0x25,0x62,0x35,0xF0,0xF0,0xB3,0x48,0x1E,0x0F,0xC9,0xCB,0x2F,0x45,0x7C,0x2C,0x25,0x1F,0xBF,0x14,0xB3,0x2C,0xB5,0x75,0xFC,0x5A,0x5C,0xA3,0x5D,0xE1,0xF1,0x7A,0x76,0xB3,0x4E,0x45,0xC7,0xED,0x96,0x23,0x3B,0x18,0x37,0x7B,0x18,0xCC,0x09,0x51,0x13,0x4C,0xAB,0x6C,0x4C,0x4B,0x96,0xD2,0x49,0xAA,0x36,0x0B,0xC5,0xC2,0x20,0x26,0x27,0x35,0x63,0x09,0x3D,0x30,0x8B,0xF0,0x48,0x5C,0xCA,0x61,0xDD,0xCB,0xCD,0x91,0x03,0x8E,0x4B,0x76,0xC0,0xCC,0x4D,0x06,0x98,0x31,0x31,0x98,0x99,0x70,0x6D,0x2A,0xA3,0xE4,0x16,0xCA,0xBD,0xCE,0x5C,0x92,0x57,0x28,0xCF,0x09,0x69,0x2E,0x7E,0xA5,0x3C,0x63,0xA2,0x30,0x05,0x95,0xD2,0x74,0x98,0xCD,0x14,0x54,0xCA,0x53,0xA9,0x96,0x52,0x50,0x28,0x6F,0xBA,0xCB,0x0C,0x41,0x50,0xDE,0x65,0x2E,0xD3,0x05,0x89,0x4B,0x7B,0x6B,0x20,0x17,0x44,0xAE,0xED,0x23,0x81,0x52,0x90,0x85,0x73,0x57,0xD0,0x72,0x41,0xB1,0x02,0xDE,0x2E,0xDB,0x04,0x89,0x05,0x79,0xBB,0x62,0xE5,0x76,0x11,0xCA,0x61,0x0E,0xFF,0x1F}; +uint8_t spTWENTY[] PROGMEM = {0x01,0x98,0xD1,0xC2,0x00,0xCD,0xA4,0x32,0x20,0x79,0x13,0x04,0x28,0xE7,0x92,0xDC,0x70,0xCC,0x5D,0xDB,0x76,0xF3,0xD2,0x32,0x0B,0x0B,0x5B,0xC3,0x2B,0xCD,0xD4,0xDD,0x23,0x35,0xAF,0x44,0xE1,0xF0,0xB0,0x6D,0x3C,0xA9,0xAD,0x3D,0x35,0x0E,0xF1,0x0C,0x8B,0x28,0xF7,0x34,0x01,0x68,0x22,0xCD,0x00,0xC7,0xA4,0x04,0xBB,0x32,0xD6,0xAC,0x56,0x9C,0xDC,0xCA,0x28,0x66,0x53,0x51,0x70,0x2B,0xA5,0xBC,0x0D,0x9A,0xC1,0xEB,0x14,0x73,0x37,0x29,0x19,0xAF,0x33,0x8C,0x3B,0xA7,0x24,0xBC,0x42,0xB0,0xB7,0x59,0x09,0x09,0x3C,0x96,0xE9,0xF4,0x58,0xFF,0x0F}; +uint8_t spTHIRTY[] PROGMEM = {0x08,0x98,0xD6,0x15,0x01,0x43,0xBB,0x0A,0x20,0x1B,0x8B,0xE5,0x16,0xA3,0x1E,0xB6,0xB6,0x96,0x97,0x3C,0x57,0xD4,0x2A,0x5E,0x7E,0x4E,0xD8,0xE1,0x6B,0x7B,0xF8,0x39,0x63,0x0D,0x9F,0x95,0xE1,0xE7,0x4C,0x76,0xBC,0x91,0x5B,0x90,0x13,0xC6,0x68,0x57,0x4E,0x41,0x8B,0x10,0x5E,0x1D,0xA9,0x44,0xD3,0xBA,0x47,0xB8,0xDD,0xE4,0x35,0x86,0x11,0x93,0x94,0x92,0x5F,0x29,0xC7,0x4C,0x30,0x0C,0x41,0xC5,0x1C,0x3B,0x2E,0xD3,0x05,0x15,0x53,0x6C,0x07,0x4D,0x15,0x14,0x8C,0xB5,0xC9,0x6A,0x44,0x90,0x10,0x4E,0x9A,0xB6,0x21,0x81,0x23,0x3A,0x91,0x91,0xE8,0xFF,0x01}; +uint8_t spFOURTY[] PROGMEM = {0x04,0x18,0xB6,0x4C,0x00,0xC3,0x56,0x30,0xA0,0xE8,0xF4,0xA0,0x98,0x99,0x62,0x91,0xAE,0x83,0x6B,0x77,0x89,0x78,0x3B,0x09,0xAE,0xBD,0xA6,0x1E,0x63,0x3B,0x79,0x7E,0x71,0x5A,0x8F,0x95,0xE6,0xA5,0x4A,0x69,0xB9,0x4E,0x8A,0x5F,0x12,0x56,0xE4,0x58,0x69,0xE1,0x36,0xA1,0x69,0x2E,0x2B,0xF9,0x95,0x93,0x55,0x17,0xED,0xE4,0x37,0xC6,0xBA,0x93,0xB2,0x92,0xDF,0x19,0xD9,0x6E,0xC8,0x0A,0xFE,0x60,0xE8,0x37,0x21,0xC9,0xF9,0x8D,0x61,0x5F,0x32,0x13,0xE7,0x17,0x4C,0xD3,0xC6,0xB1,0x94,0x97,0x10,0x8F,0x8B,0xAD,0x11,0x7E,0xA1,0x9A,0x26,0x92,0xF6,0xFF,0x01}; +uint8_t spFIFTY[] PROGMEM = {0x08,0xE8,0x2E,0x84,0x00,0x23,0x84,0x13,0x60,0x38,0x95,0xA5,0x0F,0xCF,0xE2,0x79,0x8A,0x8F,0x37,0x02,0xB3,0xD5,0x2A,0x6E,0x5E,0x93,0x94,0x79,0x45,0xD9,0x05,0x5D,0x0A,0xB9,0x97,0x63,0x02,0x74,0xA7,0x82,0x80,0xEE,0xC3,0x10,0xD0,0x7D,0x28,0x03,0x6E,0x14,0x06,0x70,0xE6,0x0A,0xC9,0x9A,0x4E,0x37,0xD9,0x95,0x51,0xCE,0xBA,0xA2,0x14,0x0C,0x81,0x36,0x1B,0xB2,0x5C,0x30,0x38,0xFA,0x9C,0xC9,0x32,0x41,0xA7,0x18,0x3B,0xA2,0x48,0x04,0x05,0x51,0x4F,0x91,0x6D,0x12,0x04,0x20,0x9B,0x61,0x89,0xFF,0x1F}; +uint8_t spGOOD[] PROGMEM = {0x0A,0x28,0xCD,0x34,0x20,0xD9,0x1A,0x45,0x74,0xE4,0x66,0x24,0xAD,0xBA,0xB1,0x8C,0x9B,0x91,0xA5,0x64,0xE6,0x98,0x21,0x16,0x0B,0x96,0x9B,0x4C,0xE5,0xFF,0x01}; +uint8_t spMORNING[] PROGMEM = {0xCE,0x08,0x52,0x2A,0x35,0x5D,0x39,0x53,0x29,0x5B,0xB7,0x0A,0x15,0x0C,0xEE,0x2A,0x42,0x56,0x66,0xD2,0x55,0x2E,0x37,0x2F,0xD9,0x45,0xB3,0xD3,0xC5,0xCA,0x6D,0x27,0xD5,0xEE,0x50,0xF5,0x50,0x94,0x14,0x77,0x2D,0xD8,0x5D,0x49,0x92,0xFD,0xB1,0x64,0x2F,0xA9,0x49,0x0C,0x93,0x4B,0xAD,0x19,0x17,0x3E,0x66,0x1E,0xF1,0xA2,0x5B,0x84,0xE2,0x29,0x8F,0x8B,0x72,0x10,0xB5,0xB1,0x2E,0x4B,0xD4,0x45,0x89,0x4A,0xEC,0x5C,0x95,0x14,0x2B,0x8A,0x9C,0x34,0x52,0x5D,0xBC,0xCC,0xB5,0x3B,0x49,0x69,0x89,0x87,0xC1,0x98,0x56,0x3A,0x21,0x2B,0x82,0x67,0xCC,0x5C,0x85,0xB5,0x4A,0x8A,0xF6,0x64,0xA9,0x96,0xC4,0x69,0x3C,0x52,0x81,0x58,0x1C,0x97,0xF6,0x0E,0x1B,0xCC,0x0D,0x42,0x32,0xAA,0x65,0x12,0x67,0xD4,0x6A,0x61,0x52,0xFC,0xFF}; +uint8_t spAFTERNOON[] PROGMEM = {0xC7,0xCE,0xCE,0x3A,0xCB,0x58,0x1F,0x3B,0x07,0x9D,0x28,0x71,0xB4,0xAC,0x9C,0x74,0x5A,0x42,0x55,0x33,0xB2,0x93,0x0A,0x09,0xD4,0xC5,0x9A,0xD6,0x44,0x45,0xE3,0x38,0x60,0x9A,0x32,0x05,0xF4,0x18,0x01,0x09,0xD8,0xA9,0xC2,0x00,0x5E,0xCA,0x24,0xD5,0x5B,0x9D,0x4A,0x95,0xEA,0x34,0xEE,0x63,0x92,0x5C,0x4D,0xD0,0xA4,0xEE,0x58,0x0C,0xB9,0x4D,0xCD,0x42,0xA2,0x3A,0x24,0x37,0x25,0x8A,0xA8,0x8E,0xA0,0x53,0xE4,0x28,0x23,0x26,0x13,0x72,0x91,0xA2,0x76,0xBB,0x72,0x38,0x45,0x0A,0x46,0x63,0xCA,0x69,0x27,0x39,0x58,0xB1,0x8D,0x60,0x1C,0x34,0x1B,0x34,0xC3,0x55,0x8E,0x73,0x45,0x2D,0x4F,0x4A,0x3A,0x26,0x10,0xA1,0xCA,0x2D,0xE9,0x98,0x24,0x0A,0x1E,0x6D,0x97,0x29,0xD2,0xCC,0x71,0xA2,0xDC,0x86,0xC8,0x12,0xA7,0x8E,0x08,0x85,0x22,0x8D,0x9C,0x43,0xA7,0x12,0xB2,0x2E,0x50,0x09,0xEF,0x51,0xC5,0xBA,0x28,0x58,0xAD,0xDB,0xE1,0xFF,0x03}; +uint8_t spEVENING[] PROGMEM = {0xCD,0x6D,0x98,0x73,0x47,0x65,0x0D,0x6D,0x10,0xB2,0x5D,0x93,0x35,0x94,0xC1,0xD0,0x76,0x4D,0x66,0x93,0xA7,0x04,0xBD,0x71,0xD9,0x45,0xAE,0x92,0xD5,0xAC,0x53,0x07,0x6D,0xA5,0x76,0x63,0x51,0x92,0xD4,0xA1,0x83,0xD4,0xCB,0xB2,0x51,0x88,0xCD,0xF5,0x50,0x45,0xCE,0xA2,0x2E,0x27,0x28,0x54,0x15,0x37,0x0A,0xCF,0x75,0x61,0x5D,0xA2,0xC4,0xB5,0xC7,0x44,0x55,0x8A,0x0B,0xA3,0x6E,0x17,0x95,0x21,0xA9,0x0C,0x37,0xCD,0x15,0xBA,0xD4,0x2B,0x6F,0xB3,0x54,0xE4,0xD2,0xC8,0x64,0xBC,0x4C,0x91,0x49,0x12,0xE7,0xB2,0xB1,0xD0,0x22,0x0D,0x9C,0xDD,0xAB,0x62,0xA9,0x38,0x53,0x11,0xA9,0x74,0x2C,0xD2,0xCA,0x59,0x34,0xA3,0xE5,0xFF,0x03}; +uint8_t spPAUSE1[] PROGMEM = {0x00,0x00,0x00,0x00,0xFF,0x0F}; + +void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) ; + +void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) { + TTGO_PWR_ON + talkie = new AudioGeneratorTalkie(); + talkie->begin(nullptr, out); + + bool pm = (hour >= 12); + uint8_t *spHour[] = { spTWELVE, spONE, spTWO, spTHREE, spFOUR, spFIVE, spSIX, + spSEVEN, spEIGHT, spNINE, spTEN, spELEVEN }; + size_t spHourLen[] = { sizeof(spTWELVE), sizeof(spONE), sizeof(spTWO), + sizeof(spTHREE), sizeof(spFOUR), sizeof(spFIVE), + sizeof(spSIX), sizeof(spSEVEN), sizeof(spEIGHT), + sizeof(spNINE), sizeof(spTEN), sizeof(spELEVEN) }; + uint8_t *spMinDec[] = { spOH, spTEN, spTWENTY, spTHIRTY, spFOURTY, spFIFTY }; + size_t spMinDecLen[] = { sizeof(spOH), sizeof(spTEN), sizeof(spTWENTY), + sizeof(spTHIRTY), sizeof(spFOURTY), sizeof(spFIFTY) }; + uint8_t *spMinSpecial[] = { spELEVEN, spTWELVE, spTHIRTEEN, spFOURTEEN, + spFIFTEEN, spSIXTEEN, spSEVENTEEN, spEIGHTEEN, + spNINETEEN }; + size_t spMinSpecialLen[] = { sizeof(spELEVEN), sizeof(spTWELVE), + sizeof(spTHIRTEEN), sizeof(spFOURTEEN), + sizeof(spFIFTEEN), sizeof(spSIXTEEN), + sizeof(spSEVENTEEN), sizeof(spEIGHTEEN), + sizeof(spNINETEEN) }; + uint8_t *spMinLow[] = { spONE, spTWO, spTHREE, spFOUR, spFIVE, spSIX, + spSEVEN, spEIGHT, spNINE }; + size_t spMinLowLen[] = { sizeof(spONE), sizeof(spTWO), sizeof(spTHREE), + sizeof(spFOUR), sizeof(spFIVE), sizeof(spSIX), + sizeof(spSEVEN), sizeof(spEIGHT), sizeof(spNINE) }; + + talkie->say(spTHE, sizeof(spTHE)); + talkie->say(spTIME, sizeof(spTIME)); + talkie->say(spIS, sizeof(spIS)); + + hour = hour % 12; + talkie->say(spHour[hour], spHourLen[hour]); + if (minutes==0) { + talkie->say(spOCLOCK, sizeof(spOCLOCK)); + } else if (minutes<=10 || minutes >=20) { + talkie->say(spMinDec[minutes / 10], spMinDecLen[minutes /10]); + if (minutes % 10) { + talkie->say(spMinLow[(minutes % 10) - 1], spMinLowLen[(minutes % 10) - 1]); + } + } else { + talkie->say(spMinSpecial[minutes - 11], spMinSpecialLen[minutes - 11]); + } + if (pm) { + talkie->say(spP_M_, sizeof(spP_M_)); + } else { + talkie->say(spA_M_, sizeof(spA_M_)); + } + out->stop(); + delete talkie; + TTGO_PWR_OFF +} +#endif + + +uint8_t is2_volume; + +void I2S_Init(void) { + +#if EXTERNAL_DAC_PLAY + out = new AudioOutputI2S(); +#ifdef ESP32 + out->SetPinout(TWATCH_DAC_IIS_BCK, TWATCH_DAC_IIS_WS, TWATCH_DAC_IIS_DOUT); +#endif +#else + out = new AudioOutputI2S(0, 1); +#endif + + is2_volume=10; + out->SetGain(((float)is2_volume/100.0)*4.0); + out->stop(); + mp3ram = nullptr; + +#ifdef ESP32 + if (psramFound()) { + mp3ram = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + } + +#ifdef USE_WEBRADIO + if (psramFound()) { + preallocateBuffer = heap_caps_malloc(preallocateBufferSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + preallocateCodec = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + } else { + preallocateBuffer = malloc(preallocateBufferSize); + preallocateCodec = malloc(preallocateCodecSize); + } + if (!preallocateBuffer || !preallocateCodec) { + + } +#endif +#endif +} + +#ifdef ESP32 +TaskHandle_t mp3_task_h; + +void mp3_task(void *arg) { + while (1) { + while (mp3->isRunning()) { + if (!mp3->loop()) { + mp3->stop(); + mp3_delete(); + if (mp3_task_h) { + vTaskDelete(mp3_task_h); + mp3_task_h = 0; + } + + } + delay(1); + } + } +} +#endif + +#ifdef USE_WEBRADIO +void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str) { + const char *ptr = reinterpret_cast(cbData); + (void) isUnicode; + (void) ptr; + if (strstr_P(type, PSTR("Title"))) { + strncpy(wr_title, str, sizeof(wr_title)); + wr_title[sizeof(wr_title)-1] = 0; + + } else { + + } +} + +void StatusCallback(void *cbData, int code, const char *string) { + const char *ptr = reinterpret_cast(cbData); + (void) code; + (void) ptr; + + +} + +void Webradio(const char *url) { + if (decoder || mp3) return; + TTGO_PWR_ON + ifile = new AudioFileSourceICYStream(url); + ifile->RegisterMetadataCB(MDCallback, NULL); + buff = new AudioFileSourceBuffer(ifile, preallocateBuffer, preallocateBufferSize); + buff->RegisterStatusCB(StatusCallback, NULL); + decoder = new AudioGeneratorMP3(preallocateCodec, preallocateCodecSize); + decoder->RegisterStatusCB(StatusCallback, NULL); + decoder->begin(buff, out); + if (!decoder->isRunning()) { + + StopPlaying(); + + retryms = millis() + 2000; + } + + xTaskCreatePinnedToCore(mp3_task2, "MP3-2", I2SAUDIO_TASK_STACK_SIZE, NULL, 3, &mp3_task_h, 1); +} + +void mp3_task2(void *arg){ + while (1) { + if (decoder && decoder->isRunning()) { + if (!decoder->loop()) { + StopPlaying(); + + } + delay(1); + } + } +} + +void StopPlaying() { + + if (mp3_task_h) { + vTaskDelete(mp3_task_h); + mp3_task_h = nullptr; + } + + if (decoder) { + decoder->stop(); + delete decoder; + decoder = NULL; + } + if (buff) { + buff->close(); + delete buff; + buff = NULL; + } + if (ifile) { + ifile->close(); + delete ifile; + ifile = NULL; + } + TTGO_PWR_OFF +} + +void Cmd_WebRadio(void) { + if (decoder) { + StopPlaying(); + } + if (XdrvMailbox.data_len > 0) { + Webradio(XdrvMailbox.data); + ResponseCmndChar(XdrvMailbox.data); + } else { + ResponseCmndChar_P(PSTR("Stopped")); + } + +} + +const char HTTP_WEBRADIO[] PROGMEM = + "{s}" "I2S_WR-Title" "{m}%s{e}"; + +void I2S_WR_Show(void) { + if (decoder) { + WSContentSend_PD(HTTP_WEBRADIO,wr_title); + } +} + +#endif + +#ifdef ESP32 +void Play_mp3(const char *path) { +#if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS) + if (decoder || mp3) return; + + bool I2S_Task; + + TTGO_PWR_ON + if (*path=='+') { + I2S_Task = true; + path++; + } else { + I2S_Task = false; + } + + file = new AudioFileSourceFS(*fsp,path); + if (file->isOpen()) { + id3 = new AudioFileSourceID3(file); + + if (mp3ram) { + mp3 = new AudioGeneratorMP3(mp3ram, preallocateCodecSize); + } else { + mp3 = new AudioGeneratorMP3(); + } + mp3->begin(id3, out); + + if (I2S_Task) { + xTaskCreatePinnedToCore(mp3_task, "MP3", I2SAUDIO_TASK_STACK_SIZE, NULL, 3, &mp3_task_h, 1); + } else { + while (mp3->isRunning()) { + if (!mp3->loop()) { + mp3->stop(); + mp3_delete(); + break; + } + OsWatchLoop(); + } + } + } + +#endif +} + +void mp3_delete(void) { + delete file; + delete id3; + delete mp3; + mp3=nullptr; + TTGO_PWR_OFF +} +#endif + +void Say(char *text) { + + TTGO_PWR_ON + + out->begin(); + ESP8266SAM *sam = new ESP8266SAM; + sam->Say(out, text); + delete sam; + out->stop(); + + TTGO_PWR_OFF +} + + +const char kI2SAudio_Commands[] PROGMEM = "I2S|" + "Say|Gain|Time" +#ifdef ESP32 + "|Play" +#ifdef USE_WEBRADIO + "|WR" +#endif +#endif + ; + +void (* const I2SAudio_Command[])(void) PROGMEM = { + &Cmd_Say, &Cmd_Gain, &Cmd_Time +#ifdef ESP32 + ,&Cmd_Play +#ifdef USE_WEBRADIO + ,&Cmd_WebRadio +#endif +#endif +}; + + + +void Cmd_Play(void) { + if (XdrvMailbox.data_len > 0) { + Play_mp3(XdrvMailbox.data); + } + ResponseCmndChar(XdrvMailbox.data); +} + +void Cmd_Gain(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + if (out) { + is2_volume=XdrvMailbox.payload; + out->SetGain(((float)(is2_volume-2)/100.0)*4.0); + } + } + ResponseCmndNumber(is2_volume); +} + +void Cmd_Say(void) { + if (XdrvMailbox.data_len > 0) { + Say(XdrvMailbox.data); + } + ResponseCmndChar(XdrvMailbox.data); +} + +void Cmd_Time(void) { +#ifdef SAY_TIME + sayTime(RtcTime.hour, RtcTime.minute, talkie); +#endif + ResponseCmndDone(); +} + + + + + +bool Xdrv42(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kI2SAudio_Commands, I2SAudio_Command); + break; + case FUNC_INIT: + I2S_Init(); + break; +#ifdef USE_WEBSERVER +#ifdef USE_WEBRADIO + case FUNC_WEB_SENSOR: + I2S_WR_Show(); + break; +#endif +#endif + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_43_mlx90640.ino" +# 26 "/workspace/Tasmota/tasmota/xdrv_43_mlx90640.ino" +#ifdef USE_I2C +#ifdef USE_MLX90640 + +#define MLX90640_ADDRESS 0x33 +#define MLX90640_POI_NUM 6 + + + + + +#define XDRV_43 43 +#define XI2C_53 53 +#include + +const char MLX90640type[] PROGMEM = "MLX90640"; + +#ifdef USE_WEBSERVER +#define WEB_HANDLE_MLX90640 "mlx" +const char HTTP_BTN_MENU_MLX90640[] PROGMEM = "

"; +#endif + +struct { + uint32_t type:1; + uint32_t ready:1; + uint32_t dumpedEE:1; + uint32_t extractedParams:1; + paramsMLX90640 *params; + float Ta; + uint16_t Frame[834]; + float To[768]; + uint8_t pois[2*MLX90640_POI_NUM] = {2,1, 30,1, 10,12, 22,12, 2,23, 30,23}; +} MLX90640; + + + + + +#define D_CMND_MLX90640 "MLX" + +const char S_JSON_MLX90640_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\":%d}"; +const char S_JSON_MLX90640_COMMAND[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\"}"; +const char kMLX90640_Commands[] PROGMEM = "POI"; + +enum MLX90640_Commands { + CMND_MLX90640_POI + }; + + + + +#ifdef USE_WEBSERVER + +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_MLX90640_1_SNS_SIZE = 389; +const char HTTP_MLX90640_1_SNS_COMPRESSED[] PROGMEM = "\x3D\x3C\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xDD\x33\x65\x1D\x86\xBB\x33\xB0\x41" + "\xA4\x7D\x9F\x81\xE7\x7A\x90\xDB\x18\x7C\x3B\xA6\x76\x10\xB6\x75\x1B\x0E\x43\xA8" + "\x8C\x8E\x43\xA8\x8D\x87\x28\xEA\x23\x23\x94\x77\x8F\x87\xE1\x02\x0D\x13\xAC\xD8" + "\x72\x1D\xE3\xD6\x77\x48\xC8\xE5\x1D\x64\x6C\x39\x47\x78\xEC\x3B\xA4\x64\x72\x1D" + "\x64\x6C\x39\x0E\xF1\xDB\x23\x61\xCA\x3C\x10\x20\xE3\x3A\x36\xC7\x9A\x3E\x2E\x63" + "\xE8\xB4\x6D\x8F\x33\xC1\x9D\xFD\x07\x7C\x67\x7E\x3A\x83\xA3\x61\xD4\x3D\xF1\x0F" + "\x06\x77\xF4\x3C\x43\x0D\x87\x50\xCC\xD3\xE1\xEF\x1E\xF9\xE0\xCE\xFE\xBE\x56\x7C" + "\x3D\xE3\xDF\x3C\x18\x17\xC1\xD6\xE7\x21\xE7\x44\x37\x05\xF9\x90\xCC\xF1\xDD\x04" + "\x2C\x65\x33\x3A\x3B\xC8\xF6\x82\x0E\x87\xF6\x1D\x23\xE0\x21\x66\x87\x41\xE7\x44" + "\x3B\x05\xF0\x9B\xC3\xC4\x18\x5A\xFA\x8B\xEC\x3A\x3B\xA7\x78\xF0\x67\x7F\x46\xC4" + "\x7C\x4C\xCE\x8E\x81\x85\xAF\xA8\x8D\x87\x5F\xD8\x74\x74\x09\x98\xA3\xC6\x98\x3B" + "\xA6\xC3\xF0\xE5\xD3\x3B\xC7\xB4\x8D\x87\xC3\x97\x11\xE0\xF7\x17\xDD\x0B\xFF\x23" + "\xDA\x6C\x3C\xD1\x0D\xBA\x14\x74\x30\x16\x67\xCE\xE8\xDB\x18\x77\x4D\x87\x51\xC6" + "\x75\x5D\x33\xA9\x9D\x57\x0E\x88\xEF\x1D\xE3\xA8\x8C\x81\x32\xF9\xDD\x04\x5D\x04" + "\x8C\x91\xD6\xBE\xC3\xA3\xA5\x60\xC3\xBC\x75\x1C\x67\x55\x63\x3A\x99\xD5\x56\x74" + "\x47\x78\xEF\x1E\xE3\xC1\xEE"; +#define HTTP_MLX90640_1_SNS Decompress(HTTP_MLX90640_1_SNS_COMPRESSED,HTTP_MLX90640_1_SNS_SIZE).c_str() +#else +const char HTTP_MLX90640_1_SNS[] PROGMEM = + "" +; +#endif +#ifdef USE_UNISHOX_COMPRESSION +const size_t HTTP_MLX90640_4b_SNS_SIZE = 418; +const char HTTP_MLX90640_4b_SNS_COMPRESSED[] PROGMEM = "\x3D\x07\x60\x86\x4B\x38\x2C\xB1\x0F\x87\xDF\x9D\x0B\x18\x77\x4E\xF1\xE0\xFB\x3F" + "\x0F\x40\xEF\x8C\xEF\xCB\x44\x3E\x1F\x63\x42\x36\x1F\x68\x7F\x44\xA1\x47\xC3\xEC" + "\xE5\xE3\x3E\xCE\xE1\x0A\x7A\x3C\x2A\x2B\x8F\x87\xD9\xCA\xC6\x7D\x9F\x87\xA1\xD8" + "\x40\x83\x83\x9F\x87\xA0\x9A\x66\x7E\x1E\x87\x60\x9A\x66\x7E\x1E\x9E\x61\x30\xE9" + "\x68\x87\xC3\xEC\x66\x69\x04\x7D\xAC\xE0\xC5\x5F\x0F\x33\xE1\xF6\x37\x3C\x77\x4E" + "\xF1\xF6\x7E\x1E\x98\x32\xB7\x39\x19\xD8\x42\xD9\xF0\xFB\x38\xCF\xB3\xF0\x88\x61" + "\x61\x69\xD6\x72\x1E\x87\x61\x02\x0D\x40\x4B\xB8\x72\x10\x20\xDC\x39\x44\x0A\x77" + "\x0E\x51\x02\x0D\xC3\x96\x40\xA7\x70\xE5\x90\x20\xDC\x39\x84\x0A\x77\x0E\x61\x02" + "\x0D\xC3\x9A\x40\xA7\x70\xE6\x90\x20\xDC\x39\xC4\x08\xB7\x0E\xC0\x41\xE1\x2A\x01" + "\xFC\x3D\x04\xD3\x30\x41\xE2\x0C\xE4\x3E\xC8\x10\xF8\x5B\x13\x4C\xCF\xC2\x18\x58" + "\x5A\x75\x9C\x67\x99\xDC\x3D\x0B\xC3\x2F\x96\x88\x7C\x3E\xEC\xE4\x3E\xCF\xC3\xD0" + "\xEC\x2F\x0C\xBE\x3F\x26\x3B\x32\xF2\x0D\x1D\xDF\x3E\xF6\x7C\xEF\x02\x2E\x1E\x08" + "\x39\x11\xCA\x20\x44\xC8\x8E\xC1\xD8\x21\x91\xF8"; +#define HTTP_MLX90640_4b_SNS Decompress(HTTP_MLX90640_4b_SNS_COMPRESSED,HTTP_MLX90640_4b_SNS_SIZE).c_str() +#else +const char HTTP_MLX90640_4b_SNS[] PROGMEM = + "" + "" + "
" + "" + "
" + "
POI-0: °C (sensor)
" + "
" + "" + ; +#endif +void MLX90640UpdateGUI(void){ + WSContentStart_P("mlx"); + WSContentSendStyle(); + WSContentSend_P(HTTP_MLX90640_1_SNS); + WSContentSend_P(HTTP_MLX90640_2a_SNS); + WSContentSend_P(HTTP_MLX90640_2b_SNS); + WSContentSend_P(HTTP_MLX90640_3a_SNS); + WSContentSend_P(HTTP_MLX90640_3b_SNS); + WSContentSend_P(HTTP_MLX90640_4a_SNS); + WSContentSend_P(HTTP_MLX90640_4b_SNS); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + +void MLX90640HandleWebGuiResponse(void){ + char tmp[(MLX90640_POI_NUM*2)+4]; + WebGetArg("ul", tmp, sizeof(tmp)); + if (strlen(tmp)) { + uint8_t _line = atoi(tmp); + + float _buf[65]; + if(_line==0){_buf[0]=1000+MLX90640.Ta;} + else{_buf[0]=(float)_line;} + memcpy((char*)&_buf[1],(char*)&MLX90640.To[_line*64],64*4); + Webserver->send(200,PSTR("application/octet-stream"),(const char*)&_buf,65*4); + return; + } + WebGetArg("up", tmp, sizeof(tmp)); + if (strlen(tmp)==1) { + Webserver->send(200,PSTR("application/octet-stream"),(const char*)&MLX90640.pois,MLX90640_POI_NUM*2); + return; + } + else if (strlen(tmp)>2) { + uint32_t _poi = atoi(tmp); + uint32_t _poiNum = (_poi-(_poi%10000))/10000; + MLX90640.pois[_poiNum*2] = (_poi%10000)/100; + MLX90640.pois[(_poiNum*2)+1] = _poi%100; + + for(int i = 0;i(MLX90640_POI_NUM-1)&&XdrvMailbox.index<1) return false; + _idx = (XdrvMailbox.index-1)*2; + if (XdrvMailbox.data_len > 0) { + uint32_t _coord = TextToInt(XdrvMailbox.data); + MLX90640.pois[_idx] = (_coord%10000)/100; + if(MLX90640.pois[_idx]>31) MLX90640.pois[_idx]=31; + MLX90640.pois[_idx+1] = _coord%100; + if(MLX90640.pois[_idx+1]>23) MLX90640.pois[_idx+1]=23; + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("POI-%u = x:%u,y:%u"),XdrvMailbox.index,MLX90640.pois[_idx],MLX90640.pois[_idx+1]); + Response_P(S_JSON_MLX90640_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + +void MLX90640init() +{ + if (MLX90640.type || !I2cSetDevice(MLX90640_ADDRESS)) { return; } + + Wire.setClock(400000); + int status = -1; + if(!MLX90640.dumpedEE){ + status = MLX90640_DumpEE(MLX90640_ADDRESS, MLX90640.Frame); + if (status != 0){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("Failed to load system parameters")); + } + else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("MLX90640: started")); + MLX90640.type = true; + } + MLX90640.params = new paramsMLX90640; + } +} + + + + +void MLX90640every100msec(){ + static uint32_t _job = 0; + int status; + uint32_t _time; + + if(!MLX90640.extractedParams){ + static uint32_t _chunk = 0; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: will read chunk: %u"), _chunk); + _time = millis(); + status = MLX90640_ExtractParameters(MLX90640.Frame, MLX90640.params, _chunk); + if (status == 0){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: parameter received after: %u msec, status: %u"), TimePassedSince(_time), status); + } + if (_chunk == 5) MLX90640.extractedParams = true; + _chunk++; + return; + } + + switch(_job){ + case 0: + if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ + _job=-1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: frame not ready")); + break; + } + + status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); + + break; + case 1: + MLX90640.Ta = MLX90640_GetTa(MLX90640.Frame, MLX90640.params); + break; + case 2: + + MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 0); + + break; + case 5: + if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ + _job=4; + break; + } + + status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); + + break; + case 7: + + MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 1); + + break; + default: + break; + } + _job++; + if(_job>10) _job=0; +} + + + + + + +void MLX90640Show(uint8_t json) +{ + char amb_tstr[FLOATSZ]; + dtostrfd(MLX90640.Ta, Settings.flag2.temperature_resolution, amb_tstr); + if (json) { + ResponseAppend_P(PSTR(",\"MLX90640\":{\"" D_JSON_TEMPERATURE "\":[%s"), amb_tstr); + for(int i = 0;i + + +struct miel_hvac_header { + uint8_t start; +#define MIEL_HVAC_H_START 0xfc + uint8_t type; +#define MIEL_HVAC_H_TYPE_UPDATED 0x61 +#define MIEL_HVAC_H_TYPE_DATA 0x62 +#define MIEL_HVAC_H_TYPE_CONNECTED 0x7a + uint8_t middle1; +#define MIEL_HVAC_H_MIDDLE1 0x01 + uint8_t middle2; +#define MIEL_HVAC_H_MIDDLE2 0x30 + uint8_t len; +}; + +struct miel_hvac_data_settings { + uint8_t _pad1[2]; + uint8_t power; + uint8_t mode; +#define MIEL_HVAC_SETTINGS_MODE_MASK 0x7f + uint8_t temp; + uint8_t fan; + uint8_t vane; + uint8_t _pad2[2]; + uint8_t widevane; +#define MIEL_HVAC_SETTTINGS_WIDEVANE_MASK \ + 0x0f +}; + +struct miel_hvac_data_roomtemp { + uint8_t _pad1[2]; + uint8_t temp; +}; + +struct miel_hvac_data_status { + uint8_t _pad1[2]; + uint8_t compressor; + uint8_t operation; +}; + +struct miel_hvac_data { + uint8_t type; +#define MIEL_HVAC_DATA_T_SETTINGS 0x02 +#define MIEL_HVAC_DATA_T_ROOMTEMP 0x03 +#define MIEL_HVAC_DATA_T_TIMER 0x05 +#define MIEL_HVAC_DATA_T_STATUS 0x06 +#define MIEL_HVAC_DATA_T_STAGE 0x09 + + union { + struct miel_hvac_data_settings + settings; + struct miel_hvac_data_roomtemp + roomtemp; + struct miel_hvac_data_status + status; + + uint8_t bytes[15]; + } data; +}; + +CTASSERT(sizeof(struct miel_hvac_data) == 16); + +CTASSERT(offsetof(struct miel_hvac_data, data.settings.power) == 3); +CTASSERT(offsetof(struct miel_hvac_data, data.settings.mode) == 4); +CTASSERT(offsetof(struct miel_hvac_data, data.settings.temp) == 5); +CTASSERT(offsetof(struct miel_hvac_data, data.settings.fan) == 6); +CTASSERT(offsetof(struct miel_hvac_data, data.settings.vane) == 7); +CTASSERT(offsetof(struct miel_hvac_data, data.settings.widevane) == 10); + +CTASSERT(offsetof(struct miel_hvac_data, data.roomtemp.temp) == 3); + + + +#define MIEL_HVAC_H_TYPE_CONNECT 0x5a +static const uint8_t miel_hvac_msg_connect[] = { 0xca, 0x01 }; + +#define MIEL_HVAC_H_TYPE_REQUEST 0x42 + +struct miel_hvac_msg_request { + uint8_t type; +#define MIEL_HVAC_REQUEST_SETTINGS 0x02 +#define MIEL_HVAC_REQUEST_ROOMTEMP 0x03 +#define MIEL_HVAC_REQUEST_TIMERS 0x05 +#define MIEL_HVAC_REQUEST_STATUS 0x06 +#define MIEL_HVAC_REQUEST_STAGE 0x09 + uint8_t zero[15]; +}; + +#define MIEL_HVAC_H_TYPE_UPDATE 0x41 + +struct miel_hvac_msg_update { + uint8_t one; + uint16_t flags; +#define MIEL_HVAC_UPDATE_F_WIDEVANE (1 << 0) +#define MIEL_HVAC_UPDATE_F_POWER (1 << 8) +#define MIEL_HVAC_UPDATE_F_MODE (1 << 9) +#define MIEL_HVAC_UPDATE_F_TEMP (1 << 10) +#define MIEL_HVAC_UPDATE_F_FAN (1 << 11) +#define MIEL_HVAC_UPDATE_F_VANE (1 << 12) + uint8_t power; +#define MIEL_HVAC_UPDATE_POWER_OFF 0x00 +#define MIEL_HVAC_UPDATE_POWER_ON 0x01 + uint8_t mode; +#define MIEL_HVAC_UPDATE_MODE_HEAT 0x01 +#define MIEL_HVAC_UPDATE_MODE_DRY 0x02 +#define MIEL_HVAC_UPDATE_MODE_COOL 0x03 +#define MIEL_HVAC_UPDATE_MODE_FAN 0x07 +#define MIEL_HVAC_UPDATE_MODE_AUTO 0x08 + uint8_t temp; +#define MIEL_HVAC_UPDATE_TEMP_MIN 16 +#define MIEL_HVAC_UPDATE_TEMP_MAX 31 + uint8_t fan; +#define MIEL_HVAC_UPDATE_FAN_AUTO 0x00 +#define MIEL_HVAC_UPDATE_FAN_QUIET 0x01 +#define MIEL_HVAC_UPDATE_FAN_1 0x02 +#define MIEL_HVAC_UPDATE_FAN_2 0x03 +#define MIEL_HVAC_UPDATE_FAN_3 0x05 +#define MIEL_HVAC_UPDATE_FAN_4 0x06 + uint8_t vane; +#define MIEL_HVAC_UPDATE_VANE_AUTO 0x00 +#define MIEL_HVAC_UPDATE_VANE_1 0x01 +#define MIEL_HVAC_UPDATE_VANE_2 0x02 +#define MIEL_HVAC_UPDATE_VANE_3 0x03 +#define MIEL_HVAC_UPDATE_VANE_4 0x04 +#define MIEL_HVAC_UPDATE_VANE_5 0x05 +#define MIEL_HVAC_UPDATE_VANE_SWING 0x07 + uint8_t _pad1[5]; + uint8_t widevane; +#define MIEL_HVAC_UPDATE_WIDEVANE_MASK 0x0f +#define MIEL_HVAC_UPDATE_WIDEVANE_LL 0x01 +#define MIEL_HVAC_UPDATE_WIDEVANE_L 0x02 +#define MIEL_HVAC_UPDATE_WIDEVANE_LL 0x01 +#define MIEL_HVAC_UPDATE_WIDEVANE_L 0x02 +#define MIEL_HVAC_UPDATE_WIDEVANE_C 0x03 +#define MIEL_HVAC_UPDATE_WIDEVANE_R 0x04 +#define MIEL_HVAC_UPDATE_WIDEVANE_RR 0x05 +#define MIEL_HVAC_UPDATE_WIDEVANE_LR 0x08 +#define MIEL_HVAC_UPDATE_WIDEVANE_SWING 0x0c +#define MIEL_HVAC_UPDATE_WIDEVANE_ADJ 0x80 + uint8_t _pad2[2]; +} __packed; + +CTASSERT(sizeof(struct miel_hvac_msg_update) == 16); +#define MIEL_HVAC_OFFS(_v) ((_v) - sizeof(struct miel_hvac_header)) +CTASSERT(offsetof(struct miel_hvac_msg_update, flags) == MIEL_HVAC_OFFS(6)); +CTASSERT(offsetof(struct miel_hvac_msg_update, power) == MIEL_HVAC_OFFS(8)); +CTASSERT(offsetof(struct miel_hvac_msg_update, mode) == MIEL_HVAC_OFFS(9)); +CTASSERT(offsetof(struct miel_hvac_msg_update, temp) == MIEL_HVAC_OFFS(10)); +CTASSERT(offsetof(struct miel_hvac_msg_update, fan) == MIEL_HVAC_OFFS(11)); +CTASSERT(offsetof(struct miel_hvac_msg_update, vane) == MIEL_HVAC_OFFS(12)); +CTASSERT(offsetof(struct miel_hvac_msg_update, widevane) == MIEL_HVAC_OFFS(18)); + +static inline uint8_t +miel_hvac_deg2temp(uint8_t deg) +{ + return (31 - deg); +} + +static inline uint8_t +miel_hvac_temp2deg(uint8_t temp) +{ + return (31 - temp); +} + +static inline unsigned int +miel_hvac_roomtemp2deg(uint8_t roomtemp) +{ + return ((unsigned int)roomtemp + 10); +} + +struct miel_hvac_msg_remotetemp { + uint8_t seven; + uint8_t control; +#define MIEL_HVAC_REMOTETEMP_CLR 0x00 +#define MIEL_HVAC_REMOTETEMP_SET 0x01 + + uint8_t temp_old; +#define MIEL_HVAC_REMOTETEMP_OLD_MIN 8 +#define MIEL_HVAC_REMOTETEMP_OLD_MAX 38 +#define MIEL_HVAC_REMOTETEMP_OLD_FACTOR 2 + + uint8_t temp; +#define MIEL_HVAC_REMOTETEMP_MIN -63 +#define MIEL_HVAC_REMOTETEMP_MAX 63 +#define MIEL_HVAC_REMOTETEMP_OFFSET 64 +#define MIEL_HVAC_REMOTETEMP_FACTOR 2 + uint8_t _pad2[12]; +}; + +CTASSERT(sizeof(struct miel_hvac_msg_remotetemp) == 16); + +static inline uint8_t +miel_hvac_cksum_fini(uint8_t sum) +{ + return (0xfc - sum); +} + +struct miel_hvac_map { + uint8_t byte; + const char *name; +}; + +static const struct miel_hvac_map miel_hvac_mode_map[] = { + { MIEL_HVAC_UPDATE_MODE_HEAT, "heat" }, + { MIEL_HVAC_UPDATE_MODE_DRY, "dry" }, + { MIEL_HVAC_UPDATE_MODE_COOL, "cool" }, + { MIEL_HVAC_UPDATE_MODE_FAN, "fan_only" }, + { MIEL_HVAC_UPDATE_MODE_AUTO, "auto" }, +}; + +static const struct miel_hvac_map miel_hvac_fan_map[] = { + { MIEL_HVAC_UPDATE_FAN_AUTO, "auto" }, + { MIEL_HVAC_UPDATE_FAN_QUIET, "quiet" }, + { MIEL_HVAC_UPDATE_FAN_1, "1" }, + { MIEL_HVAC_UPDATE_FAN_2, "2" }, + { MIEL_HVAC_UPDATE_FAN_3, "3" }, + { MIEL_HVAC_UPDATE_FAN_4, "4" }, +}; + +static const struct miel_hvac_map miel_hvac_vane_map[] = { + { MIEL_HVAC_UPDATE_VANE_AUTO, "auto" }, + { MIEL_HVAC_UPDATE_VANE_1, "1" }, + { MIEL_HVAC_UPDATE_VANE_2, "2" }, + { MIEL_HVAC_UPDATE_VANE_3, "3" }, + { MIEL_HVAC_UPDATE_VANE_4, "4" }, + { MIEL_HVAC_UPDATE_VANE_5, "5" }, + { MIEL_HVAC_UPDATE_VANE_SWING, "swing" }, +}; + +static const struct miel_hvac_map miel_hvac_widevane_map[] = { + { MIEL_HVAC_UPDATE_WIDEVANE_LL, "LL" }, + { MIEL_HVAC_UPDATE_WIDEVANE_L, "L" }, + { MIEL_HVAC_UPDATE_WIDEVANE_C, "C" }, + { MIEL_HVAC_UPDATE_WIDEVANE_R, "R" }, + { MIEL_HVAC_UPDATE_WIDEVANE_RR, "RR" }, + { MIEL_HVAC_UPDATE_WIDEVANE_LR, "split" }, + { MIEL_HVAC_UPDATE_WIDEVANE_SWING, "swing" }, +}; + +enum miel_hvac_parser_state { + MIEL_HVAC_P_START, + MIEL_HVAC_P_TYPE, + MIEL_HVAC_P_MIDDLE1, + MIEL_HVAC_P_MIDDLE2, + MIEL_HVAC_P_LEN, + MIEL_HVAC_P_DATA, + MIEL_HVAC_P_CKSUM, + + MIEL_HVAC_P_SKIP, + MIEL_HVAC_P_SKIP_CKSUM, +}; + +#define MIEL_HVAC_DATABUFLEN 64 + +struct miel_hvac_parser { + enum miel_hvac_parser_state + p_state; + uint8_t p_type; + uint8_t p_sum; + uint8_t p_len; + uint8_t p_off; + uint8_t p_data[MIEL_HVAC_DATABUFLEN]; +}; + +struct miel_hvac_softc { + TasmotaSerial *sc_serial; + struct miel_hvac_parser sc_parser; + + unsigned int sc_device; + unsigned int sc_tick; + bool sc_settings_set; + bool sc_connected; + + struct miel_hvac_data sc_settings; + struct miel_hvac_data sc_temp; + struct miel_hvac_data sc_status; + struct miel_hvac_data sc_stage; + + struct miel_hvac_msg_update + sc_update; + struct miel_hvac_msg_remotetemp + sc_remotetemp; +}; + +static inline bool +miel_hvac_update_pending(struct miel_hvac_softc *sc) +{ + struct miel_hvac_msg_update *update = &sc->sc_update; + + return (update->flags != htons(0)); +} + +static struct miel_hvac_softc *miel_hvac_sc = nullptr; + +static void miel_hvac_input_connected(struct miel_hvac_softc *, + const void *, size_t); +static void miel_hvac_input_data(struct miel_hvac_softc *, + const void *, size_t); +static void miel_hvac_input_updated(struct miel_hvac_softc *, + const void *, size_t); + +static enum miel_hvac_parser_state +miel_hvac_parse(struct miel_hvac_softc *sc, uint8_t byte) +{ + struct miel_hvac_parser *p = &sc->sc_parser; + enum miel_hvac_parser_state nstate = p->p_state; + + switch (p->p_state) { + case MIEL_HVAC_P_START: + if (byte != MIEL_HVAC_H_START) + return (MIEL_HVAC_P_START); + + + p->p_sum = 0; + + nstate = MIEL_HVAC_P_TYPE; + break; + + case MIEL_HVAC_P_TYPE: + p->p_type = byte; + nstate = MIEL_HVAC_P_MIDDLE1; + break; + + case MIEL_HVAC_P_MIDDLE1: + if (byte != MIEL_HVAC_H_MIDDLE1) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": parse state MIDDLE1 expected %02x got %02x" + ", restarting"), MIEL_HVAC_H_MIDDLE1, byte); + return (MIEL_HVAC_P_START); + } + + nstate = MIEL_HVAC_P_MIDDLE2; + break; + + case MIEL_HVAC_P_MIDDLE2: + if (byte != MIEL_HVAC_H_MIDDLE2) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": parse state MIDDLE2 expected %02x got %02x" + ", restarting"), MIEL_HVAC_H_MIDDLE2, byte); + return (MIEL_HVAC_P_START); + } + + nstate = MIEL_HVAC_P_LEN; + break; + + case MIEL_HVAC_P_LEN: + if (byte == 0) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": skipping 0 byte message type 0x%02x"), + p->p_type); + return (MIEL_HVAC_P_SKIP_CKSUM); + } + + p->p_len = byte; + p->p_off = 0; + + switch (p->p_type) { + case MIEL_HVAC_H_TYPE_CONNECTED: + case MIEL_HVAC_H_TYPE_DATA: + case MIEL_HVAC_H_TYPE_UPDATED: + break; + default: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": skipping unknown message type 0x%02x"), + p->p_type); + return (MIEL_HVAC_P_SKIP); + } + + if (byte > sizeof(p->p_data)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": skipping %u data bytes of message type 0x%02x"), + p->p_len, p->p_type); + return (MIEL_HVAC_P_SKIP); + } + + nstate = MIEL_HVAC_P_DATA; + break; + + case MIEL_HVAC_P_DATA: + p->p_data[p->p_off++] = byte; + if (p->p_off >= p->p_len) + nstate = MIEL_HVAC_P_CKSUM; + break; + + case MIEL_HVAC_P_CKSUM: + if (miel_hvac_cksum_fini(p->p_sum) != byte) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": checksum failed, restarting")); + return (MIEL_HVAC_P_START); + } + + switch (p->p_type) { + case MIEL_HVAC_H_TYPE_CONNECTED: + miel_hvac_input_connected(sc, p->p_data, p->p_len); + break; + case MIEL_HVAC_H_TYPE_DATA: + miel_hvac_input_data(sc, p->p_data, p->p_len); + break; + case MIEL_HVAC_H_TYPE_UPDATED: + miel_hvac_input_updated(sc, p->p_data, p->p_len); + break; + } + + + return (MIEL_HVAC_P_START); + + case MIEL_HVAC_P_SKIP: + if (++p->p_off >= p->p_len) + return (MIEL_HVAC_P_SKIP_CKSUM); + return (nstate); + case MIEL_HVAC_P_SKIP_CKSUM: + return (MIEL_HVAC_P_START); + } + + p->p_sum += byte; + + return (nstate); +} + +static uint8_t +miel_hvac_write(struct miel_hvac_softc *sc, const uint8_t *bytes, size_t len) +{ + TasmotaSerial *serial = sc->sc_serial; + uint8_t cksum = 0; + size_t i; + + for (i = 0; i < len; i++) { + uint8_t b = bytes[i]; + serial->write(b); + cksum += b; + } + + return (cksum); +} + +static void +miel_hvac_send(struct miel_hvac_softc *sc, uint8_t type, + const void *data, size_t len) +{ + TasmotaSerial *serial = sc->sc_serial; + struct miel_hvac_header h = { + MIEL_HVAC_H_START, + type, + MIEL_HVAC_H_MIDDLE1, + MIEL_HVAC_H_MIDDLE2, + (uint8_t)len, + }; + uint8_t cksum = 0; + + cksum += miel_hvac_write(sc, (const uint8_t *)&h, sizeof(h)); + cksum += miel_hvac_write(sc, (const uint8_t *)data, len); + + char hex_h[(sizeof(h) + 1) * 2]; + char hex_d[(len + 1) * 2]; + AddLog_P2(LOG_LEVEL_DEBUG, + PSTR(MIEL_HVAC_LOGNAME ": sending %s %s %02x"), + ToHex_P((uint8_t *)&h, sizeof(h), hex_h, sizeof(hex_h)), + ToHex_P((uint8_t *)data, len, hex_d, sizeof(hex_d)), + miel_hvac_cksum_fini(cksum)); + + serial->write(miel_hvac_cksum_fini(cksum)); + serial->flush(); +} + +#define miel_hvac_send_connect(_sc) \ + miel_hvac_send((_sc), MIEL_HVAC_H_TYPE_CONNECT, \ + miel_hvac_msg_connect, sizeof(miel_hvac_msg_connect)) + +static const struct miel_hvac_map * +miel_hvac_map_byname(const char *name, + const struct miel_hvac_map *m, size_t n) +{ + const struct miel_hvac_map *e; + size_t i; + + for (i = 0; i < n; i++) { + e = &m[i]; + if (strcasecmp(e->name, name) == 0) + return (e); + } + + return (NULL); +} + +static const char * +miel_hvac_map_byval(uint8_t byte, + const struct miel_hvac_map *m, size_t n) +{ + const struct miel_hvac_map *e; + size_t i; + + for (i = 0; i < n; i++) { + e = &m[i]; + if (byte == e->byte) + return (e->name); + } + + return (NULL); +} + +static void +miel_hvac_request(struct miel_hvac_softc *sc, uint8_t type) +{ + struct miel_hvac_msg_request request = { type }; + + miel_hvac_send(sc, MIEL_HVAC_H_TYPE_REQUEST, + &request, sizeof(request)); +} + +static void +miel_hvac_init_update(struct miel_hvac_msg_update *update) +{ + memset(update, 0, sizeof(*update)); + update->one = 1; +} + +static inline void +miel_hvac_send_update(struct miel_hvac_softc *sc, + const struct miel_hvac_msg_update *update) +{ + miel_hvac_send(sc, MIEL_HVAC_H_TYPE_UPDATE, update, sizeof(*update)); +} + +static inline void +miel_hvac_send_remotetemp(struct miel_hvac_softc *sc, + const struct miel_hvac_msg_remotetemp *remotetemp) +{ + miel_hvac_send(sc, MIEL_HVAC_H_TYPE_UPDATE, + remotetemp, sizeof(*remotetemp)); +} + +static bool +miel_hvac_set_power(struct miel_hvac_softc *sc) +{ + struct miel_hvac_msg_update *update = &sc->sc_update; + uint16_t source = XdrvMailbox.payload; + + if (source == SRC_SWITCH) + return (false); + + update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER); + update->power = (XdrvMailbox.index & (1 << sc->sc_device)) ? + MIEL_HVAC_UPDATE_POWER_ON : MIEL_HVAC_UPDATE_POWER_OFF; + + return (true); +} + +static void +miel_hvac_respond_unsupported(void) +{ + ResponseCmndChar_P(PSTR("Unsupported")); +} + +static void +miel_hvac_cmnd_setfanspeed(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + const struct miel_hvac_map *e; + + if (XdrvMailbox.data_len == 0) + return; + + e = miel_hvac_map_byname(XdrvMailbox.data, + miel_hvac_fan_map, nitems(miel_hvac_fan_map)); + if (e == NULL) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_FAN); + update->fan = e->byte; + + ResponseCmndChar_P(e->name); +} + +static void +miel_hvac_cmnd_setmode(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + const struct miel_hvac_map *e; + + if (XdrvMailbox.data_len == 0) + return; + + e = miel_hvac_map_byname(XdrvMailbox.data, + miel_hvac_mode_map, nitems(miel_hvac_mode_map)); + if (e == NULL) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_MODE); + update->mode = e->byte; + + ResponseCmndChar_P(e->name); +} + +static void +miel_hvac_cmnd_sethamode(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + const struct miel_hvac_map *e; + + if (XdrvMailbox.data_len == 0) + return; + + if (strcasecmp(XdrvMailbox.data, "off") == 0) { + update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER); + update->power = MIEL_HVAC_UPDATE_POWER_OFF; + ResponseCmndChar_P(PSTR("off")); + return; + } + + + + + + + e = miel_hvac_map_byname(XdrvMailbox.data, + miel_hvac_mode_map, nitems(miel_hvac_mode_map)); + if (e == NULL) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER) | + htons(MIEL_HVAC_UPDATE_F_MODE); + update->power = MIEL_HVAC_UPDATE_POWER_ON; + update->mode = e->byte; + + ResponseCmndChar_P(e->name); +} + +static void +miel_hvac_cmnd_settemp(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + unsigned long degc; + + if (XdrvMailbox.data_len == 0) + return; + + degc = strtoul(XdrvMailbox.data, nullptr, 0); + if (degc < MIEL_HVAC_UPDATE_TEMP_MIN || + degc > MIEL_HVAC_UPDATE_TEMP_MAX) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_TEMP); + update->temp = miel_hvac_deg2temp(degc); + + ResponseCmndNumber(degc); +} + +static void +miel_hvac_cmnd_setvane(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + const struct miel_hvac_map *e; + + if (XdrvMailbox.data_len == 0) + return; + + e = miel_hvac_map_byname(XdrvMailbox.data, + miel_hvac_vane_map, nitems(miel_hvac_vane_map)); + if (e == NULL) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_VANE); + update->vane = e->byte; + + ResponseCmndChar_P(e->name); +} + +static void +miel_hvac_cmnd_setwidevane(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_update *update = &sc->sc_update; + const struct miel_hvac_map *e; + + if (XdrvMailbox.data_len == 0) + return; + + e = miel_hvac_map_byname(XdrvMailbox.data, + miel_hvac_widevane_map, nitems(miel_hvac_widevane_map)); + if (e == NULL) { + miel_hvac_respond_unsupported(); + return; + } + + update->flags |= htons(MIEL_HVAC_UPDATE_F_WIDEVANE); + update->widevane = e->byte; + + ResponseCmndChar_P(e->name); +} + +static inline uint8_t +miel_hvac_remotetemp_degc2old(long degc) +{ +# 760 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" + if (degc < MIEL_HVAC_REMOTETEMP_OLD_MIN) + degc = MIEL_HVAC_REMOTETEMP_OLD_MIN; + else if (degc > MIEL_HVAC_REMOTETEMP_OLD_MAX) + degc = MIEL_HVAC_REMOTETEMP_OLD_MIN; + + return ((degc - MIEL_HVAC_REMOTETEMP_OLD_MIN) * + MIEL_HVAC_REMOTETEMP_OLD_FACTOR); +} + +static void +miel_hvac_cmnd_remotetemp(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + struct miel_hvac_msg_remotetemp *rt = &sc->sc_remotetemp; + uint8_t control = MIEL_HVAC_REMOTETEMP_SET; + long degc; + + if (XdrvMailbox.data_len == 0) + return; + + if (strcasecmp(XdrvMailbox.data, "clear") == 0) { + control = MIEL_HVAC_REMOTETEMP_CLR; + degc = 0; + + ResponseCmndChar_P("clear"); + } else { + degc = strtol(XdrvMailbox.data, nullptr, 0); + + + if (degc < MIEL_HVAC_REMOTETEMP_MIN) + degc = MIEL_HVAC_REMOTETEMP_MIN; + else if (degc > MIEL_HVAC_REMOTETEMP_MAX) + degc = MIEL_HVAC_REMOTETEMP_MAX; + + ResponseCmndNumber(degc); + } + + memset(rt, 0, sizeof(*rt)); + rt->seven = 0x7; + rt->control = control; +# 808 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" + rt->temp_old = miel_hvac_remotetemp_degc2old(degc); + rt->temp = (degc + MIEL_HVAC_REMOTETEMP_OFFSET) * + MIEL_HVAC_REMOTETEMP_OLD_FACTOR; +} + +#ifdef MIEL_HVAC_DEBUG +static void +miel_hvac_cmnd_request(void) +{ + struct miel_hvac_softc *sc = miel_hvac_sc; + uint8_t type = MIEL_HVAC_REQUEST_ROOMTEMP; + + if (XdrvMailbox.data_len > 0) + type = strtoul(XdrvMailbox.data, nullptr, 0); + + miel_hvac_request(sc, type); + + ResponseCmndDone(); +} +#endif + + + + + +static void +miel_hvac_log_bytes(struct miel_hvac_softc *sc, const char *name, + const void *buf, size_t len) +{ + char hex[(MIEL_HVAC_DATABUFLEN + 1) * 2]; + const unsigned char *b = (const unsigned char *)buf; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": response %s %s"), name, ToHex_P(b, len, hex, sizeof(hex))); +} + +static void +miel_hvac_input_connected(struct miel_hvac_softc *sc, + const void *buf, size_t len) +{ + AddLog_P2(LOG_LEVEL_INFO, + PSTR(MIEL_HVAC_LOGNAME ": connected to Mitsubishi Electric HVAC")); + sc->sc_connected = 1; +} + +static void +miel_hvac_publish_settings(struct miel_hvac_softc *sc) +{ + const struct miel_hvac_data_settings *set = + &sc->sc_settings.data.settings; + char hex[(sizeof(sc->sc_settings) + 1) * 2]; + char temp[33]; + const char *name; + + Response_P(PSTR("{\"" D_JSON_IRHVAC_POWER "\":\"%s\""), + set->power ? "ON" : "OFF"); + + name = miel_hvac_map_byval( set->mode & + MIEL_HVAC_SETTINGS_MODE_MASK, + miel_hvac_mode_map, nitems(miel_hvac_mode_map)); + if (name != NULL) { + ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_MODE "\":\"%s\""), + name); + ResponseAppend_P(PSTR(",\"HA" D_JSON_IRHVAC_MODE "\":\"%s\""), + set->power ? name : "off"); + } + + dtostrfd(ConvertTemp(miel_hvac_temp2deg(set->temp)), + Settings.flag2.temperature_resolution, temp); + ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_TEMP "\":%s"), temp); + + name = miel_hvac_map_byval(set->fan, + miel_hvac_fan_map, nitems(miel_hvac_fan_map)); + if (name != NULL) { + ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_FANSPEED "\":\"%s\""), + name); + } + + name = miel_hvac_map_byval(set->vane, + miel_hvac_vane_map, nitems(miel_hvac_vane_map)); + if (name != NULL) { + ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_SWINGV "\":\"%s\""), + name); + } + + name = miel_hvac_map_byval(set->widevane & + MIEL_HVAC_SETTTINGS_WIDEVANE_MASK, + miel_hvac_widevane_map, nitems(miel_hvac_widevane_map)); + if (name != NULL) { + ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_SWINGH "\":\"%s\""), + name); + } + + ResponseAppend_P(PSTR(",\"Bytes\":\"%s\""), + ToHex_P((uint8_t *)&sc->sc_settings, sizeof(sc->sc_settings), + hex, sizeof(hex))); + + ResponseAppend_P(PSTR("}")); + + MqttPublishPrefixTopic_P(TELE, PSTR("HVACSettings")); + + XdrvRulesProcess(); +} + +static void +miel_hvac_input_settings(struct miel_hvac_softc *sc, + const struct miel_hvac_data *d) +{ + const struct miel_hvac_data_settings *set = &d->data.settings; + uint32_t state = set->power ? 1 : 0; + bool publish; + + if (miel_hvac_update_pending(sc)) { + + + + + sc->sc_settings_set = 0; + return; + } + + if (bitRead(power, sc->sc_device) != !!state) + ExecuteCommandPower(sc->sc_device, state, SRC_SWITCH); + + publish = (sc->sc_settings_set == 0) || + (memcmp(d, &sc->sc_settings, sizeof(sc->sc_settings)) != 0); + sc->sc_settings_set = 1; + sc->sc_settings = *d; + + if (publish) + miel_hvac_publish_settings(sc); +} + +static void +miel_hvac_data_response(struct miel_hvac_softc *sc, + const struct miel_hvac_data *d) +{ + char hex[(sizeof(*d) + 1) * 2]; + + Response_P(PSTR("{\"Bytes\":\"%s\"}"), + ToHex_P((uint8_t *)d, sizeof(*d), hex, sizeof(hex))); + + MqttPublishPrefixTopic_P(TELE, PSTR("HVACData")); + XdrvRulesProcess(); +} + +static void +miel_hvac_input_sensor(struct miel_hvac_softc *sc, struct miel_hvac_data *dst, + const struct miel_hvac_data *src) +{ + bool publish; + + publish = (memcmp(dst, src, sizeof(*dst)) != 0); + *dst = *src; + + if (publish) + MqttPublishSensor(); + +} + +static void +miel_hvac_input_data(struct miel_hvac_softc *sc, + const void *buf, size_t len) +{ + const struct miel_hvac_data *d; + + miel_hvac_log_bytes(sc, "data", buf, len); + if (len < sizeof(*d)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": short data response (%zu < %zu)"), len, sizeof(*d)); + return; + } + + d = (const struct miel_hvac_data *)buf; + + switch (d->type) { + case MIEL_HVAC_DATA_T_SETTINGS: + miel_hvac_input_settings(sc, d); + break; + case MIEL_HVAC_DATA_T_ROOMTEMP: + miel_hvac_input_sensor(sc, &sc->sc_temp, d); + break; + case MIEL_HVAC_DATA_T_STATUS: + miel_hvac_input_sensor(sc, &sc->sc_status, d); + break; + case MIEL_HVAC_DATA_T_STAGE: + miel_hvac_input_sensor(sc, &sc->sc_stage, d); + break; + default: + miel_hvac_data_response(sc, d); + break; + } +} + +static void +miel_hvac_input_updated(struct miel_hvac_softc *sc, + const void *buf, size_t len) +{ + miel_hvac_log_bytes(sc, "updated", buf, len); +} + + + + + +static void +miel_hvac_pre_init(void) +{ + struct miel_hvac_softc *sc; + int baudrate = 2400; + + if (!PinUsed(GPIO_MIEL_HVAC_TX) || !PinUsed(GPIO_MIEL_HVAC_RX)) + return; + + sc = (struct miel_hvac_softc *)malloc(sizeof(*sc)); + if (sc == NULL) { + AddLog_P(LOG_LEVEL_ERROR, + PSTR(MIEL_HVAC_LOGNAME ": unable to allocate state")); + return; + } + + memset(sc, 0, sizeof(*sc)); + miel_hvac_init_update(&sc->sc_update); + + sc->sc_serial = new TasmotaSerial(Pin(GPIO_MIEL_HVAC_RX), + Pin(GPIO_MIEL_HVAC_TX), 2); + + if (!sc->sc_serial->begin(baudrate, 2)) { + AddLog_P2(LOG_LEVEL_ERROR, + PSTR(MIEL_HVAC_LOGNAME ": unable to begin serial " + "(baudrate %d)"), baudrate); + goto del; + } + + if (sc->sc_serial->hardwareSerial()) { + ClaimSerial(); + SetSerial(baudrate, TS_SERIAL_8E1); + } + + sc->sc_device = devices_present++; + + miel_hvac_sc = sc; + return; +del: + delete sc->sc_serial; +free: + free(sc); +} + +static void +miel_hvac_loop(struct miel_hvac_softc *sc) +{ + TasmotaSerial *serial = sc->sc_serial; + + while (serial->available()) { + yield(); + + sc->sc_parser.p_state = miel_hvac_parse(sc, serial->read()); + } +} + +static void +miel_hvac_sensor(struct miel_hvac_softc *sc) +{ + char hex[(sizeof(sc->sc_status) + 1) * 2]; + const char *sep = ""; + + ResponseAppend_P(PSTR("," "\"MiElHVAC\":{")); + + if (sc->sc_temp.type != 0) { + const struct miel_hvac_data_roomtemp *rt = + &sc->sc_temp.data.roomtemp; + unsigned int temp = miel_hvac_roomtemp2deg(rt->temp); + char room_temp[33]; + + dtostrfd(ConvertTemp(temp), + Settings.flag2.temperature_resolution, room_temp); + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), + room_temp); + + sep = ","; + } + + if (sc->sc_status.type != 0) { + const struct miel_hvac_data_status *s = + &sc->sc_status.data.status; + + ResponseAppend_P(PSTR("%s" "\"Operation\":\"%s\"" "," + "\"Compressor\":\"%s\""), sep, + s->operation ? "ON" : "OFF", + s->compressor ? "ON" : "OFF"); + + sep = ","; + } + + if (sc->sc_temp.type != 0) { + ResponseAppend_P(PSTR("%s" "\"roomtemp\":\"%s\""), sep, + ToHex_P((uint8_t *)&sc->sc_temp, sizeof(sc->sc_temp), + hex, sizeof(hex))); + + sep = ","; + } + + if (sc->sc_status.type != 0) { + ResponseAppend_P(PSTR("%s" "\"status\":\"%s\""), sep, + ToHex_P((uint8_t *)&sc->sc_status, sizeof(sc->sc_status), + hex, sizeof(hex))); + + sep = ","; + } + + if (sc->sc_stage.type != 0) { + ResponseAppend_P(PSTR("%s" "\"stage\":\"%s\""), sep, + ToHex_P((uint8_t *)&sc->sc_stage, sizeof(sc->sc_stage), + hex, sizeof(hex))); + } + + ResponseAppend_P(PSTR("}")); +} +# 1136 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" +enum miel_hvac_connect_states { + MIEL_HVAC_CONNECT_S_2400_MSG, + MIEL_HVAC_CONNECT_S_9600, + MIEL_HVAC_CONNECT_S_9600_MSG, + MIEL_HVAC_CONNECT_S_2400, + + MIEL_HVAC_CONNECT_S_COUNT, +}; + +static void +miel_hvac_connect(struct miel_hvac_softc *sc) +{ + TasmotaSerial *serial = sc->sc_serial; + uint32_t baudrate; + unsigned int state; + + state = (sc->sc_tick++ % MIEL_HVAC_CONNECT_S_COUNT); + + switch (state) { + case MIEL_HVAC_CONNECT_S_2400: + baudrate = 2400; + break; + case MIEL_HVAC_CONNECT_S_9600: + baudrate = 9600; + break; + default: + miel_hvac_send_connect(sc); + return; + } + + serial->begin(baudrate, 2); + if (serial->hardwareSerial()) + SetSerial(baudrate, TS_SERIAL_8E1); +} + +static void +miel_hvac_tick(struct miel_hvac_softc *sc) +{ + static const uint8_t updates[] = { + MIEL_HVAC_REQUEST_SETTINGS, + MIEL_HVAC_REQUEST_STATUS, + MIEL_HVAC_REQUEST_SETTINGS, + MIEL_HVAC_REQUEST_ROOMTEMP, + + MIEL_HVAC_REQUEST_SETTINGS, + + MIEL_HVAC_REQUEST_STAGE, + }; + + unsigned int i; + + if (miel_hvac_update_pending(sc)) { + struct miel_hvac_msg_update *update = &sc->sc_update; + + miel_hvac_send_update(sc, update); + + miel_hvac_init_update(update); + + + sc->sc_tick = 0; + return; + } + + if (sc->sc_remotetemp.seven) { + struct miel_hvac_msg_remotetemp *remotetemp = + &sc->sc_remotetemp; + + miel_hvac_send_remotetemp(sc, remotetemp); + memset(remotetemp, 0, sizeof(*remotetemp)); + return; + } + + i = (sc->sc_tick++ % nitems(updates)); + + miel_hvac_request(sc, updates[i]); +} + + + + + +static const char miel_hvac_cmnd_names[] PROGMEM = + + "|" D_CMND_MIEL_HVAC_SETFANSPEED + "|" D_CMND_MIEL_HVAC_SETMODE + "|" D_CMND_MIEL_HVAC_SETHAMODE + "|" D_CMND_MIEL_HVAC_SETTEMP + "|" D_CMND_MIEL_HVAC_SETSWINGV + "|" D_CMND_MIEL_HVAC_SETSWINGH + "|" D_CMND_MIEL_HVAC_REMOTETEMP +#ifdef MIEL_HVAC_DEBUG + "|" "HVACRequest" +#endif + ; + +static void (*const miel_hvac_cmnds[])(void) PROGMEM = { + &miel_hvac_cmnd_setfanspeed, + &miel_hvac_cmnd_setmode, + &miel_hvac_cmnd_sethamode, + &miel_hvac_cmnd_settemp, + &miel_hvac_cmnd_setvane, + &miel_hvac_cmnd_setwidevane, + &miel_hvac_cmnd_remotetemp, +#ifdef MIEL_HVAC_DEBUG + &miel_hvac_cmnd_request, +#endif +}; + +bool Xdrv44(uint8_t function) { + bool result = false; + struct miel_hvac_softc *sc = miel_hvac_sc; + + switch (function) { + case FUNC_PRE_INIT: + miel_hvac_pre_init(); + return (false); + } + + if (sc == NULL) + return (false); + + switch (function) { + case FUNC_LOOP: + miel_hvac_loop(sc); + break; + + case FUNC_SET_DEVICE_POWER: + result = miel_hvac_set_power(sc); + break; + + case FUNC_EVERY_250_MSECOND: + if (sc->sc_connected) + miel_hvac_tick(sc); + else + miel_hvac_connect(sc); + break; + + case FUNC_EVERY_50_MSECOND: + case FUNC_EVERY_100_MSECOND: + case FUNC_EVERY_200_MSECOND: + case FUNC_EVERY_SECOND: + break; + + case FUNC_JSON_APPEND: + miel_hvac_sensor(sc); + break; + case FUNC_AFTER_TELEPERIOD: + if (sc->sc_settings_set) + miel_hvac_publish_settings(sc); + break; + + case FUNC_COMMAND: + result = DecodeCommand(miel_hvac_cmnd_names, miel_hvac_cmnds); + break; + } + + return (result); +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" +#ifdef ESP32 +#ifdef USE_WEBCAM +# 61 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" +#define XDRV_81 81 + +#include "esp_camera.h" +#include "sensor.h" +#include "fb_gfx.h" +#include "fd_forward.h" +#include "fr_forward.h" + +bool HttpCheckPriviledgedAccess(bool); +extern ESP8266WebServer *Webserver; + +ESP8266WebServer *CamServer; +#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e" + +WiFiClient client; + + + +#define PWDN_GPIO_NUM 32 +#define RESET_GPIO_NUM -1 +#define XCLK_GPIO_NUM 0 +#define SIOD_GPIO_NUM 26 +#define SIOC_GPIO_NUM 27 + +#define Y9_GPIO_NUM 35 +#define Y8_GPIO_NUM 34 +#define Y7_GPIO_NUM 39 +#define Y6_GPIO_NUM 36 +#define Y5_GPIO_NUM 21 +#define Y4_GPIO_NUM 19 +#define Y3_GPIO_NUM 18 +#define Y2_GPIO_NUM 5 +#define VSYNC_GPIO_NUM 25 +#define HREF_GPIO_NUM 23 +#define PCLK_GPIO_NUM 22 + +struct { + uint8_t up; + uint16_t width; + uint16_t height; + uint8_t stream_active; +#ifdef USE_FACE_DETECT + uint8_t faces; + uint16_t face_detect_time; +#endif +} Wc; + +#ifdef ENABLE_RTSPSERVER +#include +#include +#include +#include +WiFiServer rtspServer(8554); +CStreamer *rtsp_streamer; +CRtspSession *rtsp_session; +WiFiClient rtsp_client; +uint8_t rtsp_start; +OV2640 cam; +#endif + + + +bool WcPinUsed(void) { + bool pin_used = true; + for (uint32_t i = 0; i < MAX_WEBCAM_DATA; i++) { + if (!PinUsed(GPIO_WEBCAM_DATA, i)) { + pin_used = false; + } + + + + + + } + if (!PinUsed(GPIO_WEBCAM_XCLK) || !PinUsed(GPIO_WEBCAM_PCLK) || + !PinUsed(GPIO_WEBCAM_VSYNC) || !PinUsed(GPIO_WEBCAM_HREF) || + !PinUsed(GPIO_WEBCAM_SIOD) || !PinUsed(GPIO_WEBCAM_SIOC)) { + pin_used = false; + } + return pin_used; +} + +uint32_t WcSetup(int32_t fsiz) { + if (fsiz > 10) { fsiz = 10; } + + Wc.stream_active = 0; + + if (fsiz < 0) { + esp_camera_deinit(); + Wc.up = 0; + return 0; + } + + if (Wc.up) { + esp_camera_deinit(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Deinit")); + + } + Wc.up = 0; + + + + camera_config_t config; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.xclk_freq_hz = 20000000; + config.pixel_format = PIXFORMAT_JPEG; + + + + if (WcPinUsed()) { + config.pin_d0 = Pin(GPIO_WEBCAM_DATA); + config.pin_d1 = Pin(GPIO_WEBCAM_DATA, 1); + config.pin_d2 = Pin(GPIO_WEBCAM_DATA, 2); + config.pin_d3 = Pin(GPIO_WEBCAM_DATA, 3); + config.pin_d4 = Pin(GPIO_WEBCAM_DATA, 4); + config.pin_d5 = Pin(GPIO_WEBCAM_DATA, 5); + config.pin_d6 = Pin(GPIO_WEBCAM_DATA, 6); + config.pin_d7 = Pin(GPIO_WEBCAM_DATA, 7); + config.pin_xclk = Pin(GPIO_WEBCAM_XCLK); + config.pin_pclk = Pin(GPIO_WEBCAM_PCLK); + config.pin_vsync = Pin(GPIO_WEBCAM_VSYNC); + config.pin_href = Pin(GPIO_WEBCAM_HREF); + config.pin_sscb_sda = Pin(GPIO_WEBCAM_SIOD); + config.pin_sscb_scl = Pin(GPIO_WEBCAM_SIOC); + config.pin_pwdn = (PinUsed(GPIO_WEBCAM_PWDN)) ? Pin(GPIO_WEBCAM_PWDN) : -1; + config.pin_reset = (PinUsed(GPIO_WEBCAM_RESET)) ? Pin(GPIO_WEBCAM_RESET) : -1; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: User template")); + } else { + + config.pin_d0 = Y2_GPIO_NUM; + config.pin_d1 = Y3_GPIO_NUM; + config.pin_d2 = Y4_GPIO_NUM; + config.pin_d3 = Y5_GPIO_NUM; + config.pin_d4 = Y6_GPIO_NUM; + config.pin_d5 = Y7_GPIO_NUM; + config.pin_d6 = Y8_GPIO_NUM; + config.pin_d7 = Y9_GPIO_NUM; + config.pin_xclk = XCLK_GPIO_NUM; + config.pin_pclk = PCLK_GPIO_NUM; + config.pin_vsync = VSYNC_GPIO_NUM; + config.pin_href = HREF_GPIO_NUM; + config.pin_sscb_sda = SIOD_GPIO_NUM; + config.pin_sscb_scl = SIOC_GPIO_NUM; + config.pin_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Default template")); + } +# 218 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" + bool psram = psramFound(); + if (psram) { + config.frame_size = FRAMESIZE_UXGA; + config.jpeg_quality = 10; + config.fb_count = 2; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM found")); + } else { + config.frame_size = FRAMESIZE_VGA; + config.jpeg_quality = 12; + config.fb_count = 1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM not found")); + } + + + + + + + + void *x = 0; + esp_err_t err = esp_camera_init(&config); + if (x) { free(x); } + + if (err != ESP_OK) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Init failed with error 0x%x"), err); + return 0; + } + + + + sensor_t * wc_s = esp_camera_sensor_get(); + + wc_s->set_vflip(wc_s, Settings.webcam_config.flip); + wc_s->set_hmirror(wc_s, Settings.webcam_config.mirror); + wc_s->set_brightness(wc_s, Settings.webcam_config.brightness -2); + wc_s->set_saturation(wc_s, Settings.webcam_config.saturation -2); + wc_s->set_contrast(wc_s, Settings.webcam_config.contrast -2); + + + wc_s->set_framesize(wc_s, (framesize_t)fsiz); + + camera_fb_t *wc_fb = esp_camera_fb_get(); + if (!wc_fb) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Init failed to get the frame on time")); + return 0; + } + Wc.width = wc_fb->width; + Wc.height = wc_fb->height; + esp_camera_fb_return(wc_fb); + +#ifdef USE_FACE_DETECT + fd_init(); +#endif + + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Initialized")); + + Wc.up = 1; + if (psram) { Wc.up = 2; } + + return Wc.up; +} + + + +int32_t WcSetOptions(uint32_t sel, int32_t value) { + int32_t res = 0; + sensor_t *s = esp_camera_sensor_get(); + if (!s) { return -99; } + + switch (sel) { + case 0: + if (value >= 0) { s->set_framesize(s, (framesize_t)value); } + res = s->status.framesize; + break; + case 1: + if (value >= 0) { s->set_special_effect(s, value); } + res = s->status.special_effect; + break; + case 2: + if (value >= 0) { s->set_vflip(s, value); } + res = s->status.vflip; + break; + case 3: + if (value >= 0) { s->set_hmirror(s, value); } + res = s->status.hmirror; + break; + case 4: + if (value >= -4) { s->set_contrast(s, value); } + res = s->status.contrast; + break; + case 5: + if (value >= -4) { s->set_brightness(s, value); } + res = s->status.brightness; + break; + case 6: + if (value >= -4) { s->set_saturation(s,value); } + res = s->status.saturation; + break; + } + + return res; +} + +uint32_t WcGetWidth(void) { + camera_fb_t *wc_fb = esp_camera_fb_get(); + if (!wc_fb) { return 0; } + Wc.width = wc_fb->width; + esp_camera_fb_return(wc_fb); + return Wc.width; +} + +uint32_t WcGetHeight(void) { + camera_fb_t *wc_fb = esp_camera_fb_get(); + if (!wc_fb) { return 0; } + Wc.height = wc_fb->height; + esp_camera_fb_return(wc_fb); + return Wc.height; +} + + + +uint16_t motion_detect; +uint32_t motion_ltime; +uint32_t motion_trigger; +uint32_t motion_brightness; +uint8_t *last_motion_buffer; + +uint32_t WcSetMotionDetect(int32_t value) { + if (value >= 0) { motion_detect = value; } + if (-1 == value) { + return motion_trigger; + } else { + return motion_brightness; + } +} + + +void WcDetectMotion(void) { + camera_fb_t *wc_fb; + uint8_t *out_buf = 0; + + if ((millis()-motion_ltime) > motion_detect) { + motion_ltime = millis(); + wc_fb = esp_camera_fb_get(); + if (!wc_fb) { return; } + + if (!last_motion_buffer) { + last_motion_buffer=(uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + } + if (last_motion_buffer) { + if (PIXFORMAT_JPEG == wc_fb->format) { + out_buf = (uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (out_buf) { + fmt2rgb888(wc_fb->buf, wc_fb->len, wc_fb->format, out_buf); + uint32_t x, y; + uint8_t *pxi = out_buf; + uint8_t *pxr = last_motion_buffer; + + uint64_t accu = 0; + uint64_t bright = 0; + for (y = 0; y < wc_fb->height; y++) { + for (x = 0; x < wc_fb->width; x++) { + int32_t gray = (pxi[0] + pxi[1] + pxi[2]) / 3; + int32_t lgray = pxr[0]; + pxr[0] = gray; + pxi += 3; + pxr++; + accu += abs(gray - lgray); + bright += gray; + } + } + motion_trigger = accu / ((wc_fb->height * wc_fb->width) / 100); + motion_brightness = bright / ((wc_fb->height * wc_fb->width) / 100); + free(out_buf); + } + } + } + esp_camera_fb_return(wc_fb); + } +} + + + +#ifdef USE_FACE_DETECT + +static mtmn_config_t mtmn_config = {0}; + +void fd_init(void) { + mtmn_config.type = FAST; + mtmn_config.min_face = 80; + mtmn_config.pyramid = 0.707; + mtmn_config.pyramid_times = 4; + mtmn_config.p_threshold.score = 0.6; + mtmn_config.p_threshold.nms = 0.7; + mtmn_config.p_threshold.candidate_number = 20; + mtmn_config.r_threshold.score = 0.7; + mtmn_config.r_threshold.nms = 0.7; + mtmn_config.r_threshold.candidate_number = 10; + mtmn_config.o_threshold.score = 0.7; + mtmn_config.o_threshold.nms = 0.7; + mtmn_config.o_threshold.candidate_number = 1; +} + +#define FACE_COLOR_WHITE 0x00FFFFFF +#define FACE_COLOR_BLACK 0x00000000 +#define FACE_COLOR_RED 0x000000FF +#define FACE_COLOR_GREEN 0x0000FF00 +#define FACE_COLOR_BLUE 0x00FF0000 +#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN) +#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN) +#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED) +void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id); +# 469 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" +#define DL_SPIRAM_SUPPORT + +uint32_t WcSetFaceDetect(int32_t value) { + if (value >= 0) { Wc.face_detect_time = value; } + return Wc.faces; +} + +uint32_t face_ltime; + +uint32_t WcDetectFace(void); + +uint32_t WcDetectFace(void) { + dl_matrix3du_t *image_matrix; + size_t out_len, out_width, out_height; + uint8_t * out_buf; + bool s; + bool detected = false; + int face_id = 0; + camera_fb_t *fb; + + if ((millis() - face_ltime) > Wc.face_detect_time) { + face_ltime = millis(); + fb = esp_camera_fb_get(); + if (!fb) { return ESP_FAIL; } + + image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3); + if (!image_matrix) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: dl_matrix3du_alloc failed")); + esp_camera_fb_return(fb); + return ESP_FAIL; + } + + out_buf = image_matrix->item; + + + + + s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); + esp_camera_fb_return(fb); + if (!s){ + dl_matrix3du_free(image_matrix); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: to rgb888 failed")); + return ESP_FAIL; + } + + box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config); + if (net_boxes){ + detected = true; + Wc.faces = net_boxes->len; + + + + + free(net_boxes->score); + free(net_boxes->box); + free(net_boxes->landmark); + free(net_boxes); + } else { + Wc.faces = 0; + } + dl_matrix3du_free(image_matrix); + + + } +} +#endif + + + +#ifndef MAX_PICSTORE +#define MAX_PICSTORE 4 +#endif +struct PICSTORE { + uint8_t *buff; + uint32_t len; +}; + +struct PICSTORE picstore[MAX_PICSTORE]; + +#ifdef COPYFRAME +struct PICSTORE tmp_picstore; +#endif + +uint32_t WcGetPicstore(int32_t num, uint8_t **buff) { + if (num<0) { return MAX_PICSTORE; } + *buff = picstore[num].buff; + return picstore[num].len; +} + +uint32_t WcGetFrame(int32_t bnum) { + size_t _jpg_buf_len = 0; + uint8_t * _jpg_buf = NULL; + camera_fb_t *wc_fb = 0; + bool jpeg_converted = false; + + if (bnum < 0) { + if (bnum < -MAX_PICSTORE) { bnum=-1; } + bnum = -bnum; + bnum--; + if (picstore[bnum].buff) { free(picstore[bnum].buff); } + picstore[bnum].len = 0; + return 0; + } + +#ifdef COPYFRAME + if (bnum & 0x10) { + bnum &= 0xf; + _jpg_buf = tmp_picstore.buff; + _jpg_buf_len = tmp_picstore.len; + if (!_jpg_buf_len) { return 0; } + goto pcopy; + } +#endif + + wc_fb = esp_camera_fb_get(); + if (!wc_fb) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't get frame")); + return 0; + } + if (!bnum) { + Wc.width = wc_fb->width; + Wc.height = wc_fb->height; + esp_camera_fb_return(wc_fb); + return 0; + } + + if (wc_fb->format != PIXFORMAT_JPEG) { + jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); + if (!jpeg_converted){ + + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + } else { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + +pcopy: + if ((bnum < 1) || (bnum > MAX_PICSTORE)) { bnum = 1; } + bnum--; + if (picstore[bnum].buff) { free(picstore[bnum].buff); } + picstore[bnum].buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (picstore[bnum].buff) { + memcpy(picstore[bnum].buff, _jpg_buf, _jpg_buf_len); + picstore[bnum].len = _jpg_buf_len; + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't allocate picstore")); + picstore[bnum].len = 0; + } + if (wc_fb) { esp_camera_fb_return(wc_fb); } + if (jpeg_converted) { free(_jpg_buf); } + if (!picstore[bnum].buff) { return 0; } + + return _jpg_buf_len; +} + +void HandleImage(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + uint32_t bnum = Webserver->arg(F("p")).toInt(); + if ((bnum < 0) || (bnum > MAX_PICSTORE)) { bnum= 1; } + WiFiClient client = Webserver->client(); + String response = "HTTP/1.1 200 OK\r\n"; + response += "Content-disposition: inline; filename=cap.jpg\r\n"; + response += "Content-type: image/jpeg\r\n\r\n"; + Webserver->sendContent(response); + + if (!bnum) { + size_t _jpg_buf_len = 0; + uint8_t * _jpg_buf = NULL; + camera_fb_t *wc_fb = 0; + wc_fb = esp_camera_fb_get(); + if (!wc_fb) { return; } + if (wc_fb->format != PIXFORMAT_JPEG) { + bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); + if (!jpeg_converted) { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + } else { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + if (_jpg_buf_len) { + client.write((char *)_jpg_buf, _jpg_buf_len); + } + if (wc_fb) { esp_camera_fb_return(wc_fb); } + } else { + bnum--; + if (!picstore[bnum].len) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: No image #: %d"), bnum); + return; + } + client.write((char *)picstore[bnum].buff, picstore[bnum].len); + } + client.stop(); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("CAM: Sending image #: %d"), bnum+1); +} + +void HandleImageBasic(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP "Capture image")); + + if (Settings.webcam_config.stream) { + if (!CamServer) { + WcStreamControl(); + } + } + + camera_fb_t *wc_fb; + wc_fb = esp_camera_fb_get(); + if (!wc_fb) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame buffer could not be acquired")); + return; + } + + size_t _jpg_buf_len = 0; + uint8_t * _jpg_buf = NULL; + if (wc_fb->format != PIXFORMAT_JPEG) { + bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); + if (!jpeg_converted) { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + } else { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + + if (_jpg_buf_len) { + Webserver->client().flush(); + WSHeaderSend(); + Webserver->sendHeader(F("Content-disposition"), F("inline; filename=snapshot.jpg")); + Webserver->send_P(200, "image/jpeg", (char *)_jpg_buf, _jpg_buf_len); + Webserver->client().stop(); + } + + esp_camera_fb_return(wc_fb); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("CAM: Image sent")); +} + +void HandleWebcamMjpeg(void) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Handle camserver")); + + + Wc.stream_active = 1; + client = CamServer->client(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Create client")); + +} + +void HandleWebcamMjpegTask(void) { + camera_fb_t *wc_fb; + size_t _jpg_buf_len = 0; + uint8_t * _jpg_buf = NULL; + + + uint32_t tlen; + bool jpeg_converted = false; + + if (!client.connected()) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Client fail")); + Wc.stream_active = 0; + } + if (1 == Wc.stream_active) { + client.flush(); + client.setTimeout(3); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Start stream")); + client.print("HTTP/1.1 200 OK\r\n" + "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" + "\r\n"); + Wc.stream_active = 2; + } + if (2 == Wc.stream_active) { + wc_fb = esp_camera_fb_get(); + if (!wc_fb) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame fail")); + Wc.stream_active = 0; + } + } + if (2 == Wc.stream_active) { + if (wc_fb->format != PIXFORMAT_JPEG) { + jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); + if (!jpeg_converted){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: JPEG compression failed")); + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + } else { + _jpg_buf_len = wc_fb->len; + _jpg_buf = wc_fb->buf; + } + + client.printf("Content-Type: image/jpeg\r\n" + "Content-Length: %d\r\n" + "\r\n", static_cast(_jpg_buf_len)); + tlen = client.write(_jpg_buf, _jpg_buf_len); + + + + + + + client.print("\r\n--" BOUNDARY "\r\n"); + +#ifdef COPYFRAME + if (tmp_picstore.buff) { free(tmp_picstore.buff); } + tmp_picstore.buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (tmp_picstore.buff) { + memcpy(tmp_picstore.buff, _jpg_buf, _jpg_buf_len); + tmp_picstore.len = _jpg_buf_len; + } else { + tmp_picstore.len = 0; + } +#endif + + if (jpeg_converted) { free(_jpg_buf); } + esp_camera_fb_return(wc_fb); + + } + if (0 == Wc.stream_active) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit")); + client.flush(); + client.stop(); + } +} + +void HandleWebcamRoot(void) { + + CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg"); + CamServer->send(302, "", ""); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Root called")); +} + + + +uint32_t WcSetStreamserver(uint32_t flag) { + if (global_state.network_down) { return 0; } + + Wc.stream_active = 0; + + if (flag) { + if (!CamServer) { + CamServer = new ESP8266WebServer(81); + CamServer->on("/", HandleWebcamRoot); + CamServer->on("/cam.mjpeg", HandleWebcamMjpeg); + CamServer->on("/cam.jpg", HandleWebcamMjpeg); + CamServer->on("/stream", HandleWebcamMjpeg); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream init")); + CamServer->begin(); + } + } else { + if (CamServer) { + CamServer->stop(); + delete CamServer; + CamServer = NULL; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit")); + } + } + return 0; +} + +void WcStreamControl() { + WcSetStreamserver(Settings.webcam_config.stream); + WcSetup(Settings.webcam_config.resolution); +} + + +#ifdef ENABLE_RTSPSERVER +static uint32_t rtsp_lastframe_time; +#ifndef RTSP_FRAME_TIME +#define RTSP_FRAME_TIME 100 +#endif +#endif + +void WcLoop(void) { + if (CamServer) { + CamServer->handleClient(); + if (Wc.stream_active) { HandleWebcamMjpegTask(); } + } + if (motion_detect) { WcDetectMotion(); } +#ifdef USE_FACE_DETECT + if (Wc.face_detect_time) { WcDetectFace(); } +#endif + +#ifdef ENABLE_RTSPSERVER + + if (!rtsp_start && !global_state.wifi_down && Wc.up) { + rtspServer.begin(); + rtsp_start = 1; + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP init")); + rtsp_lastframe_time = millis(); + } + + + if (rtsp_session) { + rtsp_session->handleRequests(0); + + + uint32_t now = millis(); + if ((now-rtsp_lastframe_time) > RTSP_FRAME_TIME) { + rtsp_session->broadcastCurrentFrame(now); + rtsp_lastframe_time = now; + + } + + if (rtsp_session->m_stopped) { + delete rtsp_session; + delete rtsp_streamer; + rtsp_session = NULL; + rtsp_streamer = NULL; + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stopped")); + } + } + else { + rtsp_client = rtspServer.accept(); + if (rtsp_client) { + rtsp_streamer = new OV2640Streamer(&rtsp_client, cam); + rtsp_session = new CRtspSession(&rtsp_client, rtsp_streamer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stream created")); + } + } +#endif +} + +void WcPicSetup(void) { + WebServer_on(PSTR("/wc.jpg"), HandleImage); + WebServer_on(PSTR("/wc.mjpeg"), HandleImage); + WebServer_on(PSTR("/snapshot.jpg"), HandleImage); +} + +void WcShowStream(void) { + if (Settings.webcam_config.stream) { + + if (!CamServer) { + WcStreamControl(); + delay(50); + } + if (CamServer && Wc.up) { + WSContentSend_P(PSTR("

Webcam stream

"), + WiFi.localIP().toString().c_str()); + } + } +} + +void WcInit(void) { + if (!Settings.webcam_config.data) { + Settings.webcam_config.stream = 1; + Settings.webcam_config.resolution = 5; + Settings.webcam_config.flip = 0; + Settings.webcam_config.mirror = 0; + Settings.webcam_config.saturation = 0; + Settings.webcam_config.brightness = 3; + Settings.webcam_config.contrast = 2; + } +} + + + + + +#define D_PRFX_WEBCAM "WC" +#define D_CMND_WC_STREAM "Stream" +#define D_CMND_WC_RESOLUTION "Resolution" +#define D_CMND_WC_MIRROR "Mirror" +#define D_CMND_WC_FLIP "Flip" +#define D_CMND_WC_SATURATION "Saturation" +#define D_CMND_WC_BRIGHTNESS "Brightness" +#define D_CMND_WC_CONTRAST "Contrast" +#define D_CMND_WC_INIT "Init" + +const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" + "|" D_CMND_WC_STREAM "|" D_CMND_WC_RESOLUTION "|" D_CMND_WC_MIRROR "|" D_CMND_WC_FLIP "|" + D_CMND_WC_SATURATION "|" D_CMND_WC_BRIGHTNESS "|" D_CMND_WC_CONTRAST "|" D_CMND_WC_INIT + ; + +void (* const WCCommand[])(void) PROGMEM = { + &CmndWebcam, &CmndWebcamStream, &CmndWebcamResolution, &CmndWebcamMirror, &CmndWebcamFlip, + &CmndWebcamSaturation, &CmndWebcamBrightness, &CmndWebcamContrast, &CmndWebcamInit + }; + +void CmndWebcam(void) { + Response_P(PSTR("{\"" D_PRFX_WEBCAM "\":{\"" D_CMND_WC_STREAM "\":%d,\"" D_CMND_WC_RESOLUTION "\":%d,\"" D_CMND_WC_MIRROR "\":%d,\"" + D_CMND_WC_FLIP "\":%d,\"" + D_CMND_WC_SATURATION "\":%d,\"" D_CMND_WC_BRIGHTNESS "\":%d,\"" D_CMND_WC_CONTRAST "\":%d}}"), + Settings.webcam_config.stream, Settings.webcam_config.resolution, Settings.webcam_config.mirror, + Settings.webcam_config.flip, + Settings.webcam_config.saturation -2, Settings.webcam_config.brightness -2, Settings.webcam_config.contrast -2); +} + +void CmndWebcamStream(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.webcam_config.stream = XdrvMailbox.payload; + if (!Settings.webcam_config.stream) { WcStreamControl(); } + } + ResponseCmndStateText(Settings.webcam_config.stream); +} + +void CmndWebcamResolution(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) { + Settings.webcam_config.resolution = XdrvMailbox.payload; + WcSetOptions(0, Settings.webcam_config.resolution); + } + ResponseCmndNumber(Settings.webcam_config.resolution); +} + +void CmndWebcamMirror(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.webcam_config.mirror = XdrvMailbox.payload; + WcSetOptions(3, Settings.webcam_config.mirror); + } + ResponseCmndStateText(Settings.webcam_config.mirror); +} + +void CmndWebcamFlip(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.webcam_config.flip = XdrvMailbox.payload; + WcSetOptions(2, Settings.webcam_config.flip); + } + ResponseCmndStateText(Settings.webcam_config.flip); +} + +void CmndWebcamSaturation(void) { + if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { + Settings.webcam_config.saturation = XdrvMailbox.payload +2; + WcSetOptions(6, Settings.webcam_config.saturation -2); + } + ResponseCmndNumber(Settings.webcam_config.saturation -2); +} + +void CmndWebcamBrightness(void) { + if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { + Settings.webcam_config.brightness = XdrvMailbox.payload +2; + WcSetOptions(5, Settings.webcam_config.brightness -2); + } + ResponseCmndNumber(Settings.webcam_config.brightness -2); +} + +void CmndWebcamContrast(void) { + if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { + Settings.webcam_config.contrast = XdrvMailbox.payload +2; + WcSetOptions(4, Settings.webcam_config.contrast -2); + } + ResponseCmndNumber(Settings.webcam_config.contrast -2); +} + +void CmndWebcamInit(void) { + WcStreamControl(); + ResponseCmndDone(); +} + + + + + +bool Xdrv81(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_LOOP: + WcLoop(); + break; + case FUNC_WEB_ADD_HANDLER: + WcPicSetup(); + break; + case FUNC_WEB_ADD_MAIN_BUTTON: + WcShowStream(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kWCCommands, WCCommand); + break; + case FUNC_PRE_INIT: + WcInit(); + break; + + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" +#ifdef ESP32 +#ifdef USE_ETHERNET +# 59 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" +#define XDRV_82 82 +# 81 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" +#include + +char eth_hostname[sizeof(my_hostname)]; + +void EthernetEvent(WiFiEvent_t event) { + switch (event) { + case SYSTEM_EVENT_ETH_START: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION)); + ETH.setHostname(eth_hostname); + break; + case SYSTEM_EVENT_ETH_CONNECTED: + AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED " at %dMbps%s"), + ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : ""); + break; + case SYSTEM_EVENT_ETH_GOT_IP: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %s, Hostname %s"), + ETH.macAddress().c_str(), ETH.localIP().toString().c_str(), eth_hostname); + Settings.ip_address[1] = (uint32_t)ETH.gatewayIP(); + Settings.ip_address[2] = (uint32_t)ETH.subnetMask(); + Settings.ip_address[3] = (uint32_t)ETH.dnsIP(); + global_state.eth_down = 0; + break; + case SYSTEM_EVENT_ETH_DISCONNECTED: + AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: Disconnected")); + global_state.eth_down = 1; + break; + case SYSTEM_EVENT_ETH_STOP: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped")); + global_state.eth_down = 1; + break; + default: + break; + } +} + +void EthernetInit(void) { + if (!Settings.flag4.network_ethernet) { return; } + if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: No ETH MDC and/or ETH MDIO GPIO defined")); + return; + } + + + strlcpy(eth_hostname, my_hostname, sizeof(eth_hostname) -5); + strcat(eth_hostname, "_eth"); + + WiFi.onEvent(EthernetEvent); + + int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : -1; + int eth_mdc = Pin(GPIO_ETH_PHY_MDC); + int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); + if (!ETH.begin(Settings.eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings.eth_type, (eth_clock_mode_t)Settings.eth_clk_mode)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error")); + }; +} + +IPAddress EthernetLocalIP(void) { + return ETH.localIP(); +} + +char* EthernetHostname(void) { + return eth_hostname; +} + +String EthernetMacAddress(void) { + return ETH.macAddress(); +} + + + + + +#define D_CMND_ETHADDRESS "EthAddress" +#define D_CMND_ETHTYPE "EthType" +#define D_CMND_ETHCLOCKMODE "EthClockMode" + +const char kEthernetCommands[] PROGMEM = "|" + D_CMND_ETHERNET "|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE; + +void (* const EthernetCommand[])(void) PROGMEM = { + &CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode }; + +void CmndEthernet(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag4.network_ethernet = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndStateText(Settings.flag4.network_ethernet); +} + +void CmndEthAddress(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) { + Settings.eth_address = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndNumber(Settings.eth_address); +} + +void CmndEthType(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + Settings.eth_type = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndNumber(Settings.eth_type); +} + +void CmndEthClockMode(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.eth_clk_mode = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndNumber(Settings.eth_clk_mode); +} + + + + + +bool Xdrv82(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kEthernetCommands, EthernetCommand); + break; + case FUNC_INIT: + EthernetInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_83_esp32watch.ino" +# 20 "/workspace/Tasmota/tasmota/xdrv_83_esp32watch.ino" +#ifdef ESP32 +#ifdef USE_TTGO_WATCH + +#include +#include +#include +#include + +#define XDRV_83 83 + +#define AXP202_INT 35 + +struct TTGO_ADC { + float vbus_v; + float vbus_c; + float batt_v; + float batt_c; + float temp; + uint16_t per; +} ttgo_adc; + +enum { + Q_EVENT_WIFI_SCAN_DONE, + Q_EVENT_WIFI_CONNECT, + Q_EVENT_BMA_INT, + Q_EVENT_AXP_INT, +} ; + +#define BMA423_INT1 39 +#define BMA423_INT2 0 + +#define WATCH_FLAG_SLEEP_MODE _BV(1) +#define WATCH_FLAG_SLEEP_EXIT _BV(2) +#define WATCH_FLAG_BMA_IRQ _BV(3) +#define WATCH_FLAG_AXP_IRQ _BV(4) + +struct TTGO_globs { + AXP20X_Class *ttgo_power = nullptr; + I2CBus *i2c = nullptr; + BMA *bma = nullptr; + QueueHandle_t g_event_queue_handle = NULL; + + EventGroupHandle_t isr_group = NULL; + bool lenergy = false; + bool bma_double_click = false; + bool bma_click = false; + bool bma_button = false; + bool power_ok = false; +} ttgo_globs; + + +void TTGO_Init(void) { + ttgo_globs.ttgo_power = new AXP20X_Class(); + ttgo_globs.i2c = new I2CBus(); + initPower(); + +#ifdef USE_BMA423 + ttgo_globs.bma = new BMA(*ttgo_globs.i2c); + if (ttgo_globs.bma->begin()) { + I2cSetActiveFound(BMA4_I2C_ADDR_SECONDARY, "BMA423"); + } else { + return; + } + + ttgo_globs.bma->attachInterrupt(); + pinMode(BMA423_INT1, INPUT); + attachInterrupt(BMA423_INT1, [] { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group); + if (bits & WATCH_FLAG_SLEEP_MODE) + { + + xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_BMA_IRQ, &xHigherPriorityTaskWoken); + } else + { + + uint8_t data = Q_EVENT_BMA_INT; + xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken); + } + + if (xHigherPriorityTaskWoken) + { + portYIELD_FROM_ISR (); + } + }, RISING); + struct bma423_axes_remap remap_data; + + remap_data.x_axis = 0; + remap_data.x_axis_sign = 1; + remap_data.y_axis = 1; + remap_data.y_axis_sign = 0; + remap_data.z_axis = 2; + remap_data.z_axis_sign = 1; + + ttgo_globs.bma->set_remap_axes(&remap_data); + + ttgo_globs.bma->enableWakeupInterrupt(true); + ttgo_globs.bma->enableAnyNoMotionInterrupt(true); + ttgo_globs.bma->enableAccel(); +#endif +} + +void initPower(void) { + int ret = ttgo_globs.ttgo_power->begin(axpReadBytes, axpWriteBytes); + if (ret == AXP_FAIL) { + + + } else { + I2cSetActiveFound(AXP202_SLAVE_ADDRESS, "AXP202"); + ttgo_globs.power_ok = true; + + + + ttgo_globs.ttgo_power->setShutdownTime(AXP_POWER_OFF_TIME_4S); + + ttgo_globs.ttgo_power->setChgLEDMode(AXP20X_LED_OFF); + + ttgo_globs.ttgo_power->setPowerOutPut(AXP202_EXTEN, false); + + ttgo_globs.ttgo_power->setChargeControlCur(300); + + ttgo_globs.ttgo_power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true); + + ttgo_globs.ttgo_power->adc2Enable(AXP202_TEMP_MONITORING_ADC2, true); + + ttgo_globs.ttgo_power->enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ, AXP202_ON); + ttgo_globs.ttgo_power->clearIRQ(); + + ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO2, AXP202_ON); + + ttgo_globs.isr_group = xEventGroupCreate(); + ttgo_globs.g_event_queue_handle = xQueueCreate(20, sizeof(uint8_t)); + + + pinMode(AXP202_INT, INPUT); + attachInterrupt(AXP202_INT, [] { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group); + if (bits & WATCH_FLAG_SLEEP_MODE) { + + xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_AXP_IRQ, &xHigherPriorityTaskWoken); + } else { + + uint8_t data = Q_EVENT_AXP_INT; + xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken); + } + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR (); + } + }, FALLING); + + } + +} + +static uint8_t axpWriteBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) { + ttgo_globs.i2c->writeBytes(devAddress, regAddress, data, len); + return 0; +} + +static uint8_t axpReadBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) { + ttgo_globs.i2c->readBytes(devAddress, regAddress, data, len); + return 0; +} + + +void TTGO_GetADC(void) { + ttgo_adc.vbus_v = ttgo_globs.ttgo_power->getVbusVoltage(); + ttgo_adc.vbus_c = ttgo_globs.ttgo_power->getVbusCurrent(); + ttgo_adc.batt_v = ttgo_globs.ttgo_power->getBattVoltage(); + ttgo_adc.per = ttgo_globs.ttgo_power->getBattPercentage(); + ttgo_adc.batt_c = ttgo_globs.ttgo_power->getBattDischargeCurrent(); + ttgo_adc.temp = ttgo_globs.ttgo_power->getTemp(); +} + +#ifdef USE_WEBSERVER +const char HTTP_TTGO[] PROGMEM = + "{s}TTGO " "VBUS Voltage" "{m}%s mV" "{e}" + "{s}TTGO " "VBUS Current" "{m}%s mA" "{e}" + "{s}TTGO " "BATT Voltage" "{m}%s mV" "{e}" + "{s}TTGO " "BATT Current" "{m}%s mA" "{e}" + "{s}TTGO " "BATT Percentage" "{m}%d %%" "{e}" + "{s}TTGO " "Temperature" "{m}%s C" "{e}"; +#ifdef USE_BMA423 +const char HTTP_TTGO_BMA[] PROGMEM = + "{s}TTGO " "BMA x" "{m}%d mg" "{e}" + "{s}TTGO " "BMA y" "{m}%d mg" "{e}" + "{s}TTGO " "BMA z" "{m}%d mg" "{e}"; +#endif +#endif + + +void TTGO_WebShow(uint32_t json) { + + if (ttgo_globs.power_ok == false) return; + + TTGO_GetADC(); + + char vstring[32]; + char cstring[32]; + char bvstring[32]; + char bcstring[32]; + char tstring[32]; + dtostrfd(ttgo_adc.vbus_v,2,vstring); + dtostrfd(ttgo_adc.vbus_c,2,cstring); + dtostrfd(ttgo_adc.batt_v,2,bvstring); + dtostrfd(ttgo_adc.batt_c,2,bcstring); + dtostrfd(ttgo_adc.temp,2,tstring); + +#ifdef USE_BMA423 + Accel acc; + bool res = ttgo_globs.bma->getAccel(acc); +#endif + + if (json) { + ResponseAppend_P(PSTR(",\"TTGO_WATCH\":{\"VBV\":%s,\"VBC\":%s,\"BV\":%s,\"BC\":%s,\"BP\":%d,\"CT\":%s"), + vstring, cstring, bvstring, bcstring, ttgo_adc.per, tstring); +#ifdef USE_BMA423 + ResponseAppend_P(PSTR(",\"BMAX\":%d,\"BMAY\":%d,\"BMAZ\":%d"),acc.x,acc.y,acc.z); +#endif + ResponseJsonEnd(); + } else { + WSContentSend_PD(HTTP_TTGO,vstring,cstring,bvstring,bcstring,ttgo_adc.per,tstring); +#ifdef USE_BMA423 + WSContentSend_PD(HTTP_TTGO_BMA,acc.x,acc.y,acc.z); +#endif + } +} + + +void enableLDO3(bool en = true) { + if (!ttgo_globs.ttgo_power) return; + ttgo_globs.ttgo_power->setLDO3Mode(1); + ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO3, en); +} + +void TTGO_audio_power(bool power) { + enableLDO3(power); +} + +const char TTGO_Commands[] PROGMEM = "TTGO|" + "LSLP"; + +void (* const TTTGO_Command[])(void) PROGMEM = { + &TTGO_LightSleep}; + +void TTGO_LightSleep(void) { +int32_t ttgo_sleeptime; + + + if ((abs(XdrvMailbox.payload) >= 10) && (abs(XdrvMailbox.payload) <= 3600*24)) { + ttgo_sleeptime = XdrvMailbox.payload; + } else { + ttgo_sleeptime = 0; + } + + ResponseCmndNumber(ttgo_sleeptime); + + TTGO_Sleep(ttgo_sleeptime); + +} + +void TTGO_Sleep(int32_t stime) { +int32_t ttgo_sleeptime; + + ttgo_sleeptime = stime; + +#ifdef USE_DISPLAY + DisplayOnOff(0); +#endif + if (ttgo_sleeptime>=0) { + + WifiShutdown(); + SettingsSaveAll(); + RtcSettingsSave(); + ttgo_globs.lenergy = true; + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_2M); + xEventGroupSetBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE); + gpio_wakeup_enable ((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL); + gpio_wakeup_enable ((gpio_num_t)BMA423_INT1, GPIO_INTR_HIGH_LEVEL); + esp_sleep_enable_gpio_wakeup(); + if (ttgo_sleeptime) { + esp_sleep_enable_timer_wakeup(ttgo_sleeptime * 1000000); + } + esp_light_sleep_start(); + } else { + ttgo_globs.ttgo_power->setPowerOutPut(0xFF, false); + Settings.deepsleep = -ttgo_sleeptime; +#ifdef USE_DEEPSLEEP + RtcSettings.nextwakeup = 0; + deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; + if (deepsleep_flag) { + if (!Settings.tele_period) { + Settings.tele_period = TELE_PERIOD; + } + } +#endif + return; + } + + if (ttgo_sleeptime) { + ttgo_globs.lenergy = false; + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); +#ifdef USE_DISPLAY + DisplayOnOff(1); +#endif + } else { + while (ttgo_globs.lenergy == true) { + TTGO_loop(0); + OsWatchLoop(); + } + } +} + + +void TTGO_loop(uint32_t flg) { +bool rlst; +uint8_t data; + + if (!flg) { + + EventBits_t bits = xEventGroupGetBits(ttgo_globs.isr_group); + if (bits & WATCH_FLAG_SLEEP_EXIT) { + if (ttgo_globs.lenergy) { + ttgo_globs.lenergy = false; + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); +#ifdef USE_DISPLAY + DisplayOnOff(1); +#endif + } + +#ifdef USE_BMA423 + if (bits & WATCH_FLAG_BMA_IRQ) { + do { + rlst = ttgo_globs.bma->readInterrupt(); + } while (!rlst); + xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_BMA_IRQ); + } +#endif + + if (bits & WATCH_FLAG_AXP_IRQ) { + ttgo_globs.ttgo_power->readIRQ(); + ttgo_globs.ttgo_power->clearIRQ(); + xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_AXP_IRQ); + } + xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT); + xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE); + } + } else { + + if (xQueueReceive(ttgo_globs.g_event_queue_handle, &data, 5 / portTICK_RATE_MS) == pdPASS) { + switch (data) { +#ifdef USE_BMA423 + case Q_EVENT_BMA_INT: + + do { + rlst = ttgo_globs.bma->readInterrupt(); + } while (!rlst); + + if (ttgo_globs.bma->isDoubleClick()) { + ttgo_globs.bma_double_click = true; + + } + if (ttgo_globs.bma->isAnyNoMotion()) { + ttgo_globs.bma_click = true; + + } + + + if (ttgo_globs.bma->isStepCounter()) { + + } + break; +#endif + case Q_EVENT_AXP_INT: + + ttgo_globs.ttgo_power->readIRQ(); + if (ttgo_globs.ttgo_power->isVbusPlugInIRQ()) { + + + } + if (ttgo_globs.ttgo_power->isVbusRemoveIRQ()) { + + + } + if (ttgo_globs.ttgo_power->isChargingDoneIRQ()) { + + + } + if (ttgo_globs.ttgo_power->isPEKShortPressIRQ()) { + ttgo_globs.bma_button = true; + + } + ttgo_globs.ttgo_power->clearIRQ(); + break; + default: + break; + } + } + } +} + +bool TTGO_doubleclick(void) { + bool retval = ttgo_globs.bma_double_click; + ttgo_globs.bma_double_click = false; + return retval; +} + +bool TTGO_button(void) { + bool retval = ttgo_globs.bma_button; + ttgo_globs.bma_button = false; + return retval; +} + + + + + +bool Xdrv83(uint8_t function) { + bool result = false; + + switch (function) { + + case FUNC_WEB_SENSOR: +#ifdef USE_WEBSERVER + TTGO_WebShow(0); +#endif + break; + case FUNC_JSON_APPEND: + TTGO_WebShow(1); + break; + case FUNC_COMMAND: + result = DecodeCommand(TTGO_Commands, TTTGO_Command); + break; + case FUNC_INIT: + TTGO_Init(); + break; + case FUNC_LOOP: + TTGO_loop(1); + break; + + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdrv_99_debug.ino" +# 22 "/workspace/Tasmota/tasmota/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_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" +#define D_CMND_I2CWRITE "I2CWrite" +#define D_CMND_I2CREAD "I2CRead" +#define D_CMND_I2CSTRETCH "I2CStretch" +#define D_CMND_I2CCLOCK "I2CClock" +#define D_CMND_SERBUFF "SerBufSize" + +const char kDebugCommands[] PROGMEM = "|" + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" +#ifdef USE_WEBSERVER + D_CMND_CFGXOR "|" +#endif + D_CMND_CPUCHECK "|" D_CMND_SERBUFF "|" +#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 "|" +#ifdef USE_I2C + D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK +#endif + ; + +void (* const DebugCommand[])(void) PROGMEM = { + &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, +#ifdef USE_WEBSERVER + &CmndCfgXor, +#endif + &CmndCpuCheck, &CmndSerBufSize, +#ifdef DEBUG_THEO + &CmndException, +#endif + &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, +#ifdef USE_I2C + &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock +#endif + }; + +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) +{ +# 145 "/workspace/Tasmota/tasmota/xdrv_99_debug.ino" + if (1 == type) { + char svalue[10]; + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); + } +# 159 "/workspace/Tasmota/tasmota/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*ssleep)) / (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*ssleep)) / (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; + } + } +} + + + +#ifdef ESP8266 + + + + +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); +} + +#else + +void DebugFreeMem(void) +{ + register uint8_t *sp asm("a1"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL), XdrvMailbox.data); +} + +#endif + + + +void DebugRtcDump(char* parms) +{ +#ifdef ESP8266 + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; +# 239 "/workspace/Tasmota/tasmota/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); + } +#endif +} + + + +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(Settings)+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(Settings)) address = sizeof(Settings) -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(Settings)) address = sizeof(Settings) -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); +} + +void SetFlashMode(uint8_t mode) +{ +#ifdef ESP8266 + 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; +#endif +} + + + + + +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_WEBSERVER +void CmndCfgXor(void) +{ + if (XdrvMailbox.data_len > 0) { + Web.config_xor_on_set = XdrvMailbox.payload; + } + char temp[10]; + snprintf_P(temp, sizeof(temp), PSTR("0x%02X"), Web.config_xor_on_set); + ResponseCmndChar(temp); +} +#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 CmndSerBufSize(void) +{ + if (XdrvMailbox.data_len > 0) { + Serial.setRxBufferSize(XdrvMailbox.payload); + } +#ifdef ESP8266 + ResponseCmndNumber(Serial.getRxBufferSize()); +#else + ResponseCmndDone(); +#endif +} + +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) +{ +#ifdef ESP8266 + + + + 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(); +#endif +} + +#ifdef USE_I2C +void CmndI2cWrite(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 1) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + + Wire.beginTransmission(buffer[0]); + for (uint32_t i = 1; i < index; i++) { + Wire.write(buffer[i]); + } + int result = Wire.endTransmission(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); + } + } + ResponseCmndDone(); +} + +void CmndI2cRead(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 0) { + uint8_t size = 1; + if (index > 1) { + size = buffer[1]; + } + Wire.requestFrom(buffer[0], size); + index = 0; + while (Wire.available() && index < sizeof(buffer)) { + buffer[index++] = Wire.read(); + } + if (index > 0) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + } + } + } + ResponseCmndDone(); +} + +void CmndI2cStretch(void) +{ +#ifdef ESP8266 + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClockStretchLimit(XdrvMailbox.payload); + } + ResponseCmndDone(); +#endif +} + +void CmndI2cClock(void) +{ + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClock(XdrvMailbox.payload); + } + ResponseCmndDone(); +} +#endif + + + + + +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 "/workspace/Tasmota/tasmota/xdrv_interface.ino" +# 20 "/workspace/Tasmota/tasmota/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 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; + + DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); + + 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 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_LCD + +#define XDSP_01 1 +#define XI2C_03 3 + +#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 (I2cSetDevice(LCD_ADDRESS1)) { + Settings.display_address[0] = LCD_ADDRESS1; + Settings.display_model = XDSP_01; + } + else if (I2cSetDevice(LCD_ADDRESS2)) { + Settings.display_address[0] = LCD_ADDRESS2; + Settings.display_model = XDSP_01; + } + } + + if (XDSP_01 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "LCD"); + + 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) +{ + if (dsp_flag) { + dsp_x--; + dsp_y--; + } + lcd->setCursor(dsp_x, dsp_y); + lcd->print(dsp_str); +} + +void LcdDisplayOnOff() +{ + if (disp_power) { + 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) +{ + if (!I2cEnabled(XI2C_03)) { return false; } + + bool result = false; + + 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(); + break; + case FUNC_DISPLAY_CLEAR: + lcd->clear(); + break; +# 238 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" + case FUNC_DISPLAY_DRAW_STRING: + LcdDrawStringAt(); + break; + + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + LcdRefresh(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdsp_02_ssd1306.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_02_ssd1306.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1306 + +#define XDSP_02 2 +#define XI2C_04 4 + +#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(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_02; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_02; + } + } + + if (XDSP_02 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SSD1306"); + + if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { + Settings.display_width = 128; + } + if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { + Settings.display_height = 64; + } + + uint8_t reset_pin = -1; + if (PinUsed(GPIO_OLED_RESET)) { + 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], reset_pin >= 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); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + 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) +{ + if (!I2cEnabled(XI2C_04)) { return false; } + + bool result = false; + + 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 "/workspace/Tasmota/tasmota/xdsp_03_matrix.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_03_matrix.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_MATRIX + +#define XDSP_03 3 +#define XI2C_05 5 + +#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 (I2cSetDevice(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]) { + I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); + 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) +{ + if (!I2cEnabled(XI2C_05)) { return false; } + + bool result = false; + + 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 "/workspace/Tasmota/tasmota/xdsp_04_ili9341.ino" +# 20 "/workspace/Tasmota/tasmota/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_top = TFT_TOP; +uint16_t tft_bottom = TFT_BOTTOM; +uint16_t tft_scroll = TFT_TOP; +uint16_t tft_cols = 0; + + + +bool Ili9341Header(void) { + if (Settings.display_cols[0] != tft_cols) { + tft_cols = Settings.display_cols[0]; + if (tft_cols > 17) { + tft_top = TFT_TOP; + tft_bottom = TFT_BOTTOM; + } else { + tft_top = 0; + tft_bottom = 0; + } + tft_scroll = tft_top; + tft->setScrollMargins(tft_top, tft_bottom); + } + return (tft_cols > 17); +} + +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 { + Ili9341Header(); + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + tft->setTextSize(2); + + + } +} + +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(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("DSP: ILI9341")); + } +} + +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() +{ + + + if (PinUsed(GPIO_BACKLIGHT)) { + pinMode(Pin(GPIO_BACKLIGHT), OUTPUT); + digitalWrite(Pin(GPIO_BACKLIGHT), 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 = (tft_top) ? theight : 0; + 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) { + + + + if (Ili9341Header()) { + char tftdt[Settings.display_cols[0] +1]; + char date4[11]; + uint8_t time_size = (Settings.display_cols[0] >= 20) ? 9 : 6; + char spaces[Settings.display_cols[0] - (8 + time_size)]; + char time[time_size]; + + tft->setTextSize(Settings.display_size); + 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(spaces, 0x20, sizeof(spaces)); + spaces[sizeof(spaces) -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, spaces, time); + + tft->print(tftdt); + } else { + tft->setCursor(0, 0); + } + + 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: + Ili9341DisplayOnOff(); + 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_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 "/workspace/Tasmota/tasmota/xdsp_05_epaper_29.ino" +# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_CLK) && PinUsed(GPIO_SPI_MOSI)) { + 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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_MOSI)) { + 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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xdsp_06_epaper_42.ino" +# 21 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) { + epd42->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); + } else { + free(buffer); + return; + } + #else + if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { + 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 "/workspace/Tasmota/tasmota/xdsp_07_sh1106.ino" +# 20 "/workspace/Tasmota/tasmota/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 XI2C_06 6 + +#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 (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_07; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_07; + } + } + + if (XDSP_07 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SH1106"); + + 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); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + 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) +{ + if (!I2cEnabled(XI2C_06)) { return false; } + + bool result = false; + + 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 "/workspace/Tasmota/tasmota/xdsp_08_ILI9488.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_08_ILI9488.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9488 + +#define XDSP_08 8 +#define XI2C_38 38 + +#define COLORED 1 +#define UNCOLORED 0 + + + +#define USE_TINY_FONT + + +#include +uint8_t ili9488_ctouch_counter = 0; + + +#define BACKPLANE_PIN 2 + +extern uint8_t *buffer; +extern uint8_t color_type; +ILI9488 *ili9488; +extern const uint16_t picture[]; + + + +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 (PinUsed(GPIO_BACKLIGHT)) { + bppin=Pin(GPIO_BACKLIGHT); + } + +#ifdef ESP32 +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 23 +#undef HW_SPI_MISO +#define HW_SPI_MISO 19 +#undef HW_SPI_CLK +#define HW_SPI_CLK 18 +#else +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 13 +#undef HW_SPI_MISO +#define HW_SPI_MISO 12 +#undef HW_SPI_CLK +#define HW_SPI_CLK 14 +#endif + + + if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { + ili9488 = new ILI9488(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK),bppin); + } else { + if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { + ili9488 = new ILI9488(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK),bppin); + } else { + return; + } + } + + 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; + +#ifdef USE_FT5206 + Touch_Init(Wire); +#endif + } +} + +#ifdef USE_FT5206 +#ifdef USE_TOUCH_BUTTONS + +void ILI9488_RotConvert(int16_t *x, int16_t *y) { +int16_t temp; + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + temp=*y; + *y=renderer->height()-*x; + *x=temp; + break; + case 1: + break; + case 2: + break; + case 3: + temp=*y; + *y=*x; + *x=renderer->width()-temp; + break; + } + } +} + + +void ILI9488_CheckTouch(void) { + ili9488_ctouch_counter++; + if (2 == ili9488_ctouch_counter) { + + ili9488_ctouch_counter = 0; + Touch_Check(ILI9488_RotConvert); + } +} +#endif +#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 (FT5206_found) { + ILI9488_CheckTouch(); + } +#endif + break; + } + } + + return result; +} + +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdsp_09_SSD1351.ino" +# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)){ + ssd1351 = new SSD1351(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); + } else { + if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { + ssd1351 = new SSD1351(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK)); + } else { + return; + } + } + + delay(100); + 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); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + 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 "/workspace/Tasmota/tasmota/xdsp_10_RA8876.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_10_RA8876.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_RA8876 + +#define XDSP_10 10 +#define XI2C_39 39 + +#define COLORED 1 +#define UNCOLORED 0 + + + +#define USE_TINY_FONT + +#include + +uint8_t ra8876_ctouch_counter = 0; +extern uint8_t *buffer; +extern uint8_t color_type; +RA8876 *ra8876; + + +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; + +#ifdef ESP32 +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 23 +#undef HW_SPI_MISO +#define HW_SPI_MISO 19 +#undef HW_SPI_CLK +#define HW_SPI_CLK 18 +#else +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 13 +#undef HW_SPI_MISO +#define HW_SPI_MISO 12 +#undef HW_SPI_CLK +#define HW_SPI_CLK 14 +#endif + + + if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { + ra8876 = new RA8876(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_MISO),Pin(GPIO_SSPI_SCLK),Pin(GPIO_BACKLIGHT)); + } else { + if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { + 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; + +#ifdef USE_FT5206 + Touch_Init(Wire); +#endif + + } +} + + +#ifdef USE_FT5206 +#ifdef USE_TOUCH_BUTTONS + + +void RA8876_RotConvert(int16_t *x, int16_t *y) { +int16_t temp; + if (renderer) { + *x=*x*renderer->width()/800; + *y=*y*renderer->height()/480; + + *x = renderer->width() - *x; + *y = renderer->height() - *y; + } +} + + +void RA8876_CheckTouch(void) { + ra8876_ctouch_counter++; + if (2 == ra8876_ctouch_counter) { + + ra8876_ctouch_counter = 0; + Touch_Check(RA8876_RotConvert); + } +} +#endif +#endif +# 324 "/workspace/Tasmota/tasmota/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_FT5206 + if (FT5206_found) RA8876_CheckTouch(); +#endif + break; + } + } + return result; +} +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SEVENSEG + +#define XDSP_11 11 +#define XI2C_47 47 + +#include +#include +#include + +Adafruit_7segment *sevenseg[8]; +uint8_t sevensegs = 0; +uint8_t sevenseg_state = 0; + + + +void SevensegWrite(void) +{ + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->writeDisplay(); + } +} + +void SevensegClear(void) +{ + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->clear(); + } + SevensegWrite(); +} + + + + +void SevensegInitMode(void) +{ + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->setBrightness(Settings.display_dimmer); + sevenseg[i]->blinkRate(0); + } + SevensegClear(); +} + +void SevensegInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + SevensegInitMode(); + break; + } +} + +void SevensegInitDriver(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(Settings.display_address[0])) { + Settings.display_model = XDSP_11; + } + } + + if (XDSP_11 == Settings.display_model) { + sevenseg_state = 1; + for (sevensegs = 0; sevensegs < 8; sevensegs++) { + if (Settings.display_address[sevensegs]) { + I2cSetActiveFound(Settings.display_address[sevensegs], "SevenSeg"); + sevenseg[sevensegs] = new Adafruit_7segment(); + sevenseg[sevensegs]->begin(Settings.display_address[sevensegs]); + } else { + break; + } + } + + Settings.display_width = 4; + Settings.display_height = sevensegs; + + SevensegInitMode(); + } +} + +void SevensegOnOff(void) +{ + if (!disp_power) { SevensegClear(); } +} + +void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + enum OutNumType {DECIMAL, HEXADECIMAL, FLOAT, SEGMENTS}; + int16_t number = 0; + double numberf = 0; + boolean hasnumber= false; + uint8_t dots= 0; + OutNumType outnumtype= DECIMAL; + uint8 fds = 0; + boolean done= false; + boolean s= false; + uint8_t unit= y; + char *buf; + + if ((unit>=sevensegs) || (unit<0)) { + unit=0; + } + + for (int i=0; (str[i]!='\0') && (!done); i++) { +# 155 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" + switch (str[i]) { + case 'x': + + outnumtype = HEXADECIMAL; + break; + case 'f': + + outnumtype = FLOAT; + break; + case ':': + dots |= 0x02; + break; + case '^': + dots |= 0x08; + break; + case 'v': + dots |= 0x04; + break; + case '.': + dots |= 0x10; + break; + case 's': + s = true; + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + hasnumber= true; + if (outnumtype == FLOAT) { + + numberf = atof(str+i); + + buf= str+i; + char *cp= strchr(buf, '.'); + if (cp == NULL) { + fds= 0; + } else { + fds= buf+strlen(buf) - 1 - cp; + } + } else { + + number = atoi(str+i); + } + done = true; + break; + case 'z': + hasnumber=false; + dots=0; + s=false; + sevenseg[unit]->clear(); + break; + case 'r': + outnumtype= SEGMENTS; + break; + default: + break; + } + } + + + if (hasnumber) { + if (s) { + + int hour = number/60/60; + int minute = (number/60)%60; + + if (hour) { + + number = hour*100 + minute; + } else { + + number = minute*100 + number%60; + } + } + + if (outnumtype == HEXADECIMAL) { + + sevenseg[unit]->print(number, HEX); + } else if (outnumtype == FLOAT) { + + sevenseg[unit]->printFloat(numberf, fds, 10); + } else if (outnumtype == SEGMENTS) { + + sevenseg[unit]->writeDigitRaw(x, number); + } else { + + sevenseg[unit]->print(number, DEC); + } + } + + if (dots) { + sevenseg[unit]->writeDigitRaw(2, dots); + } + + sevenseg[unit]->writeDisplay(); +} + + + +#ifdef USE_DISPLAY_MODES1TO5 +void SevensegTime(boolean time_24) +{ + + uint hours = RtcTime.hour; + uint minutes = RtcTime.minute; + uint second = RtcTime.second; + uint16_t displayValue = hours * 100 + minutes; + uint16_t dots = 0; + + + if (!time_24) { + + if (hours > 12) { + displayValue -= 1200; + } + + else if (hours == 0) { + displayValue += 1200; + } + } + + + + sevenseg[0]->print(displayValue, DEC); + + + + + if (time_24) { + if (hours == 0) { + + sevenseg[0]->writeDigitNum(1, 0); + + if (minutes < 10) { + sevenseg[0]->writeDigitNum(3, 0); + } + } + if (hours < 10) { + + sevenseg[0]->writeDigitNum(0, 0); + } + } else { + + if (hours >= 12) { + dots |= 0x10; + } + } + + sevenseg[0]->writeDigitRaw(2, dots |= ((second%2) << 1)); + sevenseg[0]->writeDisplay(); +} + +void SevensegRefresh(void) +{ + if (disp_power) { + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SevensegTime(false); + break; + case 2: + SevensegTime(true); + break; + case 4: + case 3: + case 5: { + break; + } + } + } + } +} + +#endif + + + + + +bool Xdsp11(uint8_t function) +{ + if (!I2cEnabled(XI2C_47)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SevensegInitDriver(); + } + else if (XDSP_11 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + SevensegInit(dsp_init); + break; + case FUNC_DISPLAY_CLEAR: + SevensegClear(); + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SevensegRefresh(); + break; +#endif + case FUNC_DISPLAY_POWER: + SevensegOnOff(); + break; + case FUNC_DISPLAY_DRAW_STRING: + SevensegDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdsp_12_ST7789.ino" +# 21 "/workspace/Tasmota/tasmota/xdsp_12_ST7789.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ST7789 + +#define XDSP_12 12 +#define XI2C_38 38 + +#undef COLORED +#define COLORED 1 +#undef UNCOLORED +#define UNCOLORED 0 + + +#undef FT5206_address +#define FT5206_address 0x38 + + + +#undef USE_TINY_FONT +#define USE_TINY_FONT + + +#include +#include + + +#define BACKPLANE_PIN 2 + +extern uint8_t *buffer; +extern uint8_t color_type; +Arduino_ST7789 *st7789; + +#ifdef USE_FT5206 +uint8_t st7789_ctouch_counter = 0; +#endif + + + +void ST7789_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_12; + } + + if (XDSP_12 == Settings.display_model) { + + if (Settings.display_width != ST7789_TFTWIDTH) { + Settings.display_width = ST7789_TFTWIDTH; + } + if (Settings.display_height != ST7789_TFTHEIGHT) { + Settings.display_height = ST7789_TFTHEIGHT; + } + + + buffer=NULL; + + + fg_color = ST7789_WHITE; + bg_color = ST7789_BLACK; + + int8_t bppin=BACKPLANE_PIN; + if (PinUsed(GPIO_BACKLIGHT)) { + bppin=Pin(GPIO_BACKLIGHT); + } + + int8_t reset = -1; + if (PinUsed(GPIO_OLED_RESET)) { + reset=Pin(GPIO_OLED_RESET); + } + + int8_t cs = -1; + if (PinUsed(GPIO_SSPI_CS)) { + cs=Pin(GPIO_SSPI_CS); + } else if (PinUsed(GPIO_SPI_CS)) { + cs=Pin(GPIO_SPI_CS); + } + +#ifdef ESP32 +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 23 +#undef HW_SPI_CLK +#define HW_SPI_CLK 18 +#else +#undef HW_SPI_MOSI +#define HW_SPI_MOSI 13 +#undef HW_SPI_CLK +#define HW_SPI_CLK 14 +#endif + + + + if ((Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) { + st7789 = new Arduino_ST7789(Pin(GPIO_SPI_DC), reset, cs, bppin); + } else { + if ((PinUsed(GPIO_SSPI_CS) || PinUsed(GPIO_OLED_RESET)) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) { + st7789 = new Arduino_ST7789(Pin(GPIO_SSPI_DC), reset, Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), cs, bppin); + } else { + return; + } + } + st7789->init(Settings.display_width,Settings.display_height); + renderer = st7789; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(ST7789_WHITE,ST7789_BLACK); + renderer->DrawStringAt(30, 100, "ST7789 TFT!", ST7789_WHITE,0); + delay(1000); +#endif + + color_type = COLOR_COLOR; + +#ifdef ESP32 +#ifdef USE_FT5206 + + #define SDA_2 23 + #define SCL_2 32 + Wire1.begin(SDA_2, SCL_2, 400000); + Touch_Init(Wire1); +#endif +#endif + + } +} + +#ifdef ESP32 +#ifdef USE_FT5206 +#ifdef USE_TOUCH_BUTTONS + +void ST7789_RotConvert(int16_t *x, int16_t *y) { +int16_t temp; + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + break; + case 1: + temp=*y; + *y=renderer->height()-*x; + *x=temp; + break; + case 2: + *x=renderer->width()-*x; + *y=renderer->height()-*y; + break; + case 3: + temp=*y; + *y=*x; + *x=renderer->width()-temp; + break; + } + } +} + + +void ST7789_CheckTouch() { +st7789_ctouch_counter++; + if (2 == st7789_ctouch_counter) { + + st7789_ctouch_counter = 0; + Touch_Check(ST7789_RotConvert); + } +} +#endif +#endif +#endif + + + + + +bool Xdsp12(uint8_t function) +{ + bool result = false; + + + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + ST7789_InitDriver(); + } + else if (XDSP_12 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_FT5206 +#ifdef USE_TOUCH_BUTTONS + if (FT5206_found) { + ST7789_CheckTouch(); + } +#endif +#endif + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xdsp_interface.ino" +# 20 "/workspace/Tasmota/tasmota/xdsp_interface.ino" +#if defined(USE_I2C) || defined(USE_SPI) +#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 "/workspace/Tasmota/tasmota/xdsp_interface.ino" +uint8_t XdspPresent(void) +{ + return xdsp_present; +} + +bool XdspCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); + + 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 +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" +#ifdef USE_LIGHT +#ifdef USE_WS2812 +# 38 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" +#define XLGT_01 1 + +const uint8_t WS2812_SCHEMES = 8; + +const char kWs2812Commands[] PROGMEM = "|" + D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; + +void (* const Ws2812Command[])(void) PROGMEM = { + &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; + +#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 + +#ifdef USE_WS2812_INVERTED + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266DmaInvertedWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266DmaInvertedSk6812Method selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) + typedef NeoEsp8266DmaInvertedApa106Method selectedNeoSpeedType; +#else + typedef NeoEsp8266DmaInverted800KbpsMethod selectedNeoSpeedType; +#endif + +#else + +#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 + +#endif + +#else + +#ifdef USE_WS2812_INVERTED + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266BitBangWs2812xInvertedMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266BitBangSk6812InvertedMethod selectedNeoSpeedType; +#else + typedef NeoEsp8266BitBang400KbpsInvertedMethod 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 + +#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 -1] = { + 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 }; + +struct WS2812 { + uint8_t show_next = 1; + uint8_t scheme_offset = 0; + bool suspend_update = false; +} Ws2812; + + + +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 Ws2812Clear(void) +{ + strip->ClearTo(0); + strip->Show(); + Ws2812.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 (!Ws2812.suspend_update) { + strip->Show(); + Ws2812.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 Ws2812ForceSuspend (void) +{ + Ws2812.suspend_update = true; +} + +void Ws2812ForceUpdate (void) +{ + Ws2812.suspend_update = false; + strip->Show(); + Ws2812.show_next = 1; +} + + + +bool Ws2812SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); + + return true; +} + +void Ws2812ShowScheme(void) +{ + uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; + + switch (scheme) { + case 0: + if ((1 == state_250mS) || (Ws2812.show_next)) { + Ws2812Clock(); + Ws2812.show_next = 0; + } + break; + default: + if (1 == Settings.light_fade) { + Ws2812Gradient(scheme -1); + } else { + Ws2812Bars(scheme -1); + } + Ws2812.show_next = 1; + break; + } +} + +void Ws2812ModuleSelected(void) +{ + if (PinUsed(GPIO_WS2812)) { + + + strip = new NeoPixelBus(WS2812_MAX_LEDS, Pin(GPIO_WS2812)); + strip->Begin(); + + Ws2812Clear(); + + Ws2812.scheme_offset = Light.max_scheme +1; + Light.max_scheme += WS2812_SCHEMES; + +#if (USE_WS2812_CTYPE > NEO_3LED) + light_type = LT_RGBW; +#else + light_type = LT_RGB; +#endif + light_flg = XLGT_01; + } +} + + + +void CmndLed(void) +{ + if ((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 ((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 ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { + Settings.light_rotation = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_rotation); +} + +void CmndWidth(void) +{ + if ((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]); + } + } +} + + + + + +bool Xlgt01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Ws2812SetChannels(); + break; + case FUNC_SET_SCHEME: + Ws2812ShowScheme(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kWs2812Commands, Ws2812Command); + break; + case FUNC_MODULE_INIT: + Ws2812ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_02_my92x1.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_02_my92x1.ino" +#ifdef USE_LIGHT +#ifdef USE_MY92X1 + + + + +#define XLGT_02 2 + +struct MY92X1 { + uint8_t pdi_pin = 0; + uint8_t pdcki_pin = 0; + uint8_t model = 0; +} My92x1; + +extern "C" { + void os_delay_us(unsigned int); +} + +void LightDiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdi_pin, HIGH); + digitalWrite(My92x1.pdi_pin, LOW); + } +} + +void LightDckiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdcki_pin, HIGH); + digitalWrite(My92x1.pdcki_pin, LOW); + } +} + +void LightMy92x1Write(uint8_t data) +{ + for (uint32_t i = 0; i < 4; i++) { + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, HIGH); + data = data << 1; + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, LOW); + data = data << 1; + } +} + +void LightMy92x1Init(void) +{ + uint8_t chips[3] = { 1, 2, 2 }; + + LightDckiPulse(chips[My92x1.model] * 32); + os_delay_us(12); + + + LightDiPulse(12); + os_delay_us(12); + for (uint32_t n = 0; n < chips[My92x1.model]; 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[3] = { 4, 6, 6 }; + + uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, + { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, + { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; + + os_delay_us(12); + for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { + LightMy92x1Write(duty[My92x1.model][channel]); + } + os_delay_us(12); + LightDiPulse(8); + os_delay_us(12); +} + + + +bool My92x1SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + + return true; +} + +void My92x1ModuleSelected(void) +{ + if (PinUsed(GPIO_DCKI) && PinUsed(GPIO_DI)) { + My92x1.pdi_pin = Pin(GPIO_DI); + My92x1.pdcki_pin = Pin(GPIO_DCKI); + + pinMode(My92x1.pdi_pin, OUTPUT); + pinMode(My92x1.pdcki_pin, OUTPUT); + digitalWrite(My92x1.pdi_pin, LOW); + digitalWrite(My92x1.pdcki_pin, LOW); + + My92x1.model = 2; + light_type = LT_RGBW; + if (AILIGHT == my_module_type) { + My92x1.model = 0; + + } + else if (SONOFF_B1 == my_module_type) { + My92x1.model = 1; + light_type = LT_RGBWC; + } + + LightMy92x1Init(); + + light_flg = XLGT_02; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); + } +} + + + + + +bool Xlgt02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = My92x1SetChannels(); + break; + case FUNC_MODULE_INIT: + My92x1ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" +#ifdef USE_LIGHT +#ifdef USE_SM16716 + + + + + + + +#define XLGT_03 3 + +#define D_LOG_SM16716 "SM16716: " + +struct SM16716 { + uint8_t pin_clk = 0; + uint8_t pin_dat = 0; + uint8_t pin_sel = 0; + bool enabled = false; +} Sm16716; + +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) { + bool should_enable = (duty_r | duty_g | duty_b); + if (!Sm16716.enabled && should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); + Sm16716.enabled = true; + digitalWrite(Sm16716.pin_sel, HIGH); + + + delayMicroseconds(1000); + SM16716_Init(); + } + else if (Sm16716.enabled && !should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); + Sm16716.enabled = false; + 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); +} +# 111 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" +void SM16716_Init(void) +{ + for (uint32_t t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } +} + + + +bool Sm16716SetChannels(void) +{ +# 132 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + + return true; +} + +void Sm16716ModuleSelected(void) +{ + if (PinUsed(GPIO_SM16716_CLK) && PinUsed(GPIO_SM16716_DAT)) { + Sm16716.pin_clk = Pin(GPIO_SM16716_CLK); + Sm16716.pin_dat = Pin(GPIO_SM16716_DAT); + Sm16716.pin_sel = Pin(GPIO_SM16716_SEL); +# 161 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" + 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(); + } + + LightPwmOffset(LST_RGB); + light_type += LST_RGB; + light_flg = XLGT_03; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); + } +} + + + + + +bool Xlgt03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm16716SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm16716ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" +#ifdef USE_LIGHT +#ifdef USE_SM2135 +# 31 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" +#define XLGT_04 4 + +#define SM2135_ADDR_MC 0xC0 +#define SM2135_ADDR_CH 0xC1 +#define SM2135_ADDR_R 0xC2 +#define SM2135_ADDR_G 0xC3 +#define SM2135_ADDR_B 0xC4 +#define SM2135_ADDR_C 0xC5 +#define SM2135_ADDR_W 0xC6 + +#define SM2135_RGB 0x00 +#define SM2135_CW 0x80 + +#define SM2135_10MA 0x00 +#define SM2135_15MA 0x01 +#define SM2135_20MA 0x02 +#define SM2135_25MA 0x03 +#define SM2135_30MA 0x04 +#define SM2135_35MA 0x05 +#define SM2135_40MA 0x06 +#define SM2135_45MA 0x07 +#define SM2135_50MA 0x08 +#define SM2135_55MA 0x09 +#define SM2135_60MA 0x0A + +enum Sm2135Color { SM2135_WCGRB, SM2135_WCBGR }; + + +const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; + +struct SM2135 { + uint8_t clk = 0; + uint8_t data = 0; + uint8_t model = SM2135_WCGRB; +} Sm2135; + + + + + +const uint8_t SM2135_DELAY = 4; + +void Sm2135SetLow(uint8_t pin) { + noInterrupts(); + digitalWrite(pin, LOW); + pinMode(pin, OUTPUT); + interrupts(); +} + +void Sm2135SetHigh(uint8_t pin) { + noInterrupts(); + pinMode(pin, INPUT_PULLUP); + interrupts(); +} + +bool Sm2135Init(void) { + digitalWrite(Sm2135.data, LOW); + digitalWrite(Sm2135.clk, LOW); + Sm2135SetHigh(Sm2135.data); + Sm2135SetHigh(Sm2135.clk); + return (!((digitalRead(Sm2135.data) == LOW || digitalRead(Sm2135.clk) == LOW))); +} + +bool Sm2135Write(uint8_t value) { + for (uint8_t curr = 0X80; curr != 0; curr >>= 1) { + if (curr & value) { + Sm2135SetHigh(Sm2135.data); + } else { + Sm2135SetLow(Sm2135.data); + } + Sm2135SetHigh(Sm2135.clk); + delayMicroseconds(SM2135_DELAY); + Sm2135SetLow(Sm2135.clk); + } + + Sm2135SetHigh(Sm2135.data); + Sm2135SetHigh(Sm2135.clk); + delayMicroseconds(SM2135_DELAY / 2); + uint8_t ack = digitalRead(Sm2135.data); + Sm2135SetLow(Sm2135.clk); + delayMicroseconds(SM2135_DELAY / 2); + Sm2135SetLow(Sm2135.data); + return (0 == ack); +} + +bool Sm2135Start(uint8_t addr) { + Sm2135SetLow(Sm2135.data); + delayMicroseconds(SM2135_DELAY); + Sm2135SetLow(Sm2135.clk); + return Sm2135Write(addr); +} + +void Sm2135Stop(void) { + Sm2135SetLow(Sm2135.data); + delayMicroseconds(SM2135_DELAY); + Sm2135SetHigh(Sm2135.clk); + delayMicroseconds(SM2135_DELAY); + Sm2135SetHigh(Sm2135.data); + delayMicroseconds(SM2135_DELAY); +} + + + +bool Sm2135SetChannels(void) { + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + uint8_t data[6]; + + Sm2135Start(SM2135_ADDR_MC); + Sm2135Write(SM2135_CURRENT); + if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { + Sm2135Write(SM2135_CW); + Sm2135Stop(); + delay(1); + Sm2135Start(SM2135_ADDR_C); + Sm2135Write(cur_col[4]); + Sm2135Write(cur_col[3]); + } else { + Sm2135Write(SM2135_RGB); + if (SM2135_WCBGR == Sm2135.model) { + Sm2135Write(cur_col[2]); + Sm2135Write(cur_col[1]); + Sm2135Write(cur_col[0]); + } else { + Sm2135Write(cur_col[1]); + Sm2135Write(cur_col[0]); + Sm2135Write(cur_col[2]); + } + } + Sm2135Stop(); + + return true; +} + +void Sm2135ModuleSelected(void) +{ + if (PinUsed(GPIO_SM2135_CLK) && PinUsed(GPIO_SM2135_DAT)) { + Sm2135.clk = Pin(GPIO_SM2135_CLK); + Sm2135.data = Pin(GPIO_SM2135_DAT); + + Sm2135.model = SM2135_WCGRB; + if (PinUsed(GPIO_SWT1)) { + Sm2135.model = SM2135_WCBGR; + pinMode(Pin(GPIO_SWT1), INPUT); + SetPin(Pin(GPIO_SWT1), AGPIO(GPIO_NONE)); + } + + Sm2135Init(); + + light_type = LT_RGBWC; + light_flg = XLGT_04; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 (%s) Found"), (SM2135_WCBGR == Sm2135.model) ? PSTR("BGR") : PSTR("GRB")); + } +} + + + + + +bool Xlgt04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm2135SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm2135ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +#ifdef USE_LIGHT +#ifdef USE_SONOFF_L1 + + + + +#define XLGT_05 5 + +#define SONOFF_L1_BUFFER_SIZE 140 + +#define SONOFF_L1_MODE_COLORFUL 1 +#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 +#define SONOFF_L1_MODE_COLORFUL_BREATH 3 +#define SONOFF_L1_MODE_DIY_GRADIENT 4 +#define SONOFF_L1_MODE_DIY_PULSE 5 +#define SONOFF_L1_MODE_DIY_BREATH 6 +#define SONOFF_L1_MODE_DIY_STROBE 7 +#define SONOFF_L1_MODE_RGB_GRADIENT 8 +#define SONOFF_L1_MODE_RGB_PULSE 9 +#define SONOFF_L1_MODE_RGB_BREATH 10 +#define SONOFF_L1_MODE_RGB_STROBE 11 +#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 + +struct SNFL1 { + uint32_t unlock = 0; + bool receive_ready = true; +} Snfl1; + + + +void SnfL1Send(const char *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))) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + } else { + serial_in_buffer[serial_in_byte_counter++] = 0x00; + + + + + + + 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)) { + + + + token = nullptr; + } + + else if (!strncmp(token2, "\"switch\"", 8)) { + switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + 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) { + + + + + + 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); + + + + 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) { + 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) { + if (Settings.light_fade) { + 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; + Snfl1.receive_ready = false; + } + return true; +} + +void SnfL1ModuleSelected(void) +{ + if (SONOFF_L1 == my_module_type) { + if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) { + SetSerial(19200, TS_SERIAL_8N1); + + light_type = LT_RGB; + light_flg = XLGT_05; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); + } + } +} + + + + + +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 +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" +#ifdef USE_LIGHT +#ifdef USE_ELECTRIQ_MOODL +# 31 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" +#define XLGT_06 6 + + + +bool ElectriqMoodLSetChannels(void) +{ + uint8_t *col = (uint8_t*)XdrvMailbox.data; + uint8_t checksum = (uint8_t)(0x65 + 0xAA + 0x01 + 0x0A); + + Serial.write(0x65); + Serial.write(0xAA); + Serial.write(0x00); + Serial.write(0x01); + Serial.write(0x0A); + + uint8_t payload[5]; + payload[0] = col[0]; + payload[1] = col[1]; + payload[2] = col[2]; + payload[3] = col[3]; + payload[4] = 0x0; + + + for (uint32_t i = 0; i < 5; i++) { + Serial.write(payload[i]); + checksum += payload[i]; + } + + + for (uint32_t i = 0; i < 5; i++) { + Serial.write(payload[i]); + checksum += payload[i]; + } + + Serial.write(checksum); + Serial.flush(); + + return true; +} + +void ElectriqMoodLModuleSelected(void) +{ + if (PinUsed(GPIO_ELECTRIQ_MOODL_TX)) { + SetSerial(9600, TS_SERIAL_8N1); + light_type = LT_RGBW; + light_flg = XLGT_06; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: ElectriQ Mood Lamp Found")); + } +} + + + + + +bool Xlgt06(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = ElectriqMoodLSetChannels(); + break; + case FUNC_MODULE_INIT: + ElectriqMoodLModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xlgt_interface.ino" +# 20 "/workspace/Tasmota/tasmota/xlgt_interface.ino" +#ifdef USE_LIGHT + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xlgt_func_ptr[])(uint8_t) = { +#endif + +#ifdef XLGT_01 + &Xlgt01, +#endif + +#ifdef XLGT_02 + &Xlgt02, +#endif + +#ifdef XLGT_03 + &Xlgt03, +#endif + +#ifdef XLGT_04 + &Xlgt04, +#endif + +#ifdef XLGT_05 + &Xlgt05, +#endif + +#ifdef XLGT_06 + &Xlgt06, +#endif + +#ifdef XLGT_07 + &Xlgt07, +#endif + +#ifdef XLGT_08 + &Xlgt08, +#endif + +#ifdef XLGT_09 + &Xlgt09, +#endif + +#ifdef XLGT_10 + &Xlgt10, +#endif + +#ifdef XLGT_11 + &Xlgt11, +#endif + +#ifdef XLGT_12 + &Xlgt12, +#endif + +#ifdef XLGT_13 + &Xlgt13, +#endif + +#ifdef XLGT_14 + &Xlgt14, +#endif + +#ifdef XLGT_15 + &Xlgt15, +#endif + +#ifdef XLGT_16 + &Xlgt16 +#endif +}; + +const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); + +uint8_t xlgt_active = 0; + +bool XlgtCall(uint8_t function) +{ + DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); + + if (FUNC_MODULE_INIT == function) { + for (uint32_t x = 0; x < xlgt_present; x++) { + xlgt_func_ptr[x](function); + if (light_flg) { + xlgt_active = x; + return true; + } + } + } + else if (light_flg) { + return xlgt_func_ptr[xlgt_active](function); + } + return false; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_01_hlw8012.ino" +# 20 "/workspace/Tasmota/tasmota/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 + uint32_t debug[HLW_SAMPLE_COUNT]; +#endif + volatile uint32_t cf_pulse_length = 0; + volatile uint32_t cf_pulse_last_time = 0; + uint32_t cf_power_pulse_length = 0; + + volatile uint32_t cf1_pulse_length = 0; + volatile uint32_t cf1_pulse_last_time = 0; + volatile uint32_t cf1_summed_pulse_length = 0; + volatile uint32_t cf1_pulse_counter = 0; + uint32_t cf1_voltage_pulse_length = 0; + uint32_t cf1_current_pulse_length = 0; + + volatile uint32_t energy_period_counter = 0; + + uint32_t power_ratio = 0; + uint32_t voltage_ratio = 0; + uint32_t current_ratio = 0; + + uint8_t model_type = 0; + volatile uint8_t cf1_timer = 0; + uint8_t power_retry = 0; + bool select_ui_flag = false; + bool ui_flag = true; + volatile 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) +{ + uint32_t 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) +{ + uint32_t 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) +{ + uint32_t cf1_pulse_length = 0; + uint32_t hlw_w = 0; + uint32_t hlw_u = 0; + uint32_t 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 (PinUsed(GPIO_NRG_CF1)) { + Hlw.cf1_timer++; + if (Hlw.cf1_timer >= 8) { + Hlw.cf1_timer = 0; + Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; + DigitalWrite(GPIO_NRG_SEL, 0, 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]); + } + } + } + uint32_t 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 { + uint32_t hlw_len; + + if (Hlw.energy_period_counter) { + hlw_len = 10000 * 100 / Hlw.energy_period_counter; + Hlw.energy_period_counter = 0; + if (hlw_len) { + Energy.kWhtoday_delta += (((Hlw.power_ratio * Settings.energy_power_calibration) / 36) * 100) / hlw_len; + 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 (PinUsed(GPIO_NRG_SEL)) { + pinMode(Pin(GPIO_NRG_SEL), OUTPUT); + digitalWrite(Pin(GPIO_NRG_SEL), Hlw.select_ui_flag); + } + if (PinUsed(GPIO_NRG_CF1)) { + 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 (PinUsed(GPIO_HJL_CF)) { + SetPin(Pin(GPIO_HJL_CF), AGPIO(GPIO_HLW_CF)); + Hlw.model_type = 1; + } + + if (PinUsed(GPIO_HLW_CF)) { + + Hlw.ui_flag = true; + if (PinUsed(GPIO_NRG_SEL_INV)) { + SetPin(Pin(GPIO_NRG_SEL_INV), AGPIO(GPIO_NRG_SEL)); + Hlw.ui_flag = false; + } + + if (PinUsed(GPIO_NRG_CF1)) { + if (!PinUsed(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 = ((uint32_t)(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 = ((uint32_t)(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 = ((uint32_t)(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 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_CSE7766 +# 31 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" +#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 + +#define CSE_BUFFER_SIZE 25 + +#include + +TasmotaSerial *CseSerial = nullptr; + +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; + + int byte_counter = 0; + uint8_t *rx_buffer = nullptr; + uint8_t power_invalid = 0; + bool received = false; +} Cse; + +void CseReceived(void) { + + + + + + + uint8_t header = Cse.rx_buffer[0]; + if ((header & 0xFC) == 0xFC) { + AddLog_P2(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 = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_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 = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_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 = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; + } + Settings.energy_power_calibration = power_coefficient / CSE_PREF; + } + + uint8_t adjustement = Cse.rx_buffer[20]; + Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; + Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; + Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; + Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_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; + } +} + +void CseSerialInput(void) { + while (CseSerial->available()) { + yield(); + uint8_t serial_in_byte = CseSerial->read(); + + if (Cse.received) { + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + if (24 == Cse.byte_counter) { + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); + + uint8_t checksum = 0; + for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } + if (checksum == Cse.rx_buffer[23]) { + Energy.data_valid[0] = 0; + CseReceived(); + Cse.received = false; + return; + } else { + do { + memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); + Cse.byte_counter--; + } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); + if (0x5A != Cse.rx_buffer[1]) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + Cse.received = false; + Cse.byte_counter = 0; + } + } + } + } else { + if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { + Cse.received = true; + } else { + Cse.byte_counter = 0; + } + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + } + } +} + + + +void CseEverySecond(void) { + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Cse.voltage_cycle = 0; + Cse.current_cycle = 0; + Cse.power_cycle = 0; + } else { + if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + } else { + uint32_t cf_pulses = 0; + if (Cse.cf_pulses < Cse.cf_pulses_last_time) { + cf_pulses = (0x10000 - Cse.cf_pulses_last_time) + Cse.cf_pulses; + } else { + cf_pulses = Cse.cf_pulses - Cse.cf_pulses_last_time; + } + if (cf_pulses && Energy.active_power[0]) { + uint32_t delta = (cf_pulses * Settings.energy_power_calibration) / 36; + + + if (delta <= (4000 * 1000 / 36)) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + Energy.kWhtoday_delta += delta; + } + else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CSE: Overload")); + Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + } +} + +void CseSnsInit(void) { + + + CseSerial = new TasmotaSerial(Pin(GPIO_CSE7766_RX), -1, 1); + if (CseSerial->begin(4800, 2)) { + if (CseSerial->hardwareSerial()) { + SetSerial(4800, TS_SERIAL_8E1); + ClaimSerial(); + } + 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]; + } else { + energy_flg = ENERGY_NONE; + } +} + +void CseDrvInit(void) { + + if (PinUsed(GPIO_CSE7766_RX)) { + Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); + if (Cse.rx_buffer != nullptr) { + 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_LOOP: + if (CseSerial) { CseSerialInput(); } + break; + case FUNC_EVERY_SECOND: + CseEverySecond(); + break; + case FUNC_COMMAND: + result = CseCommand(); + break; + case FUNC_INIT: + CseSnsInit(); + break; + case FUNC_PRE_INIT: + CseDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM004T +# 31 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#define XNRG_03 3 + +const uint32_t PZEM_STABILIZE = 30; + +#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; + float last_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] = 192; + pzem.addr[1] = 168; + pzem.addr[2] = 1; + 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) +{ +# 124 "/workspace/Tasmota/tasmota/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 (!len && ((c & 0xF8) != 0xA0)) { + 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 PzemEvery250ms(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) { + if (Pzem.energy > Pzem.last_energy) { + if (uptime > PZEM_STABILIZE) { + EnergyUpdateTotal(Pzem.energy, false); + } + Pzem.last_energy = Pzem.energy; + } + Pzem.energy = 0; + } + break; + } + Pzem.read_state++; + if (5 == Pzem.read_state) { + Pzem.read_state = 1; + } + + + } + } + + if (0 == Pzem.send_retry || data_ready) { + if (1 == Pzem.read_state) { + if (0 == Pzem.phase) { + Pzem.phase = Energy.phase_count -1; + } else { + Pzem.phase--; + } + + + } + + 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 < PZEM_STABILIZE)) { + 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 = 0; + Pzem.read_state = 1; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDrvInit(void) +{ + if (PinUsed(GPIO_PZEM004_RX) && PinUsed(GPIO_PZEM0XX_TX)) { + energy_flg = XNRG_03; + } +} + +bool PzemCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + Pzem.address = XdrvMailbox.payload; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } + break; + case FUNC_COMMAND: + result = PzemCommand(); + break; + case FUNC_INIT: + PzemSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_04_mcp39f501.ino" +# 20 "/workspace/Tasmota/tasmota/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)); + } + DigitalWrite(GPIO_MCP39F5_RST, 0, 1); + } else { + energy_flg = ENERGY_NONE; + } +} + +void McpDrvInit(void) +{ + if (PinUsed(GPIO_MCP39F5_RX) && PinUsed(GPIO_MCP39F5_TX)) { + if (PinUsed(GPIO_MCP39F5_RST)) { + 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 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_AC +# 33 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#define XNRG_05 5 + +const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_AC_STABILIZE = 30; + +#include +TasmotaModbus *PzemAcModbus; + +struct PZEMAC { + float energy = 0; + float last_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) { + if (PzemAc.energy > PzemAc.last_energy) { + if (uptime > PZEM_AC_STABILIZE) { + EnergyUpdateTotal(PzemAc.energy, false); + } + PzemAc.last_energy = PzemAc.energy; + } + PzemAc.energy = 0; + } + + } + } + } + + if (0 == PzemAc.send_retry || data_ready) { + if (0 == PzemAc.phase) { + PzemAc.phase = Energy.phase_count -1; + } else { + PzemAc.phase--; + } + 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 < PZEM_AC_STABILIZE)) { + 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 = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit(void) +{ + if (PinUsed(GPIO_PZEM016_RX) && PinUsed(GPIO_PZEM0XX_TX)) { + 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 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_DC +# 32 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#define XNRG_06 6 + +const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_DC_STABILIZE = 30; + +#include +TasmotaModbus *PzemDcModbus; + +struct PZEMDC { + float energy = 0; + float last_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) { + if (PzemDc.energy > PzemDc.last_energy) { + if (uptime > PZEM_DC_STABILIZE) { + EnergyUpdateTotal(PzemDc.energy, false); + } + PzemDc.last_energy = PzemDc.energy; + } + PzemDc.energy = 0; + } + } + } + } + + if (0 == PzemDc.send_retry || data_ready) { + if (0 == PzemDc.channel) { + PzemDc.channel = Energy.phase_count -1; + } else { + PzemDc.channel--; + } + 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 < PZEM_DC_STABILIZE)) { + 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 = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit(void) +{ + if (PinUsed(GPIO_PZEM017_RX) && PinUsed(GPIO_PZEM0XX_TX)) { + 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 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" +#ifdef USE_I2C +#ifdef USE_ENERGY_SENSOR +#ifdef USE_ADE7953 +# 31 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" +#define XNRG_07 7 +#define XI2C_07 7 + +#define ADE7953_PREF 1540 +#define ADE7953_UREF 26000 +#define ADE7953_IREF 10000 + +#define ADE7953_ADDR 0x38 + +const uint16_t Ade7953Registers[] { + 0x31B, + 0x313, + 0x311, + 0x315, + 0x31A, + 0x312, + 0x310, + 0x314, + 0x31C, + 0x10E +}; + +struct Ade7953 { + uint32_t voltage_rms = 0; + uint32_t period = 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)/sizeof(uint16_t); i++) { + int32_t value = Ade7953Read(Ade7953Registers[i]); + if (8 == i) { + Ade7953.voltage_rms = value; + } else if (9 == i) { + Ade7953.period = 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, %d]"), + Ade7953.voltage_rms, Ade7953.period, + 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, C %d, I %d + %d = %d, P %d + %d = %d"), + Ade7953.voltage_rms, Ade7953.period, + 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; + Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); + + 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(void) +{ + if (Ade7953.init_step) { + if (1 == Ade7953.init_step) { + Ade7953Init(); + } + Ade7953.init_step--; + } else { + Ade7953GetData(); + } +} + +void Ade7953DrvInit(void) +{ + if (PinUsed(GPIO_ADE7953_IRQ)) { + pinMode(Pin(GPIO_ADE7953_IRQ), INPUT); + delay(100); + if (I2cSetDevice(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; + } + I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); + Ade7953.init_step = 2; + Energy.phase_count = 2; + Energy.voltage_common = true; + Energy.frequency_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) +{ + if (!I2cEnabled(XI2C_07)) { return false; } + + 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 "/workspace/Tasmota/tasmota/xnrg_08_sdm120.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_08_sdm120.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM120 + + + + + + +#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[0] = 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 (PinUsed(GPIO_SDM120_RX) && PinUsed(GPIO_SDM120_TX)) { + 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 "/workspace/Tasmota/tasmota/xnrg_09_dds2382.ino" +# 20 "/workspace/Tasmota/tasmota/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; +# 67 "/workspace/Tasmota/tasmota/xnrg_09_dds2382.ino" + 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; + uint8_t offset = 11; + if (Settings.flag3.dds2382_model) { + offset = 19; + } + Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; + float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; + + EnergyUpdateTotal(import_active, true); + } + } + + 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 (PinUsed(GPIO_DDS2382_RX) && PinUsed(GPIO_DDS2382_TX)) { + 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 "/workspace/Tasmota/tasmota/xnrg_10_sdm630.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_10_sdm630.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM630 + + + + + + +#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, + 0x0046, + 0x0160, + 0x0162, + 0x0164, +#ifdef SDM630_IMPORT + 0x015A, + 0x015C, + 0x015E, +#endif + 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: + Energy.frequency[0] = value; + break; + + case 16: + Energy.export_active[0] = value; + break; + + case 17: + Energy.export_active[1] = value; + break; + + case 18: + Energy.export_active[2] = value; + break; + + case 19: +#ifdef SDM630_IMPORT + Energy.import_active[0] = value; + break; + + case 20: + Energy.import_active[1] = value; + break; + + case 21: + Energy.import_active[2] = value; + break; + + case 22: +#endif + 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; + Energy.frequency_common = true; + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm630DrvInit(void) +{ + if (PinUsed(GPIO_SDM630_RX) && PinUsed(GPIO_SDM630_TX)) { + 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 "/workspace/Tasmota/tasmota/xnrg_11_ddsu666.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_11_ddsu666.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDSU666 + + + + +#define XNRG_11 11 + + +#ifndef DDSU666_SPEED + #define DDSU666_SPEED 9600 +#endif + +#ifndef DDSU666_ADDR + #define DDSU666_ADDR 1 +#endif + +#include +TasmotaModbus *Ddsu666Modbus; + +const uint16_t Ddsu666_start_addresses[] { + 0x2000, + 0x2002, + 0x2004, + 0x2006, + 0x200A, + 0x200E, + 0X4000, + 0X400A, +}; + +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]; + + 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; + + + + + 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(Ddsu666.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value * 1000; + break; + + case 3: + Energy.reactive_power[0] = value * 1000; + break; + + case 4: + Energy.power_factor[0] = value; + break; + + case 5: + Energy.frequency[0] = value; + break; + + case 6: + Ddsu666.import_active = value; + break; + + case 7: + Energy.export_active[0] = value; + break; + } + + Ddsu666.read_state++; + + if (Ddsu666.read_state == 8) { + Ddsu666.read_state = 0; + EnergyUpdateTotal(Ddsu666.import_active, true); + } + } + } + + 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 (PinUsed(GPIO_DDSU666_RX) && PinUsed(GPIO_DDSU666_TX)) { + energy_flg = XNRG_11; + } +} + + + + + +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 +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_12_solaxX1.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_12_solaxX1.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SOLAX_X1 + + + + +#define XNRG_12 12 + +#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; + +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; + uint8_t freeBit6:1; + uint8_t freeBit5:1; + uint8_t queryOffline:1; + uint8_t queryOfflineSend:1; + uint8_t hasAddress:1; + uint8_t inverterAddressSend:1; + uint8_t inverterSnReceived:1; + }; +} 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); + + while (solaxX1Serial->available() > 0) + { + 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); + + 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_SendInverterAddress(void) +{ + source[0] = 0x00; + destination[0] = 0x00; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x01; + dataLength[0] = 0x0F; + data[14] = INVERTER_ADDRESS; + solaxX1_RS485Send(24); +} + +void solaxX1_QueryLiveData(void) +{ + 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; + return 0; +} + + + +uint8_t solaxX1_send_retry = 0; +uint8_t solaxX1_nodata_count = 0; + +void solaxX1250MSecond(void) +{ + 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]); + solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; + solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; + solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; + solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; + solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; + Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; + Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; + Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; + Energy.active_power[0] = (float)((value[27] << 8) | value[28]); + + solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; + solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); + solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); + + + + + + + + solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); + + 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); + } + } + + if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { + solaxX1_send_retry = 12; + solaxX1_QueryLiveData(); + } + + + + if (255 == solaxX1_nodata_count) { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + } + } + 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) + { + solaxX1_nodata_count++; + } + else if (255 != solaxX1_nodata_count) + { + + solaxX1_nodata_count = 255; + solaxX1_send_retry = 12; + protocolStatus.status = 0b00001000; + 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; + + } + } + + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + + 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; + } + } + } + + + if (protocolStatus.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 && protocolStatus.inverterSnReceived == false) + { + for (uint8_t i = 9; i <= 22; i++) + { + data[i - 9] = value[i]; + } + solaxX1_SendInverterAddress(); + protocolStatus.status = 0b1100000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); + } + } + } + } + + if (solaxX1_send_retry == 0) + { + if (protocolStatus.queryOfflineSend) + { + protocolStatus.status = 0b00001000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); + } + solaxX1_send_retry = 12; + } + + + if (protocolStatus.queryOffline) + { + + source[0] = 0x01; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x00; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); + protocolStatus.status = 0b00010000; + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); + } + } + + 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; + + 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 (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { + 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 + +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 + } +} + + + + + +bool Xnrg12(uint8_t function) +{ + bool result = false; + + 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; +#endif + case FUNC_INIT: + solaxX1SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_LE01MR +# 71 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#define XNRG_13 13 + + +#ifndef LE01MR_SPEED + #define LE01MR_SPEED 2400 +#endif + +#ifndef LE01MR_ADDR + #define LE01MR_ADDR 1 +#endif + +#include +TasmotaModbus *FifLEModbus; + +const uint8_t le01mr_table_sz = 9; + +const uint16_t le01mr_register_addresses[] { + + 0x0130, + 0x0131, + 0x0158, + 0x0139, + 0x0140, + 0x0148, + 0x0150, + 0xA000, + 0xA01E +}; + +struct LE01MR { + float total_active = 0; + float total_reactive = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = le01mr_table_sz; +} Le01mr; + + + +void FifLEEvery250ms(void) +{ + bool data_ready = FifLEModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + uint8_t reg_count = 2; + if (Le01mr.read_state < 3) { + reg_count=1; + } + + uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); + } else { + Energy.data_valid[0] = 0; +# 146 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" + uint32_t value_buff = 0; + + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { + value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; + } else { + value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; + } + + switch(Le01mr.read_state) { + case 0: + Energy.frequency[0] = value_buff * 0.01f; + break; + + case 1: + Energy.voltage[0] = value_buff * 0.01f; + break; + + case 2: + Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; + break; + + case 3: + Energy.current[0] = value_buff * 0.001f; + break; + + case 4: + Energy.active_power[0] = value_buff * 1.0f; + break; + + case 5: + Energy.reactive_power[0] = value_buff * 1.0f; + break; + + case 6: + Energy.apparent_power[0] = value_buff * 1.0f; + break; + + case 7: + Le01mr.total_active = value_buff * 0.01f; + break; + + case 8: + Le01mr.total_reactive = value_buff * 0.01f; + break; + } + + Le01mr.read_state++; + if (Le01mr.read_state == Le01mr.start_address_count) { + Le01mr.read_state = 0; + + EnergyUpdateTotal(Le01mr.total_active, true); + } + } + } + + if (0 == Le01mr.send_retry || data_ready) { + uint8_t reg_count = 2; + + Le01mr.send_retry = 5; + + if (Le01mr.read_state < 3) reg_count=1; + + FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); + } else { + Le01mr.send_retry--; + } +} + +void FifLESnsInit(void) +{ + FifLEModbus = new TasmotaModbus(Pin(GPIO_LE01MR_RX), Pin(GPIO_LE01MR_TX)); + uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void FifLEDrvInit(void) +{ + if (PinUsed(GPIO_LE01MR_RX) && PinUsed(GPIO_LE01MR_TX)) { + energy_flg = XNRG_13; + } +} + +void FifLEReset(void) +{ + Le01mr.total_active = 0; + Le01mr.total_reactive = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_LE01MR[] PROGMEM = + "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + ; +#endif + +void FifLEShow(bool json) +{ + char total_reactive_chr[FLOATSZ]; + dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); + char total_active_chr[FLOATSZ]; + dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), + total_active_chr, total_reactive_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); +#endif + } +} + + + + + +bool Xnrg13(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { + FifLEEvery250ms(); + } + break; + case FUNC_JSON_APPEND: + FifLEShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + FifLEShow(0); + break; +#endif + case FUNC_ENERGY_RESET: + FifLEReset(); + break; + case FUNC_INIT: + FifLESnsInit(); + break; + case FUNC_PRE_INIT: + FifLEDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_BL0940 +# 30 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" +#define XNRG_14 14 + +#define BL0940_PREF 1430 +#define BL0940_UREF 33000 +#define BL0940_IREF 2750 + +#define BL0940_PULSES_NOT_INITIALIZED -1 + +#define BL0940_BUFFER_SIZE 36 + +#define BL0940_WRITE_COMMAND 0xA0 +#define BL0940_REG_I_FAST_RMS_CTRL 0x10 +#define BL0940_REG_MODE 0x18 +#define BL0940_REG_SOFT_RESET 0x19 +#define BL0940_REG_USR_WRPROT 0x1A +#define BL0940_REG_TPS_CTRL 0x1B + +#define BL0940_READ_COMMAND 0x50 +#define BL0940_FULL_PACKET 0xAA + +#define BL0940_PACKET_HEADER 0x55 + +#include + +TasmotaSerial *Bl0940Serial = nullptr; + +struct BL0940 { + long voltage = 0; + long current = 0; + long power = 0; + long power_cycle_first = 0; + long cf_pulses = 0; + long cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; + float temperature; + + int byte_counter = 0; + uint16_t tps1 = 0; + uint8_t *rx_buffer = nullptr; + bool received = false; +} Bl0940; + +const uint8_t bl0940_init[5][6] = { + { BL0940_WRITE_COMMAND, BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38 }, + { BL0940_WRITE_COMMAND, BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0 }, + { BL0940_WRITE_COMMAND, BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37 }, + { BL0940_WRITE_COMMAND, BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE }, + { BL0940_WRITE_COMMAND, BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B }}; + +void Bl0940Received(void) { + + + + + + + uint16_t tps1 = Bl0940.rx_buffer[29] << 8 | Bl0940.rx_buffer[28]; + if ((Bl0940.rx_buffer[0] != BL0940_PACKET_HEADER) || + (Bl0940.tps1 && ((tps1 < (Bl0940.tps1 -10)) || (tps1 > (Bl0940.tps1 +10)))) + ) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: Invalid data")); + return; + } + + Bl0940.tps1 = tps1; + float t = ((170.0f/448.0f)*(((float)Bl0940.tps1/2.0f)-32.0f))-45.0f; + Bl0940.temperature = ConvertTemp(t); + + Bl0940.voltage = Bl0940.rx_buffer[12] << 16 | Bl0940.rx_buffer[11] << 8 | Bl0940.rx_buffer[10]; + Bl0940.current = Bl0940.rx_buffer[6] << 16 | Bl0940.rx_buffer[5] << 8 | Bl0940.rx_buffer[4]; + int32_t power = Bl0940.rx_buffer[18] << 24 | Bl0940.rx_buffer[17] << 16 | Bl0940.rx_buffer[16] << 8; + Bl0940.power = abs(power) >> 8; + int32_t cf_cnt = Bl0940.rx_buffer[24] << 24 | Bl0940.rx_buffer[23] << 16 | Bl0940.rx_buffer[22] << 8; + Bl0940.cf_pulses = abs(cf_cnt) >> 8; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: U %d, I %d, P %d, C %d, T %d"), + Bl0940.voltage, Bl0940.current, Bl0940.power, Bl0940.cf_pulses, Bl0940.tps1); + + if (Energy.power_on) { + Energy.voltage[0] = (float)Bl0940.voltage / Settings.energy_voltage_calibration; + if (power && (Bl0940.power > Settings.energy_power_calibration)) { + Energy.active_power[0] = (float)Bl0940.power / Settings.energy_power_calibration; + Energy.current[0] = (float)Bl0940.current / (Settings.energy_current_calibration * 100); + } else { + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } + } else { + + Energy.voltage[0] = 0; + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } +} + +void Bl0940SerialInput(void) { + while (Bl0940Serial->available()) { + yield(); + uint8_t serial_in_byte = Bl0940Serial->read(); + if (!Bl0940.received && (BL0940_PACKET_HEADER == serial_in_byte)) { + Bl0940.received = true; + Bl0940.byte_counter = 0; + } + if (Bl0940.received) { + Bl0940.rx_buffer[Bl0940.byte_counter++] = serial_in_byte; + if (BL0940_BUFFER_SIZE == Bl0940.byte_counter) { + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Bl0940.rx_buffer, BL0940_BUFFER_SIZE -1); + + uint8_t checksum = BL0940_READ_COMMAND; + for (uint32_t i = 0; i < BL0940_BUFFER_SIZE -2; i++) { checksum += Bl0940.rx_buffer[i]; } + checksum ^= 0xFF; + if (checksum == Bl0940.rx_buffer[34]) { + Energy.data_valid[0] = 0; + Bl0940Received(); + Bl0940.received = false; + return; + } else { + do { + memmove(Bl0940.rx_buffer, Bl0940.rx_buffer +1, BL0940_BUFFER_SIZE -1); + Bl0940.byte_counter--; + } while ((Bl0940.byte_counter > 1) && (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0])); + if (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0]) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: " D_CHECKSUM_FAILURE)); + Bl0940.received = false; + Bl0940.byte_counter = 0; + } + } + } + } + } +} + + + +void Bl0940EverySecond(void) { + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Bl0940.voltage = 0; + Bl0940.current = 0; + Bl0940.power = 0; + } else { +# 178 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" + if (BL0940_PULSES_NOT_INITIALIZED == Bl0940.cf_pulses_last_time) { + Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; + } else { + uint32_t cf_pulses = 0; + if (Bl0940.cf_pulses < Bl0940.cf_pulses_last_time) { + cf_pulses = (0x1000000 - Bl0940.cf_pulses_last_time) + Bl0940.cf_pulses; + } else { + cf_pulses = Bl0940.cf_pulses - Bl0940.cf_pulses_last_time; + } + if (cf_pulses && Energy.active_power[0]) { + uint32_t watt256 = (1638400 * 256) / Settings.energy_power_calibration; + uint32_t delta = (cf_pulses * watt256) / 36; + if (delta <= (4000 * 1000 / 36)) { + Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; + Energy.kWhtoday_delta += delta; + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: Overload")); + Bl0940.cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + + } + + + + Bl0940Serial->flush(); + Bl0940Serial->write(BL0940_READ_COMMAND); + Bl0940Serial->write(BL0940_FULL_PACKET); +} + +void Bl0940SnsInit(void) { + + Bl0940Serial = new TasmotaSerial(Pin(GPIO_BL0940_RX), Pin(GPIO_TXD), 1); + if (Bl0940Serial->begin(4800, 1)) { + if (Bl0940Serial->hardwareSerial()) { + ClaimSerial(); + } + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + Settings.energy_voltage_calibration = BL0940_UREF; + Settings.energy_current_calibration = BL0940_IREF; + Settings.energy_power_calibration = BL0940_PREF; + } + + for (uint32_t i = 0; i < 5; i++) { + for (uint32_t j = 0; j < 6; j++) { + Bl0940Serial->write(bl0940_init[i][j]); + + } + delay(1); + } + + } else { + energy_flg = ENERGY_NONE; + } +} + +void Bl0940DrvInit(void) { + if (PinUsed(GPIO_BL0940_RX) && PinUsed(GPIO_TXD)) { + Bl0940.rx_buffer = (uint8_t*)(malloc(BL0940_BUFFER_SIZE)); + if (Bl0940.rx_buffer != nullptr) { + energy_flg = XNRG_14; + } + } +} + +bool Bl0940Command(void) { + bool serviced = true; + + uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.power) { + Settings.energy_power_calibration = (Bl0940.power * 100) / value; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.voltage) { + Settings.energy_voltage_calibration = (Bl0940.voltage * 100) / value; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.current) { + Settings.energy_current_calibration = Bl0940.current / value; + } + } + else serviced = false; + + return serviced; +} + +void Bl0940Show(bool json) { + char temperature[33]; + dtostrfd(Bl0940.temperature, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "BL0940", temperature); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, Bl0940.temperature); +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xnrg14(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (Bl0940Serial) { Bl0940SerialInput(); } + break; + case FUNC_EVERY_SECOND: + Bl0940EverySecond(); + break; + case FUNC_JSON_APPEND: + Bl0940Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bl0940Show(0); + break; +#endif + case FUNC_COMMAND: + result = Bl0940Command(); + break; + case FUNC_INIT: + Bl0940SnsInit(); + break; + case FUNC_PRE_INIT: + Bl0940DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_TELEINFO +# 34 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +#define XNRG_15 15 + +#include "LibTeleinfo.h" +#include + +#define TINFO_READ_TIMEOUT 400 + + +enum TInfoContrat{ + CONTRAT_BAS = 1, + CONTRAT_HC, + CONTRAT_EJP, + CONTRAT_BBR, + CONTRAT_END +}; + + +const char kContratName[] PROGMEM = + "|Base|Heures Creuses|EJP|Bleu Blanc Rouge" + ; + + +const char kContratValue[] PROGMEM = + "|BASE|HC..|EJP.|BBR" + ; + + +enum TInfoTarif{ + TARIF_TH = 1, + TARIF_HC, TARIF_HP, + TARIF_HN, TARIF_PM, + TARIF_CB, TARIF_CW, TARIF_CR, + TARIF_PB, TARIF_PW, TARIF_PR, + TARIF_END +}; + + + +const char kTarifValue[] PROGMEM = + "|TH..|HC..|HP.." + "|HN..|PM.." + "|HCJB|HCJW|HCJR" + "|HPJB|HPJW|HPJR" + ; + + +const char kTarifName[] PROGMEM = + "|Toutes|Creuses|Pleines" + "|Normales|Pointe Mobile" + "|Creuses Bleu|Creuses Blanc|Creuse Rouges" + "|Pleines Bleu|Pleines Blanc|Pleines Rouges" + ; + + +enum TInfoLabel{ + LABEL_BASE = 1, + LABEL_ADCO, LABEL_ADSC, + LABEL_HCHC, LABEL_HCHP, LABEL_EAST, LABEL_EASF01, LABEL_EASF02, + LABEL_OPTARIF, LABEL_NGTF, LABEL_ISOUSC, LABEL_PREF, LABEL_PTEC, LABEL_LTARF, LABEL_NTARF, + LABEL_PAPP, LABEL_SINSTS, LABEL_IINST, LABEL_IRMS1, LABEL_TENSION, LABEL_URMS1, + LABEL_IMAX, LABEL_PMAX, LABEL_SMAXSN, + LABEL_DEMAIN, + LABEL_END +}; + +const char kLabel[] PROGMEM = + "|BASE|ADCO|ADSC" + "|HCHC|HCHP|EAST|EASF01|EASF02" + "|OPTARIF|NGTF|ISOUSC|PREF|PTEC|LTARF|NTARF" + "|PAPP|SINSTS|IINST|IRMS1|TENSION|URMS1" + "|IMAX|PMAX|SMAXSN" + "|DEMAIN" + ; + +TInfo tinfo; +TasmotaSerial *TInfoSerial = nullptr; +_Mode_e tinfo_mode = TINFO_MODE_HISTORIQUE; +char serialNumber[13] = ""; +bool tinfo_found = false; +int contrat; +int tarif; +int isousc; +# 126 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +char * getValueFromLabelIndex(int labelIndex, char * value) +{ + char labelName[16]; + + GetTextIndexed(labelName, sizeof(labelName), labelIndex, kLabel); + + return tinfo.valueGet(labelName, value) ; +} +# 147 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void ADPSCallback(uint8_t phase) +{ + + if (phase == 0){ + phase = 1; + } + + Response_P(PSTR("{")); + ResponseAppend_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), serialNumber, phase ); + ResponseJsonEnd(); + + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ADPS on phase %d"), phase); +} +# 172 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void DataCallback(struct _ValueList * me, uint8_t flags) +{ + char c = ' '; + int ilabel ; + + + if (flags & (TINFO_FLAGS_ADDED | TINFO_FLAGS_UPDATED) ) { + char labelName[16]; + + for ( ilabel = 1 ; ilabel < LABEL_END ; ilabel++) { + GetTextIndexed(labelName, sizeof(labelName), ilabel, kLabel); + if (!strcmp(labelName, me->name)) { + break; + } + } + + if (flags & TINFO_FLAGS_ADDED) { c = '#'; } + if (flags & TINFO_FLAGS_UPDATED) { c = '*'; } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: [%d]%c %s=%s"), ilabel, c , me->name, me->value); + + if (ilabelvalue)) { + break; + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); + } + + + else if (ilabel == LABEL_LTARF) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif name changed, now '%s'"), me->value); + } + + else if (ilabel == LABEL_NTARF) + { + tarif = atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif index changed, now '%d'"), tarif); + } + + + + else if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1) + { + Energy.voltage_available = true; + Energy.voltage[0] = (float) atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s, now %d"), me->value, (int) Energy.voltage[0]); + } + + + else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1) + { + Energy.current[0] = (float) atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s, now %d"), me->value, (int) Energy.current[0]); + } + + + else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS) + { + Energy.active_power[0] = (float) atoi(me->value);; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]); + } + + + else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP || ilabel == LABEL_BASE) + { + char value[32]; + uint32_t hc = 0; + uint32_t hp = 0; + uint32_t total = 0; + + + if (ilabel == LABEL_BASE) { + total = atoi(me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Base:%u"), total); + + } else { + + if (ilabel == LABEL_HCHC) { + hc = atoi(me->value); + if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { + hp = atoi(value); + } + + + } else if (ilabel == LABEL_HCHP) { + hp = atoi(me->value); + if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { + hc = atoi(value); + } + } + total = hc + hp; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); + } + + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); + } + } + + + else if ( ilabel == LABEL_EAST) + { + uint32_t total = atoi(me->value); + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); + } + + + else if ( ilabel == LABEL_EASF01) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value)); + } + else if ( ilabel == LABEL_EASF02) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%u"), atoi(me->value)); + } + + + else if (ilabel == LABEL_OPTARIF) + { + char contrat_value[] = " "; + + for (contrat = CONTRAT_BAS ; contrat < CONTRAT_END ; contrat++) { + GetTextIndexed(contrat_value, sizeof(contrat_value), contrat, kContratValue); + if (!strcmp(contrat_value, me->value)) { + break; + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); + } + + else if (ilabel == LABEL_NGTF) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s'"), me->value); + } + + + else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF) + { + isousc = atoi( me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); + } + + + else if (ilabel == LABEL_ADCO || ilabel == LABEL_ADSC) + { + strcpy(serialNumber, me->value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: %s set to %s"), me->name, serialNumber); + } + + } + } + + + + +} +# 348 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void ResponseAppendTInfo(char sep) +{ + struct _ValueList * me = tinfo.getList(); + + char * p ; + boolean isNumber ; + + + + while (me->next) { + + me = me->next; + + if (me->name && me->value && *me->name && *me->value) { + isNumber = true; + p = me->value; + + + if (strcmp(me->name, "ADCO")==0 || strcmp(me->name, "ADSC")==0) { + isNumber = false; + } else { + + while (*p && isNumber) { + if ( *p < '0' || *p > '9' ) { + isNumber = false; + } + p++; + } + } + + ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); + + if (!isNumber) { + ResponseAppend_P( PSTR("\"%s\""), me->value ); + } else { + ResponseAppend_P( PSTR("%d"), atoi(me->value)); + } + + + sep =','; + } + } +} +# 399 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void NewFrameCallback(struct _ValueList * me) +{ + + Energy.data_valid[0] = 0; + + + + if (Settings.flag4.teleinfo_rawdata) { + Response_P(PSTR("{")); + ResponseAppendTInfo(' '); + ResponseJsonEnd(); + + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); + } +} +# 423 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void TInfoDrvInit(void) { + if (PinUsed(GPIO_TELEINFO_RX)) { + energy_flg = XNRG_15; + Energy.voltage_available = false; + } +} +# 437 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void TInfoInit(void) +{ + int baudrate; + + + if (Settings.flag4.teleinfo_baudrate) { + baudrate = 9600; + tinfo_mode = TINFO_MODE_STANDARD; + } else { + baudrate = 1200; + tinfo_mode = TINFO_MODE_HISTORIQUE; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: inferface speed %d bps"),baudrate); + + if (PinUsed(GPIO_TELEINFO_RX)) { + uint8_t rx_pin = Pin(GPIO_TELEINFO_RX); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: RX on GPIO%d"), rx_pin); + + + if (PinUsed(GPIO_TELEINFO_ENABLE)) { + uint8_t en_pin = Pin(GPIO_TELEINFO_ENABLE); + pinMode(en_pin, OUTPUT); + digitalWrite(en_pin, HIGH); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Enable with GPIO%d"), en_pin); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: always enabled")); + } + +#if defined (ESP8266) + + TInfoSerial = new TasmotaSerial(rx_pin, -1, 2); + +#else + TInfoSerial = new TasmotaSerial(rx_pin, -1, 1); +#endif + + + + if (TInfoSerial->begin(baudrate)) { + + +#if defined (ESP8266) + if (TInfoSerial->hardwareSerial() ) { + ClaimSerial(); +# 490 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using hardware serial")); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using software serial")); + } + +#elif defined (ESP32) + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using ESP32 hardware serial")); +#endif + + tinfo.init(tinfo_mode); + + tinfo.attachADPS(ADPSCallback); + tinfo.attachData(DataCallback); + tinfo.attachNewFrame(NewFrameCallback); + tinfo_found = true; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Ready")); + } + } +} +# 518 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +void TInfoEvery250ms(void) +{ + if (!tinfo_found) { + return; + } + + if (TInfoSerial->available()) { + unsigned long start = millis(); + char c; + + + while (TInfoSerial->available()>8 && millis()-start < 100) { + + c = TInfoSerial->read(); + + tinfo.process(c & 0x7F); + } + } +} +# 545 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_ID_TELEINFO[] PROGMEM = "{s}ID{m}%s{e}" ; +const char HTTP_ENERGY_INDEX_TELEINFO[] PROGMEM = "{s}%s{m}%s " D_UNIT_WATTHOUR "{e}" ; +const char HTTP_ENERGY_PAPP_TELEINFO[] PROGMEM = "{s}" D_POWERUSAGE "{m}%d " D_UNIT_WATT "{e}" ; +const char HTTP_ENERGY_IINST_TELEINFO[] PROGMEM = "{s}" D_CURRENT "{m}%d " D_UNIT_AMPERE "{e}" ; +const char HTTP_ENERGY_TARIF_TELEINFO[] PROGMEM = "{s}" D_CURRENT_TARIFF "{m}Heures %s{e}" ; +const char HTTP_ENERGY_CONTRAT_TELEINFO[] PROGMEM = "{s}" D_CONTRACT "{m}%s %d" D_UNIT_AMPERE "{e}" ; +const char HTTP_ENERGY_LOAD_TELEINFO[] PROGMEM = "{s}" D_POWER_LOAD "{m}%d" D_UNIT_PERCENT "{e}" ; +const char HTTP_ENERGY_IMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_CURRENT "{m}%d" D_UNIT_AMPERE "{e}" ; +const char HTTP_ENERGY_PMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_POWER "{m}%d" D_UNIT_WATT "{e}" ; +#endif + +void TInfoShow(bool json) +{ + + + + if (json) + { + + if (isousc) { + ResponseAppend_P(PSTR(",\"Load\":%d"),(int) ((Energy.current[0]*100.0f) / isousc)); + } + + + if (!Settings.flag4.teleinfo_rawdata) { + ResponseAppendTInfo(','); + } + + +#ifdef USE_WEBSERVER + } + else + { + char name[32]; + char value[32]; + + if (getValueFromLabelIndex(LABEL_BASE, value) ) { + GetTextIndexed(name, sizeof(name), LABEL_BASE, kLabel); + WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); + } + if (getValueFromLabelIndex(LABEL_HCHC, value) ) { + GetTextIndexed(name, sizeof(name), LABEL_HCHC, kLabel); + WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); + } + if (getValueFromLabelIndex(LABEL_HCHP, value) ) { + GetTextIndexed(name, sizeof(name), LABEL_HCHP, kLabel); + WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); + } + if (getValueFromLabelIndex(LABEL_IMAX, value) ) { + WSContentSend_PD(HTTP_ENERGY_IMAX_TELEINFO, atoi(value)); + } + if (getValueFromLabelIndex(LABEL_PMAX, value) ) { + WSContentSend_PD(HTTP_ENERGY_PMAX_TELEINFO, atoi(value)); + } + + if (tinfo_mode==TINFO_MODE_HISTORIQUE ) { + if (tarif) { + GetTextIndexed(name, sizeof(name), tarif-1, kTarifName); + WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); + } + if (contrat && isousc) { + int percent = (int) ((Energy.current[0]*100.0f) / isousc) ; + GetTextIndexed(name, sizeof(name), contrat, kContratName); + WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); + WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); + } + } else if (tinfo_mode==TINFO_MODE_STANDARD ) { + if (getValueFromLabelIndex(LABEL_LTARF, name) ) { + WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); + } + + if (getValueFromLabelIndex(LABEL_NGTF, name) ) { + if (isousc) { + int percent = (int) ((Energy.current[0]*100.0f) / isousc) ; + WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); + WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); + } + } + } + + + if (*serialNumber) { + WSContentSend_PD(HTTP_ENERGY_ID_TELEINFO, serialNumber); + } + +#endif + } +} + + + + +bool Xnrg15(uint8_t function) +{ + switch (function) + { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { TInfoEvery250ms(); } + break; + case FUNC_JSON_APPEND: + TInfoShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + TInfoShow(0); + break; + #endif + case FUNC_INIT: + TInfoInit(); + break; + case FUNC_PRE_INIT: + TInfoDrvInit(); + break; + } + return false; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_16_iem3000.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_16_iem3000.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_IEM3000 + + + + + + +#define XNRG_16 16 + + +#ifndef IEM3000_SPEED + #define IEM3000_SPEED 19200 +#endif + +#ifndef IEM3000_ADDR + #define IEM3000_ADDR 1 +#endif + +#include +TasmotaModbus *Iem3000Modbus; + +const uint16_t Iem3000_start_addresses[] { + + 0x0bb7, + 0x0bb9, + 0x0bbb, + 0x0bd3, + 0x0bd5, + 0x0bd7, + 0x0bed, + 0x0bef, + 0x0bf1, + 0x0c25, + 0xb02b, +}; + +struct IEM3000 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Iem3000; + + + +void IEM3000Every250ms(void) +{ + bool data_ready = Iem3000Modbus->ReceiveReady(); + uint8_t reg_count = 4; + if (Iem3000.read_state < 10) { + reg_count = 2; + } + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Iem3000Modbus->ReceiveBuffer(buffer, reg_count); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Iem3000Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Iem3000 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + int64_t value64; + if(Iem3000.read_state >= 0 && Iem3000.read_state < 10) { + ((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 { + ((uint8_t*)&value64)[7] = buffer[3]; + ((uint8_t*)&value64)[6] = buffer[4]; + ((uint8_t*)&value64)[5] = buffer[5]; + ((uint8_t*)&value64)[4] = buffer[6]; + ((uint8_t*)&value64)[3] = buffer[7]; + ((uint8_t*)&value64)[2] = buffer[8]; + ((uint8_t*)&value64)[1] = buffer[9]; + ((uint8_t*)&value64)[0] = buffer[10]; + } + + switch(Iem3000.read_state) { + case 0: + Energy.current[0] = value; + break; + + case 1: + Energy.current[1] = value; + break; + + case 2: + Energy.current[2] = value; + break; + + case 3: + Energy.voltage[0] = value; + break; + + case 4: + Energy.voltage[1] = value; + break; + + case 5: + Energy.voltage[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.frequency[0] = value; + break; + + case 10: + EnergyUpdateTotal(value64 * 0.001f, true); + break; + } + + Iem3000.read_state++; + if (sizeof(Iem3000_start_addresses)/2 == Iem3000.read_state) { + Iem3000.read_state = 0; + } + } + } + + if (0 == Iem3000.send_retry || data_ready) { + Iem3000.send_retry = 5; + Iem3000Modbus->Send(IEM3000_ADDR, 0x03, Iem3000_start_addresses[Iem3000.read_state], reg_count); + } else { + Iem3000.send_retry--; + } +} + +void Iem3000SnsInit(void) +{ + Iem3000Modbus = new TasmotaModbus(Pin(GPIO_IEM3000_RX), Pin(GPIO_IEM3000_TX)); + uint8_t result = Iem3000Modbus->Begin(IEM3000_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + Energy.frequency_common = true; + } else { + energy_flg = ENERGY_NONE; + } +} + +void Iem3000DrvInit(void) +{ + if (PinUsed(GPIO_IEM3000_RX) && PinUsed(GPIO_IEM3000_TX)) { + energy_flg = XNRG_16; + } +} + + + + + +bool Xnrg16(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { IEM3000Every250ms(); } + break; + case FUNC_INIT: + Iem3000SnsInit(); + break; + case FUNC_PRE_INIT: + Iem3000DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" +# 20 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_WE517 +# 30 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" +#define XNRG_17 17 + + +#ifndef WE517_SPEED + #define WE517_SPEED 9600 +#endif + +#ifndef WE517_ADDR + #define WE517_ADDR 1 +#endif + +#define FUNCTION_CODE_READ_HOLDING_REGISTERS (0x03) + +#include +TasmotaModbus *We517Modbus; + +const uint16_t we517_start_addresses[] { + + 0x000E, + 0x0010, + 0x0012, + 0x0016, + 0x0018, + 0x001A, + 0x001E, + 0x0020, + 0x0022, + 0x0026, + 0x0026, + 0x002A, + 0x0036, + 0x0038, + 0x003A, + 0x0014, + 0x0100 +}; + +struct WE517 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} We517; + + + +void WE517Every250ms(void) +{ + bool data_ready = We517Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = We517Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, We517Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ORNO: WE517 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(We517.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 * 1000; + break; + + case 7: + Energy.active_power[1] = value * 1000; + break; + + case 8: + Energy.active_power[2] = value * 1000; + 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: + Energy.frequency[0] = value; + break; + + case 16: + EnergyUpdateTotal(value, true); + break; + } + + We517.read_state++; + if (sizeof(we517_start_addresses)/2 == We517.read_state) { + We517.read_state = 0; + } + } + } + + if (0 == We517.send_retry || data_ready) { + We517.send_retry = 5; + We517Modbus->Send(WE517_ADDR, FUNCTION_CODE_READ_HOLDING_REGISTERS, we517_start_addresses[We517.read_state], 2); + } else { + We517.send_retry--; + } +} + +void We517SnsInit(void) +{ + We517Modbus = new TasmotaModbus(Pin(GPIO_WE517_RX), Pin(GPIO_WE517_TX)); + uint8_t result = We517Modbus->Begin(WE517_SPEED); + if (result) { + if (2 == result) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ORNO: WE517 HW serial init 8E1 at %d baud"), WE517_SPEED); + Serial.begin(WE517_SPEED, SERIAL_8E1); + ClaimSerial(); + } + Energy.phase_count = 3; + Energy.frequency_common = true; + } else { + energy_flg = ENERGY_NONE; + } +} + +void We517DrvInit(void) +{ + if (PinUsed(GPIO_WE517_RX) && PinUsed(GPIO_WE517_TX)) { + energy_flg = XNRG_17; + } +} + + + + + +bool Xnrg17(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { WE517Every250ms(); } + break; + case FUNC_INIT: + We517SnsInit(); + break; + case FUNC_PRE_INIT: + We517DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xnrg_interface.ino" +# 20 "/workspace/Tasmota/tasmota/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 + +#ifdef XNRG_17 + &Xnrg17, +#endif + +#ifdef XNRG_18 + &Xnrg18, +#endif + +#ifdef XNRG_19 + &Xnrg19, +#endif + +#ifdef XNRG_20 + &Xnrg20, +#endif + +#ifdef XNRG_21 + &Xnrg21, +#endif + +#ifdef XNRG_22 + &Xnrg22, +#endif + +#ifdef XNRG_23 + &Xnrg23, +#endif + +#ifdef XNRG_24 + &Xnrg24, +#endif + +#ifdef XNRG_25 + &Xnrg25, +#endif + +#ifdef XNRG_26 + &Xnrg26, +#endif + +#ifdef XNRG_27 + &Xnrg27, +#endif + +#ifdef XNRG_28 + &Xnrg28, +#endif + +#ifdef XNRG_29 + &Xnrg29, +#endif + +#ifdef XNRG_30 + &Xnrg30, +#endif + +#ifdef XNRG_31 + &Xnrg31, +#endif + +#ifdef XNRG_32 + &Xnrg32 +#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) +{ + DEBUG_TRACE_LOG(PSTR("NRG: %d"), 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 "/workspace/Tasmota/tasmota/xsns_01_counter.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_01_counter.ino" +#ifdef USE_COUNTER + + + + +#define XSNS_01 1 + +#define USE_AC_ZERO_CROSS_DIMMER 1 + +#define D_PRFX_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "Type" +#define D_CMND_COUNTERDEBOUNCE "Debounce" +#define D_CMND_COUNTERDEBOUNCELOW "DebounceLow" +#define D_CMND_COUNTERDEBOUNCEHIGH "DebounceHigh" + +const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" + "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE "|" D_CMND_COUNTERDEBOUNCELOW "|" D_CMND_COUNTERDEBOUNCEHIGH ; + +void (* const CounterCommand[])(void) PROGMEM = { + &CmndCounter, &CmndCounterType, &CmndCounterDebounce, &CmndCounterDebounceLow, &CmndCounterDebounceHigh }; + +uint8_t ctr_index[MAX_COUNTERS] = { 0, 1, 2, 3 }; + +struct COUNTER { + uint32_t timer[MAX_COUNTERS]; + uint32_t timer_low_high[MAX_COUNTERS]; + uint8_t no_pullup = 0; + uint8_t pin_state = 0; + bool any_counter = false; + +} Counter; + +#ifdef USE_AC_ZERO_CROSS_DIMMER +struct AC_ZERO_CROSS_DIMMER { + bool startReSync = false; + uint32_t current_cycle_ClockCycles = 0; + uint32_t dimm_timeClockCycles = 0; + uint32_t currentCycleCount = 0; + uint32_t tobe_cycle_timeClockCycles = 0; + uint32_t lastCycleCount = 0; + uint32_t currentSteps = 100; +} ac_zero_cross_dimmer; +#endif + +void ICACHE_RAM_ATTR CounterIsrArg(void *arg) { + uint32_t index = *static_cast(arg); + + uint32_t time = micros(); + uint32_t debounce_time; + + if (Counter.pin_state) { + + if (digitalRead(Pin(GPIO_CNTR1, index)) == bitRead(Counter.pin_state, index)) { + + return; + } + debounce_time = time - Counter.timer_low_high[index]; + if bitRead(Counter.pin_state, index) { + + if (debounce_time <= Settings.pulse_counter_debounce_high * 1000) return; + } else { + + if (debounce_time <= Settings.pulse_counter_debounce_low * 1000) return; + } + + Counter.timer_low_high[index] = time; + Counter.pin_state ^= (1<0) { + ac_zero_cross_dimmer.startReSync = true; + ac_zero_cross_dimmer.currentSteps = (ac_zero_cross_dimmer.currentCycleCount-ac_zero_cross_dimmer.lastCycleCount+(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles/2))/(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles); + ac_zero_cross_dimmer.current_cycle_ClockCycles = (ac_zero_cross_dimmer.currentCycleCount-ac_zero_cross_dimmer.lastCycleCount)/ac_zero_cross_dimmer.currentSteps; + } + ac_zero_cross_dimmer.lastCycleCount = ac_zero_cross_dimmer.currentCycleCount; + } +#endif + return; + } + } + + 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]++; + } + } +} + + + +void CounterInterruptDisable(bool state) { + if (state) { + if (Counter.any_counter) { + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (PinUsed(GPIO_CNTR1, i)) { + detachInterrupt(Pin(GPIO_CNTR1, i)); + } + } + Counter.any_counter = false; + } + } else { + if (!Counter.any_counter) { + CounterInit(); + } + } +} + +bool CounterPinState(void) +{ + if ((XdrvMailbox.index >= AGPIO(GPIO_CNTR1_NP)) && (XdrvMailbox.index < (AGPIO(GPIO_CNTR1_NP) + MAX_COUNTERS))) { + bitSet(Counter.no_pullup, XdrvMailbox.index - AGPIO(GPIO_CNTR1_NP)); + XdrvMailbox.index -= (AGPIO(GPIO_CNTR1_NP) - AGPIO(GPIO_CNTR1)); + return true; + } + return false; +} + +void CounterInit(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (PinUsed(GPIO_CNTR1, i)) { +#ifdef USE_AC_ZERO_CROSS_DIMMER + ac_zero_cross_dimmer.tobe_cycle_timeClockCycles = microsecondsToClockCycles(1000000 / Settings.pwm_frequency); +#endif + Counter.any_counter = true; + pinMode(Pin(GPIO_CNTR1, i), bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); + if ((0 == Settings.pulse_counter_debounce_low) && (0 == Settings.pulse_counter_debounce_high) && !Settings.flag4.zerocross_dimmer) { + Counter.pin_state = 0; + attachInterruptArg(Pin(GPIO_CNTR1, i), CounterIsrArg, &ctr_index[i], FALLING); + } else { + Counter.pin_state = 0x8f; + attachInterruptArg(Pin(GPIO_CNTR1, i), CounterIsrArg, &ctr_index[i], CHANGE); + } + } + } +} + +void CounterEverySecond(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (PinUsed(GPIO_CNTR1, i)) { + if (bitRead(Settings.pulse_counter_type, i)) { + uint32_t time = micros() - Counter.timer[i]; + if (time > 4200000000) { + RtcSettings.pulse_counter[i] = 4200000000; + } + } + } + } +} + +void CounterSaveState(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (PinUsed(GPIO_CNTR1, i)) { + 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 (PinUsed(GPIO_CNTR1, i)) { + 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 + if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + RtcSettings.pulse_counter[i] = 0; + } +#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 (header) { + ResponseJsonEnd(); + } +} + +#ifdef USE_AC_ZERO_CROSS_DIMMER +void SyncACDimmer(void) +{ + if (ac_zero_cross_dimmer.startReSync) { + + for (uint32_t i = 0; i < 1; i++) { + if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) + { + + const uint32_t current_cycle = ESP.getCycleCount(); + digitalWrite(Pin(GPIO_PWM1, i), LOW); + + ac_zero_cross_dimmer.startReSync = false; + + + ac_zero_cross_dimmer.dimm_timeClockCycles = (ac_zero_cross_dimmer.tobe_cycle_timeClockCycles * (1024 - (Light.fade_running ? Light.fade_cur_10[i] : Light.fade_start_10[i]))) / 1024; + ac_zero_cross_dimmer.dimm_timeClockCycles = tmax(ac_zero_cross_dimmer.dimm_timeClockCycles, 16000); + + uint32_t timelag_ClockCycles = (current_cycle - ac_zero_cross_dimmer.currentCycleCount)%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles; + timelag_ClockCycles = ((ac_zero_cross_dimmer.dimm_timeClockCycles + ac_zero_cross_dimmer.tobe_cycle_timeClockCycles) - timelag_ClockCycles)%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles; + delayMicroseconds(clockCyclesToMicroseconds(timelag_ClockCycles)); + + #ifdef ESP8266 + pinMode(Pin(GPIO_PWM1, i), OUTPUT); + + uint32_t high = ac_zero_cross_dimmer.current_cycle_ClockCycles / 256; + uint32_t low = ac_zero_cross_dimmer.current_cycle_ClockCycles - high; + + startWaveformClockCycles(Pin(GPIO_PWM1, i), high, low, 0, -1, 0, true); + #else + analogWrite(Pin(GPIO_PWM1, i), 5); + #endif + + } + } + } +} +#endif + + + + + +void CmndCounter(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.data_len > 0) && PinUsed(GPIO_CNTR1, XdrvMailbox.index -1)) { + 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) && PinUsed(GPIO_CNTR1, XdrvMailbox.index -1)) { + 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); +} + +void CmndCounterDebounceLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce_low = XdrvMailbox.payload; + CounterInit(); + } + ResponseCmndNumber(Settings.pulse_counter_debounce_low); +} + +void CmndCounterDebounceHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce_high = XdrvMailbox.payload; + CounterInit(); + } + ResponseCmndNumber(Settings.pulse_counter_debounce_high); +} + + + + + +bool Xsns01(uint8_t function) +{ + bool result = false; + + if (Counter.any_counter) { + switch (function) { + case FUNC_EVERY_SECOND: + CounterEverySecond(); + break; + case FUNC_JSON_APPEND: + CounterShow(1); + break; +#ifdef USE_AC_ZERO_CROSS_DIMMER + case FUNC_LOOP: + SyncACDimmer(); + break; +#endif +#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; + } + } else { + switch (function) { + case FUNC_INIT: + CounterInit(); + break; + case FUNC_PIN_STATE: + result = CounterPinState(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" +#ifdef USE_ADC + + + + +#define XSNS_02 2 + +#ifdef ESP8266 +#define ANALOG_RESOLUTION 10 +#define ANALOG_RANGE 1023 +#else +#undef ANALOG_RESOLUTION +#define ANALOG_RESOLUTION 12 +#undef ANALOG_RANGE +#define ANALOG_RANGE 4095 +#endif + +#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 +# 68 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" +#define ANALOG_CT_FLAGS 0 +#define ANALOG_CT_MULTIPLIER 2146 +#define ANALOG_CT_VOLTAGE 2300 + +#define CT_FLAG_ENERGY_RESET (1 << 0) +# 83 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" +#define ANALOG_BUTTON 128 +# 94 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" +#define ANALOG_JOYSTICK (ANALOG_RANGE / 3) +100 + +struct { + uint8_t present = 0; + uint8_t type = 0; +} Adcs; + +struct { + float temperature = 0; + float current = 0; + float energy = 0; + uint32_t param1 = 0; + uint32_t param2 = 0; + int param3 = 0; + int param4 = 0; + uint32_t previous_millis = 0; + uint16_t last_value = 0; + uint8_t type = 0; + uint8_t pin = 0; +} Adc[MAX_ADCS]; + +#ifdef ESP8266 +bool adcAttachPin(uint8_t pin) { + return (ADC0_PIN == pin); +} +#endif + +void AdcSaveSettings(uint32_t idx) { + char parameters[32]; + snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"), + Adc[idx].type, Adc[idx].param1, Adc[idx].param2, Adc[idx].param3, Adc[idx].param4); + SettingsUpdateText(SET_ADC_PARAM1 + idx, parameters); +} + +void AdcGetSettings(uint32_t idx) { + char parameters[32]; + Adcs.type = 0; + Adc[idx].param1 = 0; + Adc[idx].param2 = 0; + Adc[idx].param3 = 0; + Adc[idx].param4 = 0; + if (strstr(SettingsText(SET_ADC_PARAM1 + idx), ",") != nullptr) { + Adcs.type = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 1)); + Adc[idx].param1 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 2)); + Adc[idx].param2 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 3)); + Adc[idx].param3 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 4)); + Adc[idx].param4 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 5)); + } +} + +void AdcInitParams(uint8_t idx) { + if ((Adcs.type != Adc[idx].type) || (Adc[idx].param1 > 1000000)) { + if (ADC_TEMP == Adc[idx].type) { + + Adc[idx].param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Adc[idx].param2 = ANALOG_NTC_RESISTANCE; + Adc[idx].param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC_LIGHT == Adc[idx].type) { + Adc[idx].param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Adc[idx].param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Adc[idx].param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + else if (ADC_RANGE == Adc[idx].type) { + Adc[idx].param1 = 0; + Adc[idx].param2 = ANALOG_RANGE; + Adc[idx].param3 = 0; + Adc[idx].param4 = 100; + } + else if (ADC_CT_POWER == Adc[idx].type) { + Adc[idx].param1 = ANALOG_CT_FLAGS; + Adc[idx].param2 = ANALOG_CT_MULTIPLIER; + Adc[idx].param3 = ANALOG_CT_VOLTAGE; + } + } + if ((Adcs.type != Adc[idx].type) || (0 == Adc[idx].param1) || (Adc[idx].param1 > ANALOG_RANGE)) { + if ((ADC_BUTTON == Adc[idx].type) || (ADC_BUTTON_INV == Adc[idx].type)) { + Adc[idx].param1 = ANALOG_BUTTON; + } + else if (ADC_JOY == Adc[idx].type) { + Adc[idx].param1 = ANALOG_JOYSTICK; + } + } +} + +void AdcAttach(uint8_t pin, uint8_t type) { + if (Adcs.present == MAX_ADCS) { return; } + Adc[Adcs.present].pin = pin; + if (adcAttachPin(Adc[Adcs.present].pin)) { + Adc[Adcs.present].type = type; + + Adcs.present++; + } +} + +void AdcInit(void) { + Adcs.present = 0; + for (uint32_t i = 0; i < MAX_ADCS; i++) { + if (PinUsed(GPIO_ADC_INPUT, i)) { + AdcAttach(Pin(GPIO_ADC_INPUT, i), ADC_INPUT); + } + if (PinUsed(GPIO_ADC_TEMP, i)) { + AdcAttach(Pin(GPIO_ADC_TEMP, i), ADC_TEMP); + } + if (PinUsed(GPIO_ADC_LIGHT, i)) { + AdcAttach(Pin(GPIO_ADC_LIGHT, i), ADC_LIGHT); + } + if (PinUsed(GPIO_ADC_RANGE, i)) { + AdcAttach(Pin(GPIO_ADC_RANGE, i), ADC_RANGE); + } + if (PinUsed(GPIO_ADC_CT_POWER, i)) { + AdcAttach(Pin(GPIO_ADC_CT_POWER, i), ADC_CT_POWER); + } + if (PinUsed(GPIO_ADC_JOY, i)) { + AdcAttach(Pin(GPIO_ADC_JOY, i), ADC_JOY); + } + } + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if (PinUsed(GPIO_ADC_BUTTON, i)) { + AdcAttach(Pin(GPIO_ADC_BUTTON, i), ADC_BUTTON); + } + else if (PinUsed(GPIO_ADC_BUTTON_INV, i)) { + AdcAttach(Pin(GPIO_ADC_BUTTON_INV, i), ADC_BUTTON_INV); + } + } + + if (Adcs.present) { +#ifdef ESP32 + analogSetClockDiv(1); + analogSetWidth(ANALOG_RESOLUTION); + analogSetAttenuation(ADC_11db); +#endif + for (uint32_t idx = 0; idx < Adcs.present; idx++) { + AdcGetSettings(idx); + AdcInitParams(idx); + AdcSaveSettings(idx); + } + } +} + +uint16_t AdcRead(uint32_t pin, uint32_t factor) { + + + + + + uint32_t samples = 1 << factor; + uint32_t analog = 0; + for (uint32_t i = 0; i < samples; i++) { + analog += analogRead(pin); + delay(1); + } + analog >>= factor; + return analog; +} + +#ifdef USE_RULES +void AdcEvery250ms(void) { + char adc_idx[3] = { 0 }; + uint32_t offset = 0; + for (uint32_t idx = 0; idx < Adcs.present; idx++) { +#ifdef ESP32 + snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1); + offset = 1; +#endif + if (ADC_INPUT == Adc[idx].type) { + uint16_t new_value = AdcRead(Adc[idx].pin, 5); + if ((new_value < Adc[idx].last_value -10) || (new_value > Adc[idx].last_value +10)) { + Adc[idx].last_value = new_value; + uint16_t value = Adc[idx].last_value / 10; + Response_P(PSTR("{\"ANALOG\":{\"A%ddiv10\":%d}}"), idx + offset, (value > 99) ? 100 : value); + XdrvRulesProcess(); + } + } + else if (ADC_JOY == Adc[idx].type) { + uint16_t new_value = AdcRead(Adc[idx].pin, 1); + if (new_value && (new_value != Adc[idx].last_value)) { + Adc[idx].last_value = new_value; + uint16_t value = new_value / Adc[idx].param1; + Response_P(PSTR("{\"ANALOG\":{\"Joy%s\":%d}}"), adc_idx, value); + XdrvRulesProcess(); + } else { + Adc[idx].last_value = 0; + } + } + } +} +#endif + +uint8_t AdcGetButton(uint32_t pin) { + for (uint32_t idx = 0; idx < Adcs.present; idx++) { + if (Adc[idx].pin == pin) { + if (ADC_BUTTON_INV == Adc[idx].type) { + return (AdcRead(Adc[idx].pin, 1) < Adc[idx].param1); + } + else if (ADC_BUTTON == Adc[idx].type) { + return (AdcRead(Adc[idx].pin, 1) > Adc[idx].param1); + } + } + } + return 0; +} + +uint16_t AdcGetLux(uint32_t idx) { + int adc = AdcRead(Adc[idx].pin, 2); + + double resistorVoltage = ((double)adc / ANALOG_RANGE) * ANALOG_V33; + double ldrVoltage = ANALOG_V33 - resistorVoltage; + double ldrResistance = ldrVoltage / resistorVoltage * (double)Adc[idx].param1; + double ldrLux = (double)Adc[idx].param2 * FastPrecisePow(ldrResistance, (double)Adc[idx].param3 / 10000); + + return (uint16_t)ldrLux; +} + +uint16_t AdcGetRange(uint32_t idx) { + + + + int adc = AdcRead(Adc[idx].pin, 2); + double adcrange = ( ((double)Adc[idx].param2 - (double)adc) / ( ((double)Adc[idx].param2 - (double)Adc[idx].param1)) * ((double)Adc[idx].param3 - (double)Adc[idx].param4) + (double)Adc[idx].param4 ); + return (uint16_t)adcrange; +} + +void AdcGetCurrentPower(uint8_t idx, uint8_t factor) { + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + uint16_t analog_min = ANALOG_RANGE; + uint16_t analog_max = 0; + + if (0 == Adc[idx].param1) { + for (uint32_t i = 0; i < samples; i++) { + analog = analogRead(Adc[idx].pin); + if (analog < analog_min) { + analog_min = analog; + } + if (analog > analog_max) { + analog_max = analog; + } + delay(1); + } + Adc[idx].current = (float)(analog_max-analog_min) * ((float)(Adc[idx].param2) / 100000); + } + else { + analog = AdcRead(Adc[idx].pin, 5); + if (analog > Adc[idx].param1) { + Adc[idx].current = ((float)(analog) - (float)Adc[idx].param1) * ((float)(Adc[idx].param2) / 100000); + } + else { + Adc[idx].current = 0; + } + } + + float power = Adc[idx].current * (float)(Adc[idx].param3) / 10; + uint32_t current_millis = millis(); + Adc[idx].energy = Adc[idx].energy + ((power * (current_millis - Adc[idx].previous_millis)) / 3600000000); + Adc[idx].previous_millis = current_millis; +} + +void AdcEverySecond(void) { + for (uint32_t idx = 0; idx < Adcs.present; idx++) { + if (ADC_TEMP == Adc[idx].type) { + int adc = AdcRead(Adc[idx].pin, 2); + + double Rt = (adc * Adc[idx].param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Adc[idx].param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2)); + Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T)); + } + else if (ADC_CT_POWER == Adc[idx].type) { + AdcGetCurrentPower(idx, 5); + } + } +} + +void AdcShowContinuation(bool *jsonflg) { + if (*jsonflg) { + ResponseAppend_P(PSTR(",")); + } else { + ResponseAppend_P(PSTR(",\"ANALOG\":{")); + *jsonflg = true; + } +} + +void AdcShow(bool json) { + bool domo_flag[ADC_END] = { false }; + char adc_name[10] = { 0 }; + char adc_idx[3] = { 0 }; + uint32_t offset = 0; + + bool jsonflg = false; + for (uint32_t idx = 0; idx < Adcs.present; idx++) { +#ifdef ESP32 + snprintf_P(adc_name, sizeof(adc_name), PSTR("Analog%d"), idx +1); + snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1); + offset = 1; +#endif + + switch (Adc[idx].type) { + case ADC_INPUT: { + uint16_t analog = AdcRead(Adc[idx].pin, 5); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"A%d\":%d"), idx + offset, analog); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ANALOG, "", idx + offset, analog); +#endif + } + break; + } + case ADC_TEMP: { + char temperature[33]; + dtostrfd(Adc[idx].temperature, Settings.flag2.temperature_resolution, temperature); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "%s\":%s"), adc_idx, temperature); + if ((0 == tele_period) && (!domo_flag[ADC_TEMP])) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); + domo_flag[ADC_TEMP] = true; +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, Adc[idx].temperature); +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, adc_name, temperature, TempUnit()); +#endif + } + break; + } + case ADC_LIGHT: { + uint16_t adc_light = AdcGetLux(idx); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"" D_JSON_ILLUMINANCE "%s\":%d"), adc_idx, adc_light); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (!domo_flag[ADC_LIGHT])) { + DomoticzSensor(DZ_ILLUMINANCE, adc_light); + domo_flag[ADC_LIGHT] = true; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, adc_name, adc_light); +#endif + } + break; + } + case ADC_RANGE: { + uint16_t adc_range = AdcGetRange(idx); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"" D_JSON_RANGE "%s\":%d"), adc_idx, adc_range); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_RANGE, adc_name, adc_range); +#endif + } + break; + } + case ADC_CT_POWER: { + AdcGetCurrentPower(idx, 5); + + float voltage = (float)(Adc[idx].param3) / 10; + char voltage_chr[FLOATSZ]; + dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); + char current_chr[FLOATSZ]; + dtostrfd(Adc[idx].current, Settings.flag2.current_resolution, current_chr); + char power_chr[FLOATSZ]; + dtostrfd(voltage * Adc[idx].current, Settings.flag2.wattage_resolution, power_chr); + char energy_chr[FLOATSZ]; + dtostrfd(Adc[idx].energy, Settings.flag2.energy_resolution, energy_chr); + + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"CTEnergy%s\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + adc_idx, energy_chr, power_chr, voltage_chr, current_chr); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (!domo_flag[ADC_CT_POWER])) { + DomoticzSensor(DZ_POWER_ENERGY, power_chr); + DomoticzSensor(DZ_VOLTAGE, voltage_chr); + DomoticzSensor(DZ_CURRENT, current_chr); + domo_flag[ADC_CT_POWER] = true; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); + WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); + WSContentSend_PD(HTTP_SNS_POWER, power_chr); + WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); +#endif + } + break; + } + case ADC_JOY: { + uint16_t new_value = AdcRead(Adc[idx].pin, 1); + uint16_t value = new_value / Adc[idx].param1; + if (json) { + AdcShowContinuation(&jsonflg); + ResponseAppend_P(PSTR("\"Joy%s\":%d"), adc_idx, value); + } + break; + } + } + } + if (jsonflg) { + ResponseJsonEnd(); + } +} + + + + + +const char kAdcCommands[] PROGMEM = "|" + D_CMND_ADCPARAM; + +void (* const AdcCommand[])(void) PROGMEM = { + &CmndAdcParam }; + +void CmndAdcParam(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_ADCS)) { + uint8_t idx = XdrvMailbox.index -1; + if (XdrvMailbox.data_len) { + if (XdrvMailbox.payload > ADC_INPUT) { + AdcGetSettings(idx); + if (ChrCount(XdrvMailbox.data, ",") > 2) { + char sub_string[XdrvMailbox.data_len +1]; + + + + + + + + Adc[idx].type = XdrvMailbox.payload; + Adc[idx].param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Adc[idx].param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + if (ADC_RANGE == XdrvMailbox.payload) { + Adc[idx].param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); + Adc[idx].param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); + } else { + Adc[idx].param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } + if (ADC_CT_POWER == XdrvMailbox.payload) { + if (((1 == Adc[idx].param1) & CT_FLAG_ENERGY_RESET) > 0) { + for (uint32_t idx = 0; idx < MAX_ADCS; idx++) { + Adc[idx].energy = 0; + } + Adc[idx].param1 ^= CT_FLAG_ENERGY_RESET; + } + } + } else { + + + + + + + + Adcs.type = 0; + AdcInitParams(idx); + } + AdcSaveSettings(idx); + } + } + + + AdcGetSettings(idx); + Response_P(PSTR("{\"" D_CMND_ADCPARAM "%d\":[%d,%d,%d"), idx +1, Adcs.type, Adc[idx].param1, Adc[idx].param2); + if (ADC_RANGE == Adc[idx].type) { + ResponseAppend_P(PSTR(",%d,%d"), Adc[idx].param3, Adc[idx].param4); + } else { + int value = Adc[idx].param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Adc[idx].param3)/10000, precision, param3); + ResponseAppend_P(PSTR(",%s"), param3); + } + ResponseAppend_P(PSTR("]}")); + } +} + + + + + +bool Xsns02(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kAdcCommands, AdcCommand); + break; + case FUNC_MODULE_INIT: + AdcInit(); + break; + default: + if (Adcs.present) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdcEvery250ms(); + break; +#endif + case FUNC_EVERY_SECOND: + AdcEverySecond(); + break; + case FUNC_JSON_APPEND: + AdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AdcShow(0); + break; +#endif + } + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_04_snfsc.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_04_snfsc.ino" +#ifdef USE_SONOFF_SC +# 57 "/workspace/Tasmota/tasmota/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]); + + if (json) { + ResponseAppend_P(PSTR(",\"SonoffSC\":{")); + ResponseAppendTHD(t, h); + ResponseAppend_P(PSTR(",\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), sc_value[2], sc_value[3], sc_value[4]); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumPressureSensor(t, h); + 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_THD("", t, h); + 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_JSON_APPEND: + SonoffScShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SonoffScShow(0); + break; +#endif + case FUNC_INIT: + SonoffScInit(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" +#ifdef ESP8266 +#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; +uint8_t ds18x20_pin_out = 0; +bool ds18x20_dual_mode = false; +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; + + if (!ds18x20_dual_mode) { + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : 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, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin); + delayMicroseconds(410); + return r; + } else { + digitalWrite(ds18x20_pin_out, HIGH); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(480); + digitalWrite(ds18x20_pin_out, HIGH); + 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; + if (!ds18x20_dual_mode) { + digitalWrite(ds18x20_pin, LOW); + pinMode(ds18x20_pin, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin, HIGH); + } else { + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(delay_high[v]); +} + +uint8_t OneWire1ReadBit(void) +{ + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + delayMicroseconds(53); + return r; +} + +uint8_t OneWire2ReadBit(void) +{ + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + digitalWrite(ds18x20_pin_out, HIGH); + 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; + + if (!ds18x20_dual_mode) { + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWire1ReadBit()) { + r |= bit_mask; + } + } + } else { + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWire2ReadBit()) { + 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 { + if (!ds18x20_dual_mode) { + id_bit = OneWire1ReadBit(); + cmp_id_bit = OneWire1ReadBit(); + } else { + id_bit = OneWire2ReadBit(); + cmp_id_bit = OneWire2ReadBit(); + } + 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); + + if (PinUsed(GPIO_DSB_OUT)) { + ds18x20_pin_out = Pin(GPIO_DSB_OUT); + ds18x20_dual_mode = true; + pinMode(ds18x20_pin_out, OUTPUT); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } + + 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: { +# 389 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" + int16_t tempS = (((data[1] << 8) | (data[0] & 0xFE)) << 3) | ((0x10 - data[6]) & 0x0F); + ds18x20_sensor[index].temperature = ConvertTemp(tempS * 0.0625 - 0.250); + + 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) +{ + if (!ds18x20_sensors) { return; } + +#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) { + 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 (PinUsed(GPIO_DSB)) { + 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 +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_05_ds18x20_esp32.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_05_ds18x20_esp32.ino" +#ifdef ESP32 +#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_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 }; + +uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; +uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_valid[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +char ds18x20_types[12]; + + + +#include + +OneWire *ds = nullptr; + +void Ds18x20Init(void) { + ds = new OneWire(Pin(GPIO_DSB)); + + Ds18x20Search(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); +} + +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]==DS1822_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; +} + +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; + + t = NAN; + + uint8_t index = ds18x20_index[sensor]; + if (ds18x20_valid[index]) { ds18x20_valid[index]--; } + + ds->reset(); + ds->select(ds18x20_address[index]); + 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[index][0]) { + case DS18S20_CHIPID: { + int16_t tempS = (((data[1] << 8) | (data[0] & 0xFE)) << 3) | ((0x10 - data[6]) & 0x0F); + t = ConvertTemp(tempS * 0.0625 - 0.250); + ds18x20_valid[index] = SENSOR_MAX_MISS; + return true; + } + case DS1822_CHIPID: + case DS18B20_CHIPID: { + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + t = ConvertTemp(sign * temp12 * 0.0625); + ds18x20_valid[index] = SENSOR_MAX_MISS; + return true; + } + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + t = ConvertTemp(temp14 * 0.0625); + ds18x20_valid[index] = 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_address[ds18x20_index[sensor]][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) +{ + if (!ds18x20_sensors) { return; } + + if (uptime & 1) { + + + Ds18x20Convert(); + } else { + float t; + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + + if (!Ds18x20Read(i, t)) { + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_valid[ds18x20_index[i]]); + } + } + } +} + +void Ds18x20Show(bool json) +{ + float t; + + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + if (Ds18x20Read(i, t)) { + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + Ds18x20Name(i); + + if (json) { + char address[17]; + for (uint32_t j = 0; j < 6; j++) { + sprintf(address+2*j, "%02X", ds18x20_address[ds18x20_index[i]][6-j]); + } + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); + dsxflg++; +#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 { + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); +#endif + } + } + } +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_DSB)) { + 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 +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" +#ifdef USE_DHT +# 30 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + uint8_t lastresult; + char stype[12]; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtWaitState(uint32_t sensor, uint32_t level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (TimeReachedUsec(timeout)) { + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), + (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); + return false; + } + delayMicroseconds(1); + } + return true; +} + +bool DhtRead(uint32_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + + delayMicroseconds(2000); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + delayMicroseconds(20); + break; + } +# 134 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" + uint32_t i = 0; + noInterrupts(); + if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + for (i = 0; i < 40; i++) { + if (!DhtWaitState(sensor, 1)) { break; } + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + dht_data[i / 8] |= (1 << (7 - i % 8)); + } + if (!DhtWaitState(sensor, 0)) { break; } + } + } + interrupts(); + if (i < 40) { return false; } + + 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; + } + + float temperature = NAN; + float humidity = NAN; + switch (Dht[sensor].type) { + case GPIO_DHT11: + humidity = dht_data[0]; + temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + temperature *= -1; + } + break; + } + if (isnan(temperature) || isnan(humidity)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); + return false; + } + + if (humidity > 100) { humidity = 100.0; } + if (humidity < 0) { humidity = 0.1; } + Dht[sensor].h = ConvertHumidity(humidity); + Dht[sensor].t = ConvertTemp(temperature); + Dht[sensor].lastresult = 0; + + return true; +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= AGPIO(GPIO_DHT11)) && (XdrvMailbox.index <= AGPIO(GPIO_SI7021))) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = BGPIO(XdrvMailbox.index); + dht_sensors++; + XdrvMailbox.index = AGPIO(GPIO_DHT11); + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (PinUsed(GPIO_DHT11_OUT)) { + dht_pin_out = Pin(GPIO_DHT11_OUT); + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastresult = DHT_MAX_RETRY; + 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); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { + + if (!DhtRead(sensor)) { + Dht[sensor].lastresult++; + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + } + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + TempHumDewShow(json, ((0 == tele_period) && (0 == i)), Dht[i].stype, Dht[i].t, Dht[i].h); + } +} + + + + + +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 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" +#ifdef USE_I2C +#ifdef USE_SHT +# 31 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" +#define XSNS_07 7 +#define XI2C_08 8 + +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) { + + 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)); + + 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); + sht_humidity = ConvertHumidity(sht_humidity); + + sht_valid = SENSOR_MAX_MISS; + return true; +} + + + +void ShtDetect(void) +{ + 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 (!(uptime %4)) { + + if (!ShtRead()) { + AddLogMissed(sht_types, sht_valid); + } + } +} + +void ShtShow(bool json) +{ + if (sht_valid) { + TempHumDewShow(json, (0 == tele_period), sht_types, sht_temperature, sht_humidity); + } +} + + + + + +bool Xsns07(uint8_t function) +{ + if (!I2cEnabled(XI2C_08)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + ShtDetect(); + } + else if (sht_type) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" +#ifdef USE_I2C +#ifdef USE_HTU +# 30 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" +#define XSNS_08 8 +#define XI2C_09 9 + +#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?"; + +struct { + float temperature = 0; + float humidity = 0; + uint8_t address; + uint8_t type = 0; + uint8_t delay_temp; + uint8_t delay_humidity = 50; + uint8_t valid = 0; + char types[7]; +} Htu; + + + +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) +{ + HtuReset(); + + 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; + } + Htu.humidity = ConvertHumidity(Htu.humidity); + + Htu.valid = SENSOR_MAX_MISS; + return true; +} + + + +void HtuDetect(void) +{ + Htu.address = HTU21_ADDR; + if (I2cActive(Htu.address)) { return; } + + 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); + I2cSetActiveFound(Htu.address, Htu.types); + } +} + +void HtuEverySecond(void) +{ + if (uptime &1) { + + if (!HtuRead()) { + AddLogMissed(Htu.types, Htu.valid); + } + } +} + +void HtuShow(bool json) +{ + if (Htu.valid) { + TempHumDewShow(json, (0 == tele_period), Htu.types, Htu.temperature, Htu.humidity); + } +} + + + + + +bool Xsns08(uint8_t function) +{ + if (!I2cEnabled(XI2C_09)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + HtuDetect(); + } + else if (Htu.type) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" +#ifdef USE_I2C +#ifdef USE_BMP +# 30 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" +#define XSNS_09 9 +#define XI2C_10 10 + +#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_REGISTER_RESET 0xE0 + +#define BMP_CMND_RESET 0xB6 + +#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) +{ + 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++) { + if (I2cActive(bmp_addresses[i])) { continue; } + 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); + I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); + bmp_count++; + } + } + } +} + +void BmpRead(void) +{ + 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 + } + } +} + +void BmpShow(bool json) +{ + 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); + + float bmp_humidity = ConvertHumidity(bmp_sensors[bmp_idx].bmp_humidity); + char humidity[33]; + dtostrfd(bmp_humidity, Settings.flag2.humidity_resolution, humidity); + float f_dewpoint = CalcTempHumToDew(bmp_temperature, bmp_humidity); + char dewpoint[33]; + dtostrfd(f_dewpoint, Settings.flag2.temperature_resolution, dewpoint); +#ifdef USE_BME680 + char gas_resistance[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); +#endif + + if (json) { + char json_humidity[80]; + snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_DEWPOINT "\":%s"), humidity, dewpoint); + 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(bmp_temperature, bmp_humidity, bmp_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_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_DEW, name, dewpoint, TempUnit()); + } + 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 + } + } + } +} + +#ifdef USE_DEEPSLEEP + +void BMP_EnterSleep(void) +{ + if (DeepSleepEnabled()) { + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + case BMP280_CHIPID: + case BME280_CHIPID: + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); + break; + default: + break; + } + } + } +} + +#endif + + + + + +bool Xsns09(uint8_t function) +{ + if (!I2cEnabled(XI2C_10)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + BmpDetect(); + } + else if (bmp_count) { + switch (function) { + case FUNC_EVERY_SECOND: + BmpRead(); + break; + case FUNC_JSON_APPEND: + BmpShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + BmpShow(0); + break; +#endif +#ifdef USE_DEEPSLEEP + case FUNC_SAVE_BEFORE_RESTART: + BMP_EnterSleep(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" +#ifdef USE_I2C +#ifdef USE_BH1750 +# 33 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" +#define XSNS_10 10 +#define XI2C_11 11 + +#define BH1750_ADDR1 0x23 +#define BH1750_ADDR2 0x5C + +#define BH1750_CONTINUOUS_HIGH_RES_MODE2 0x11 +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 +#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 + +#define BH1750_MEASUREMENT_TIME_HIGH 0x40 +#define BH1750_MEASUREMENT_TIME_LOW 0x60 + +#define D_PRFX_BH1750 "Bh1750" +#define D_CMND_RESOLUTION "Resolution" +#define D_CMND_MTREG "MTime" + +const char kBh1750Commands[] PROGMEM = D_PRFX_BH1750 "|" + D_CMND_RESOLUTION "|" D_CMND_MTREG ; + +void (* const Bh1750Command[])(void) PROGMEM = { + &CmndBh1750Resolution, &CmndBh1750MTime }; + +struct { + uint8_t addresses[2] = { BH1750_ADDR1, BH1750_ADDR2 }; + uint8_t resolution[3] = { BH1750_CONTINUOUS_HIGH_RES_MODE, BH1750_CONTINUOUS_HIGH_RES_MODE2, BH1750_CONTINUOUS_LOW_RES_MODE }; + uint8_t count = 0; + char types[7] = "BH1750"; +} Bh1750; + +struct { + uint8_t address; + uint8_t valid = 0; + uint8_t mtreg = 69; + uint16_t illuminance = 0; +} Bh1750_sensors[2]; + + + +uint8_t Bh1750Resolution(uint32_t sensor_index) { + uint8_t settings_resolution = Settings.SensorBits1.bh1750_1_resolution; + if (1 == sensor_index) { + settings_resolution = Settings.SensorBits1.bh1750_2_resolution; + } + return settings_resolution; +} + +bool Bh1750SetResolution(uint32_t sensor_index) { + Wire.beginTransmission(Bh1750_sensors[sensor_index].address); + Wire.write(Bh1750.resolution[Bh1750Resolution(sensor_index)]); + return (!Wire.endTransmission()); +} + +bool Bh1750SetMTreg(uint32_t sensor_index) { + Wire.beginTransmission(Bh1750_sensors[sensor_index].address); + uint8_t data = BH1750_MEASUREMENT_TIME_HIGH | ((Bh1750_sensors[sensor_index].mtreg >> 5) & 0x07); + Wire.write(data); + if (Wire.endTransmission()) { return false; } + Wire.beginTransmission(Bh1750_sensors[sensor_index].address); + data = BH1750_MEASUREMENT_TIME_LOW | (Bh1750_sensors[sensor_index].mtreg & 0x1F); + Wire.write(data); + if (Wire.endTransmission()) { return false; } + return Bh1750SetResolution(sensor_index); +} + +bool Bh1750Read(uint32_t sensor_index) { + if (Bh1750_sensors[sensor_index].valid) { Bh1750_sensors[sensor_index].valid--; } + + if (2 != Wire.requestFrom(Bh1750_sensors[sensor_index].address, (uint8_t)2)) { return false; } + + float illuminance = (Wire.read() << 8) | Wire.read(); + illuminance /= (1.2 * (69 / (float)Bh1750_sensors[sensor_index].mtreg)); + if (1 == Bh1750Resolution(sensor_index)) { + illuminance /= 2; + } + Bh1750_sensors[sensor_index].illuminance = illuminance; + + Bh1750_sensors[sensor_index].valid = SENSOR_MAX_MISS; + return true; +} + + + +void Bh1750Detect(void) { + for (uint32_t i = 0; i < sizeof(Bh1750.addresses); i++) { + if (I2cActive(Bh1750.addresses[i])) { continue; } + + Bh1750_sensors[Bh1750.count].address = Bh1750.addresses[i]; + if (Bh1750SetMTreg(Bh1750.count)) { + I2cSetActiveFound(Bh1750_sensors[Bh1750.count].address, Bh1750.types); + Bh1750.count++; + } + } +} + +void Bh1750EverySecond(void) { + for (uint32_t i = 0; i < Bh1750.count; i++) { + + if (!Bh1750Read(i)) { + + } + } +} + + + + + +void CmndBh1750Resolution(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Bh1750.count)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + if (1 == XdrvMailbox.index) { + Settings.SensorBits1.bh1750_1_resolution = XdrvMailbox.payload; + } else { + Settings.SensorBits1.bh1750_2_resolution = XdrvMailbox.payload; + } + Bh1750SetResolution(XdrvMailbox.index -1); + } + ResponseCmndIdxNumber(Bh1750Resolution(XdrvMailbox.index -1)); + } +} + +void CmndBh1750MTime(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Bh1750.count)) { + if ((XdrvMailbox.payload > 30) && (XdrvMailbox.payload < 255)) { + Bh1750_sensors[XdrvMailbox.index -1].mtreg = XdrvMailbox.payload; + Bh1750SetMTreg(XdrvMailbox.index -1); + } + ResponseCmndIdxNumber(Bh1750_sensors[XdrvMailbox.index -1].mtreg); + } +} + + + +void Bh1750Show(bool json) { + for (uint32_t sensor_index = 0; sensor_index < Bh1750.count; sensor_index++) { + if (Bh1750_sensors[sensor_index].valid) { + char sensor_name[10]; + strlcpy(sensor_name, Bh1750.types, sizeof(sensor_name)); + if (Bh1750.count > 1) { + snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), Bh1750_sensors[sensor_index].address); + } + + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, sensor_name, Bh1750_sensors[sensor_index].illuminance); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == sensor_index)) { + DomoticzSensor(DZ_ILLUMINANCE, Bh1750_sensors[sensor_index].illuminance); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor_name, Bh1750_sensors[sensor_index].illuminance); +#endif + } + } + } +} + + + + + +bool Xsns10(uint8_t function) { + if (!I2cEnabled(XI2C_11)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Bh1750Detect(); + } + else if (Bh1750.count) { + switch (function) { + case FUNC_EVERY_SECOND: + Bh1750EverySecond(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kBh1750Commands, Bh1750Command); + break; + case FUNC_JSON_APPEND: + Bh1750Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bh1750Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_11_veml6070.ino" +# 89 "/workspace/Tasmota/tasmota/xsns_11_veml6070.ino" +#ifdef USE_I2C +#ifdef USE_VEML6070 + + + + + + +#define XSNS_11 11 +#define XI2C_12 12 + +#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; +char veml6070_name[9]; +char str_uvrisk_text[10]; + + + +void Veml6070Detect(void) +{ + if (I2cActive(VEML6070_ADDR_L)) { return; } + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((itime << 2) | 0x02); + uint8_t status = Wire.endTransmission(); + + if (!status) { + veml6070_type = 1; + Veml6070UvTableInit(); + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); + } +} + + + +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) +{ + + 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, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); + } +} + + + +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) +{ + + 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) +{ + if (!I2cEnabled(XI2C_12)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Veml6070Detect(); + } + else if (veml6070_type) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" +#ifdef USE_I2C +#ifdef USE_ADS1115 +# 43 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" +#define XSNS_12 12 +#define XI2C_13 13 + +#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) + +struct ADS1115 { + uint8_t count = 0; + uint8_t address; + uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; + uint8_t found[4] = {false,false,false,false}; + int16_t last_values[4][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}; +} Ads1115; + + + +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) +{ + for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { + if (!Ads1115.found[i]) { + Ads1115.address = Ads1115.addresses[i]; + if (I2cActive(Ads1115.address)) { continue; } + uint16_t buffer; + if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); + I2cSetActiveFound(Ads1115.address, "ADS1115"); + Ads1115.found[i] = 1; + Ads1115.count++; + } + } + } +} + + +void Ads1115Label(char* label, uint32_t maxsize, uint8_t address) { + if (1 == Ads1115.count) { + + snprintf_P(label, maxsize, PSTR("ADS1115")); + } else { + + snprintf_P(label, maxsize, PSTR("ADS1115%c%02x"), IndexSeparator(), address); + } +} + +#ifdef USE_RULES + + +void AdsEvery250ms(void) +{ + int16_t value; + + for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { + if (Ads1115.found[t]) { + + uint8_t old_address = Ads1115.address; + Ads1115.address = Ads1115.addresses[t]; + + + uint32_t changed = 0; + for (uint32_t i = 0; i < 4; i++) { + value = Ads1115GetConversion(i); + + + + if (value >= Ads1115.last_values[t][i] + 327 || value <= Ads1115.last_values[t][i] - 327) { + Ads1115.last_values[t][i] = value; + bitSet(changed, i); + } + } + Ads1115.address = old_address; + if (changed) { + char label[15]; + Ads1115Label(label, sizeof(label), Ads1115.addresses[t]); + + Response_P(PSTR("{\"%s\":{"), label); + + bool first = true; + for (uint32_t i = 0; i < 4; i++) { + if (bitRead(changed, i)) { + ResponseAppend_P(PSTR("%s\"A%ddiv10\":%d"), (first) ? "" : ",", i, Ads1115.last_values[t][i]); + first = false; + } + } + ResponseJsonEndEnd(); + + XdrvRulesProcess(); + } + + } + } +} +#endif + +void Ads1115Show(bool json) +{ + int16_t values[4]; + + for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { + + if (Ads1115.found[t]) { + + uint8_t old_address = Ads1115.address; + Ads1115.address = Ads1115.addresses[t]; + for (uint32_t i = 0; i < 4; i++) { + values[i] = Ads1115GetConversion(i); + + } + Ads1115.address = old_address; + + char label[15]; + Ads1115Label(label, sizeof(label), Ads1115.addresses[t]); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{"), label); + for (uint32_t i = 0; i < 4; i++) { + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); + } + ResponseJsonEnd(); + } +#ifdef USE_WEBSERVER + else { + for (uint32_t i = 0; i < 4; i++) { + WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); + } + } +#endif + } + } +} + + + + + +bool Xsns12(uint8_t function) +{ + if (!I2cEnabled(XI2C_13)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ads1115Detect(); + } + else if (Ads1115.count) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdsEvery250ms(); + break; +#endif + case FUNC_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ads1115Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" +#ifdef USE_I2C +#ifdef USE_INA219 +# 30 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" +#define XSNS_13 13 +#define XI2C_14 14 + +#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_1S_84US (0x0<<7) +#define INA219_CONFIG_BADCRES_10BIT_1S_148US (0x1<<7) +#define INA219_CONFIG_BADCRES_11BIT_1S_276US (0x2<<7) +#define INA219_CONFIG_BADCRES_12BIT_1S_532US (0x3<<7) +#define INA219_CONFIG_BADCRES_12BIT_2S_1060US (0x9<<7) +#define INA219_CONFIG_BADCRES_12BIT_4S_2130US (0xA<<7) +#define INA219_CONFIG_BADCRES_12BIT_8S_4260US (0xB<<7) +#define INA219_CONFIG_BADCRES_12BIT_16S_8510US (0xC<<7) +#define INA219_CONFIG_BADCRES_12BIT_32S_17MS (0xD<<7) +#define INA219_CONFIG_BADCRES_12BIT_64S_34MS (0xE<<7) +#define INA219_CONFIG_BADCRES_12BIT_128S_69MS (0xF<<7) + +#define INA219_CONFIG_SADCRES_MASK (0x0078) +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0<<3) +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x1<<3) +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x2<<3) +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x3<<3) +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x9<<3) +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0xA<<3) +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0xB<<3) +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0xC<<3) +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0xD<<3) +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0xE<<3) +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0xF<<3) + +#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) + +#define INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS (100.0) + +uint8_t ina219_type[4] = {0,0,0,0}; +uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; + +#ifdef DEBUG_TASMOTA_SENSOR + +char __ina219_dbg1[10]; +char __ina219_dbg2[10]; +#endif + + + + +float ina219_current_multiplier; + +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"; +uint8_t ina219_count = 0; +# 132 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" +bool Ina219SetCalibration(uint8_t mode, uint16_t addr) +{ + uint16_t config = 0; + + DEBUG_SENSOR_LOG("Ina219SetCalibration: mode=%d",mode); + if (mode < 5) + { + + ina219_current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + DEBUG_SENSOR_LOG("Ina219SetCalibration: cur_mul=%s",__ina219_dbg1); + #endif + } + else if (mode >= 10) + { + int mult = mode % 10; + int shunt_milliOhms = mode / 10; + for ( ; mult > 0 ; mult-- ) + shunt_milliOhms *= 10; + ina219_current_multiplier = 1.0 / shunt_milliOhms; + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + DEBUG_SENSOR_LOG("Ina219SetCalibration: shunt=%dmO => cur_mul=%s",shunt_milliOhms,__ina219_dbg1); + #endif + } + config = INA219_CONFIG_BVOLTAGERANGE_32V + | INA219_CONFIG_GAIN_8_320MV + | INA219_CONFIG_BADCRES_12BIT_16S_8510US + | INA219_CONFIG_SADCRES_12BIT_16S_8510US + | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + + return I2cWrite16(addr, INA219_REG_CONFIG, config); +} + +float Ina219GetShuntVoltage_mV(uint16_t addr) +{ + + int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); + DEBUG_SENSOR_LOG("Ina219GetShuntVoltage_mV: ShReg = 0x%04X",value); + + return value * 0.01; +} + +float Ina219GetBusVoltage_V(uint16_t addr) +{ + + uint16_t value = I2cRead16(addr, INA219_REG_BUSVOLTAGE) >> 3; + DEBUG_SENSOR_LOG("Ina219GetBusVoltage_V: BusReg = 0x%04X",value); + + return value * 0.004; +} +# 201 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" +bool Ina219Read(void) +{ + for (int i=0; i= 0) && (XdrvMailbox.payload <= 255)) { + Settings.ina219_mode = XdrvMailbox.payload; + restart_flag = 2; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + + return true; +} + + + +void Ina219Detect(void) +{ + for (uint32_t i = 0; i < sizeof(ina219_type); i++) { + uint16_t addr = ina219_addresses[i]; + if (I2cActive(addr)) { continue; } + if (Ina219SetCalibration(Settings.ina219_mode, addr)) { + I2cSetActiveFound(addr, ina219_types); + ina219_type[i] = 1; + ina219_count++; + } + } +} + +void Ina219EverySecond(void) +{ + + Ina219Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA219_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 Ina219Show(bool json) +{ + int num_found=0; + 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) +{ + if (!I2cEnabled(XI2C_14)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ina219Detect(); + } + else if (ina219_count) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_13 == XdrvMailbox.index) { + result = Ina219CommandSensor(); + } + 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 "/workspace/Tasmota/tasmota/xsns_14_sht3x.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_14_sht3x.ino" +#ifdef USE_I2C +#ifdef USE_SHT3X + + + + + + +#define XSNS_14 14 +#define XI2C_15 15 + +#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) +{ + for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { + if (I2cActive(sht3x_addresses[i])) { continue; } + float t; + float h; + 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); + I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); + sht3x_count++; + } + } +} + +void Sht3xShow(bool json) +{ + for (uint32_t i = 0; i < sht3x_count; i++) { + float t; + float h; + if (Sht3xRead(t, h, sht3x_sensors[i].address)) { + char types[11]; + snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); + TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, t, h); + } + } +} + + + + + +bool Xsns14(uint8_t function) +{ + if (!I2cEnabled(XI2C_15)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Sht3xDetect(); + } + else if (sht3x_count) { + switch (function) { + case FUNC_JSON_APPEND: + Sht3xShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sht3xShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_15_mhz19.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_15_mhz19.ino" +#ifdef USE_MHZ19 +# 33 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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; +#ifdef USE_LIGHT + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); +#endif + + 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); + } + } + } + + } + } + + } +} +# 268 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_MHZ_RXD) && PinUsed(GPIO_MHZ_TXD)) { + 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 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" +#ifdef USE_I2C +#ifdef USE_TSL2561 +# 30 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" +#define XSNS_16 16 +#define XI2C_16 16 + +#include + +Tsl2561 Tsl(Wire); + +uint8_t tsl2561_type = 0; +uint8_t tsl2561_valid = 0; +uint32_t tsl2561_milliLux = 0; +uint32_t tsl2561_full = 0; +uint32_t tsl2561_ir = 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; + + if (Tsl.on()) { + if (Tsl.id(id) + && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) + && Tsl2561Util::normalizedLuminosity(gain, exposure, tsl2561_full = scaledFull, tsl2561_ir = scaledIr)) { + if (! Tsl2561Util::milliLux(tsl2561_full, tsl2561_ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { + tsl2561_milliLux = 0; + } + } else{ + tsl2561_milliLux = 0; + tsl2561_full = 0; + tsl2561_ir = 0; + } + } + tsl2561_valid = SENSOR_MAX_MISS; + return true; +} + +void Tsl2561Detect(void) +{ + if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { + uint8_t id; + Tsl.begin(); + if (!Tsl.id(id)) return; + if (Tsl.on()) { + tsl2561_type = 1; + I2cSetActiveFound(Tsl.address(), tsl2561_types); + } + } +} + +void Tsl2561EverySecond(void) +{ + if (!(uptime %2)) { + + if (!Tsl2561Read()) { + AddLogMissed(tsl2561_types, tsl2561_valid); + } + } +} + +#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,\"IR\":%u,\"Broadband\":%u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000, tsl2561_ir, tsl2561_full); +#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) +{ + if (!I2cEnabled(XI2C_16)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2561Detect(); + } + else if (tsl2561_type) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_17_senseair.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_17_senseair.ino" +#ifdef USE_SENSEAIR +# 29 "/workspace/Tasmota/tasmota/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; +#ifdef USE_LIGHT + LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); +#endif + 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 (PinUsed(GPIO_SAIR_RX) && PinUsed(GPIO_SAIR_TX)) { + 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) +{ + 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(",")); + ResponseAppendTHD(senseair_temperature, senseair_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_THD(senseair_types, senseair_temperature, senseair_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 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" +#ifdef USE_PMS5003 +# 31 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" +#define XSNS_18 18 + +#include + +#ifndef WARMUP_PERIOD +#define WARMUP_PERIOD 30 +#endif + +#ifndef MIN_INTERVAL_PERIOD +#define MIN_INTERVAL_PERIOD 60 +#endif + +TasmotaSerial *PmsSerial; + +struct PMS5003 { + uint16_t time = 0; + uint8_t type = 1; + uint8_t valid = 0; + uint8_t wake_mode = 1; + uint8_t ready = 1; +} Pms; + +enum PmsCommands +{ + CMD_MODE_ACTIVE, + CMD_SLEEP, + CMD_WAKEUP, + CMD_MODE_PASSIVE, + CMD_READ_DATA +}; + +const uint8_t kPmsCommands[][7] PROGMEM = { + + {0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71}, + {0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73}, + {0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74}, + {0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70}, + {0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71}}; + +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 + uint16_t checksum; +} pms_data; + + + +size_t PmsSendCmd(uint8_t command_id) +{ + return PmsSerial->write(kPmsCommands[command_id], sizeof(kPmsCommands[command_id])); +} + + + +bool PmsReadData(void) +{ + if (! PmsSerial->available()) { + return false; + } + while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { + PmsSerial->read(); + } +#ifdef PMS_MODEL_PMS3003 + if (PmsSerial->available() < 22) { +#else + if (PmsSerial->available() < 32) { +#endif + return false; + } + +#ifdef PMS_MODEL_PMS3003 + uint8_t buffer[22]; + PmsSerial->readBytes(buffer, 22); +#else + uint8_t buffer[32]; + PmsSerial->readBytes(buffer, 32); +#endif + uint16_t sum = 0; + PmsSerial->flush(); + +#ifdef PMS_MODEL_PMS3003 + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); +#else + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); +#endif + + +#ifdef PMS_MODEL_PMS3003 + for (uint32_t i = 0; i < 20; i++) { +#else + for (uint32_t i = 0; i < 30; i++) { +#endif + sum += buffer[i]; + } + +#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 + 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 + 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.valid = 10; + + return true; +} +# 172 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" +bool PmsCommandSensor(void) +{ + if (PinUsed(GPIO_PMS5003_TX) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + if (XdrvMailbox.payload < MIN_INTERVAL_PERIOD) { + + Settings.pms_wake_interval = 0; + Pms.wake_mode = 1; + Pms.ready = 1; + PmsSendCmd(CMD_MODE_ACTIVE); + PmsSendCmd(CMD_WAKEUP); + } else { + + Settings.pms_wake_interval = XdrvMailbox.payload; + PmsSendCmd(CMD_MODE_PASSIVE); + PmsSendCmd(CMD_SLEEP); + Pms.wake_mode = 0; + Pms.ready = 0; + } + } + + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_18, Settings.pms_wake_interval); + + return true; +} + + + +void PmsSecond(void) +{ + if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { + + Pms.time++; + if ((Settings.pms_wake_interval - Pms.time <= WARMUP_PERIOD) && !Pms.wake_mode) { + + Pms.wake_mode = 1; + PmsSendCmd(CMD_WAKEUP); + } + if (Pms.time >= Settings.pms_wake_interval) { + + PmsSendCmd(CMD_READ_DATA); + Pms.ready = 1; + Pms.time = 0; + } + } + + if (Pms.ready) { + if (PmsReadData()) { + Pms.valid = 10; + if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { + PmsSendCmd(CMD_SLEEP); + Pms.wake_mode = 0; + Pms.ready = 0; + } + } else { + if (Pms.valid) { + Pms.valid--; + if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { + PmsSendCmd(CMD_READ_DATA); + Pms.ready = 1; + } + } + } + } +} + + + +void PmsInit(void) +{ + Pms.type = 0; + if (PinUsed(GPIO_PMS5003_RX)) { + PmsSerial = new TasmotaSerial(Pin(GPIO_PMS5003_RX), (PinUsed(GPIO_PMS5003_TX)) ? Pin(GPIO_PMS5003_TX) : -1, 1); + if (PmsSerial->begin(9600)) { + if (PmsSerial->hardwareSerial()) { ClaimSerial(); } + + if (!PinUsed(GPIO_PMS5003_TX)) { + Settings.pms_wake_interval = 0; + Pms.ready = 1; + } + + Pms.type = 1; + } + } +} + +#ifdef USE_WEBSERVER +#ifdef PMS_MODEL_PMS3003 +const char HTTP_PMS3003_SNS[] PROGMEM = + + + + "{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_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 +#endif + +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 +#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 { + +#ifdef PMS_MODEL_PMS3003 + WSContentSend_PD(HTTP_PMS3003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#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 +#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_COMMAND_SENSOR: + if (XSNS_18 == XdrvMailbox.index) { + result = PmsCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + PmsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PmsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_19_mgs.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_19_mgs.ino" +#ifdef USE_I2C +#ifdef USE_MGS + + + + + + + +#define XSNS_19 19 +#define XI2C_17 17 + +#ifndef MGS_SENSOR_ADDR +#define MGS_SENSOR_ADDR 0x04 +#endif + +#include "MutichannelGasSensor.h" + +bool mgs_detected = false; + +void MGSInit(void) { + gas.begin(MGS_SENSOR_ADDR); +} + +void MGSPrepare(void) +{ + if (I2cActive(MGS_SENSOR_ADDR)) { return; } + + gas.begin(MGS_SENSOR_ADDR); + if (!gas.isError()) { + I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); + mgs_detected = true; + } +} + +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) +{ + if (!I2cEnabled(XI2C_17)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MGSPrepare(); + } + else if (mgs_detected) { + switch (function) { + case FUNC_JSON_APPEND: + MGSShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGSShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" +#ifdef USE_NOVA_SDS +# 30 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" +#define XSNS_20 20 + +#include + +#ifndef STARTING_OFFSET +#define STARTING_OFFSET 30 +#endif +#if STARTING_OFFSET < 10 +#error "Please set STARTING_OFFSET >= 10" +#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; +uint8_t cont_mode = 1; + +struct sds011data { + uint16_t pm100; + uint16_t pm25; +} novasds_data; +uint16_t pm100_sum; +uint16_t pm25_sum; + + +#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_SLEEP 0 + #define NOVA_SDS_WORK 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, 0, 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 (!novasds_valid) + { + NovaSdsSetWorkPeriod(); + novasds_valid=1; + } + if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) + { + if(!cont_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 - Settings.novasds_startingoffset && !cont_mode) + { + 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) + { + if(!(NovaSdsReadData())) novasds_valid=0; + pm100_sum += novasds_data.pm100; + pm25_sum += novasds_data.pm25; + } + if(tele_period == Settings.tele_period-1) + { + 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); + pm100_sum = pm25_sum = 0; + } +} + + + + + + + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + 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_startingoffset); + + return true; +} + +void NovaSdsInit(void) +{ + novasds_type = 0; + if (PinUsed(GPIO_SDS0X1_RX) && PinUsed(GPIO_SDS0X1_TX)) { + 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 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" +#ifdef USE_I2C +#ifdef USE_SGP30 +# 30 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" +#define XSNS_21 21 +#define XI2C_18 18 + +#define SGP30_ADDRESS 0x58 + +#include "Adafruit_SGP30.h" +Adafruit_SGP30 sgp; + +bool sgp30_type = false; +bool sgp30_ready = false; +float sgp30_abshum; + + + +void sgp30_Init(void) +{ + if (I2cActive(SGP30_ADDRESS)) { return; } + + if (sgp.begin()) { + sgp30_type = true; + + I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); + } +} + + +#define POW_FUNC FastPrecisePow + +float sgp30_AbsoluteHumidity(float temperature, float humidity) { + + + + + + float temp = NAN; + const float mw = 18.01534; + const float r = 8.31447215; + + if (isnan(temperature) || isnan(humidity) ) { + return NAN; + } + + 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 = false; + if (!sgp.IAQmeasure()) { + return; + } + if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { + + sgp30_abshum = sgp30_AbsoluteHumidity(global_temperature_celsius, global_humidity); + sgp.setHumidity(sgp30_abshum*1000); + } + sgp30_ready = true; + + + 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 (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { + + dtostrfd(sgp30_abshum,4,abs_hum); + } + if (json) { + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); + if (global_update && global_humidity>0 && !isnan(global_temperature_celsius)) { + 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) +{ + if (!I2cEnabled(XI2C_18)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + sgp30_Init(); + } + else if (sgp30_type) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" +#ifdef USE_SR04 + +#include +#include +# 32 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" +#define XSNS_22 22 + +uint8_t sr04_type = 1; +real64_t distance; + +NewPing* sonar = nullptr; +TasmotaSerial* sonar_serial = nullptr; + +uint8_t Sr04TModeDetect(void) +{ + sr04_type = 0; + if (!PinUsed(GPIO_SR04_ECHO)) { return sr04_type; } + + int sr04_echo_pin = Pin(GPIO_SR04_ECHO); + int sr04_trig_pin = (PinUsed(GPIO_SR04_TRIG)) ? Pin(GPIO_SR04_TRIG) : Pin(GPIO_SR04_ECHO); + sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); + + if (sonar_serial->begin(9600,1)) { + DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); + + if (sr04_trig_pin != -1) { + sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != NO_ECHO) ? 3 : 1; + } else { + sr04_type = 2; + } + } else { + sr04_type = 1; + } + + if (sr04_type < 2) { + delete sonar_serial; + sonar_serial = nullptr; + if (-1 == sr04_trig_pin) { + sr04_trig_pin = Pin(GPIO_SR04_ECHO); + } + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); + } else { + if (sonar_serial->hardwareSerial()) { + ClaimSerial(); + } + } + + AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); + return sr04_type; +} + +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) +{ + uint16_t ret = first; + if (first > second) { + first = second; + second = ret; + } + + if (third < first) { + return first; + } else if (third > second) { + return second; + } else { + return third; + } +} + +uint16_t Sr04TMode3Distance() { + + sonar_serial->write(0x55); + sonar_serial->flush(); + + return Sr04TMode2Distance(); +} + +uint16_t Sr04TMode2Distance(void) +{ + sonar_serial->setTimeout(300); + const char startByte = 0xff; + + if (!sonar_serial->find(startByte)) { + + return NO_ECHO; + } + + delay(5); + + uint8_t crc = sonar_serial->read(); + + uint16_t distance = ((uint16_t)crc) << 8; + + + distance += sonar_serial->read(); + crc += distance & 0x00ff; + crc += 0x00FF; + + + if (crc != sonar_serial->read()) { + AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); + return NO_ECHO; + } + + return distance; +} + +void Sr04TReading(void) { + + if (sonar_serial==nullptr && sonar==nullptr) { + Sr04TModeDetect(); + } + + switch (sr04_type) { + case 3: + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; + break; + case 2: + + while(sonar_serial->available()) sonar_serial->read(); + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; + break; + case 1: + distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; + break; + default: + distance = NO_ECHO; + } + + return; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_DISTANCE[] PROGMEM = + "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; +#endif + +void Sr04Show(bool json) +{ + + 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 (sr04_type) { + switch (function) { + case FUNC_INIT: + result = (PinUsed(GPIO_SR04_ECHO)); + break; + case FUNC_EVERY_SECOND: + Sr04TReading(); + result = true; + break; + case FUNC_JSON_APPEND: + Sr04Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sr04Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" +#ifdef USE_I2C +#ifdef USE_SI1145 +# 30 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" +#define XSNS_24 24 +#define XI2C_19 19 + +#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 + +uint16_t si1145_visible; +uint16_t si1145_infrared; +uint16_t si1145_uvindex; + +bool si1145_type = false; +uint8_t si1145_valid = 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); +} + + + +bool Si1145Read(void) +{ + if (si1145_valid) { si1145_valid--; } + + if (!Si1145Present()) { return false; } + + si1145_visible = Si1145ReadVisible(); + si1145_infrared = Si1145ReadIR(); + si1145_uvindex = Si1145ReadUV(); + si1145_valid = SENSOR_MAX_MISS; + return true; +} + +void Si1145Detect(void) +{ + if (I2cActive(SI114X_ADDR)) { return; } + + if (Si1145Begin()) { + si1145_type = true; + I2cSetActiveFound(SI114X_ADDR, "SI1145"); + } +} + +void Si1145Update(void) +{ + if (!Si1145Read()) { + AddLogMissed("SI1145", si1145_valid); + } +} + +#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_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#endif + } + } +} + + + + + +bool Xsns24(uint8_t function) +{ + if (!I2cEnabled(XI2C_19)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Si1145Detect(); + } + else if (si1145_type) { + 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 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" +#ifdef USE_I2C +#ifdef USE_LM75AD +# 31 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" +#define XSNS_26 26 +#define XI2C_20 20 + +#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 + +bool lm75ad_type = false; +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) +{ + for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { + lm75ad_address = lm75ad_addresses[i]; + if (I2cActive(lm75ad_address)) { + continue; } + if (!I2cSetDevice(lm75ad_address)) { + break; + } + uint16_t buffer; + if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { + if (buffer == 0x4B00) { + lm75ad_type = true; + I2cSetActiveFound(lm75ad_address, "LM75AD"); + 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) +{ + float t = LM75ADGetTemp(); + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "LM75AD", 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) +{ + if (!I2cEnabled(XI2C_20)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + LM75ADDetect(); + } + else if (lm75ad_type) { + switch (function) { + case FUNC_JSON_APPEND: + LM75ADShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LM75ADShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +# 28 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +#ifdef USE_I2C +#ifdef USE_APDS9960 +# 52 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +#define XSNS_27 27 +#define XI2C_21 21 + + +#define APDS9960_I2C_ADDR 0x39 + +#define APDS9960_CHIPID_1 0xAB +#define APDS9960_CHIPID_2 0x9C +#define APDS9960_CHIPID_3 0xA8 + +#define APDS9930_CHIPID_1 0x12 +#define APDS9930_CHIPID_2 0x39 + +#define APDS9960_MODE_GESTURE 0 +#define APDS9960_MODE_COLOR 1 + + +#define GESTURE_THRESHOLD_OUT 10 +#define GESTURE_SENSITIVITY_1 50 +#define GESTURE_SENSITIVITY_2 20 + +#define APDS9960_LONG_RECOVERY 50 +#define APDS9960_MAX_GESTURE_CYCLES 50 + + + + + +const char APDS9960_TAG[] PROGMEM = "APDS9960"; + +#ifdef USE_WEBSERVER + +#ifdef USE_APDS9960_GESTURE +const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}"; +#endif + +#ifdef USE_APDS9960_COLOR +const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}"; +const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}"; +const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}"; +const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}"; +#endif + +#ifdef USE_APDS9960_PROXIMITY +const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; +#endif + +#endif +# 108 "/workspace/Tasmota/tasmota/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 APDS9960_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 APDS9960_ERROR 0xFF + +#ifdef USE_APDS9960_GESTURE + + +const char GESTURE_UP[] PROGMEM = "Up"; +const char GESTURE_DOWN[] PROGMEM = "Down"; +const char GESTURE_LEFT[] PROGMEM = "Left"; +const char GESTURE_RIGHT[] PROGMEM = "Right"; +const char GESTURE_LONG[] PROGMEM = "Long"; +const char GESTURE_NONE[] PROGMEM = "None"; + +enum { + DIR_NONE, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN, + DIR_NEAR, + DIR_FAR, + DIR_ALL +}; +# 291 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +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_t; + +typedef struct gesture_type { + int16_t ud_delta_ = 0; + int16_t lr_delta_ = 0; + int16_t ud_count_ = 0; + int16_t lr_count_ = 0; + int16_t state_ = 0; + int16_t motion_ = DIR_NONE; +} gesture_t; + +#endif + +#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) +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_t; +#endif + + + + + +#ifdef USE_APDS9960_GESTURE +gesture_data_t gesture_data; +gesture_t gesture; +char currentGesture[6]; +#endif + +#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) +color_data_t color_data; +#endif + +volatile uint8_t recovery_loop_counter = 0; +bool APDS9960_overload = false; +uint8_t APDS9960_aTime = DEFAULT_ATIME; +uint8_t APDS9960_type = 0; +uint8_t gesture_mode = 1; + + + + + +#ifdef USE_APDS9960_COLOR + + + + + +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; +} +#endif +# 393 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getProxIntLowThresh(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); + + return val; +} + + + + + + +inline 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; +} + + + + + + +inline void setProxIntHighThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); +} +# 445 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getLEDDrive(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + val = (val >> 6) & 0b00000011; + + return val; +} +# 468 "/workspace/Tasmota/tasmota/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); +} +# 495 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getProximityGain(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + val = (val >> 2) & 0b00000011; + + return val; +} +# 518 "/workspace/Tasmota/tasmota/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); +} +# 545 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getAmbientLightGain() { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + val &= 0b00000011; + + return val; +} +# 568 "/workspace/Tasmota/tasmota/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); +} +# 594 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getLEDBoost(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2); + + + val = (val >> 4) & 0b00000011; + + return val; +} +# 617 "/workspace/Tasmota/tasmota/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); +} +# 683 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getProxPhotoMask(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); + + + val &= 0b00001111; + + return val; +} +# 707 "/workspace/Tasmota/tasmota/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); +} + +#ifdef USE_APDS9960_GESTURE + + + + + + +uint8_t getGestureEnterThresh(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH); + + return val; +} + + + + + + +inline 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; +} + + + + + + +inline void setGestureExitThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold); +} +# 781 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getGestureGain(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + + val = (val >> 5) & 0b00000011; + + return val; +} +# 804 "/workspace/Tasmota/tasmota/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); +} +# 831 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getGestureLEDDrive(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + + val = (val >> 3) & 0b00000011; + + return val; +} +# 854 "/workspace/Tasmota/tasmota/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); +} +# 885 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getGestureWaitTime(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + + val &= 0b00000111; + + return val; +} +# 912 "/workspace/Tasmota/tasmota/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); +} + +#endif + + + + + + +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); +} + + + + + + +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) { + setMode(ALL, OFF); + + + 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); + + +#ifdef USE_APDS9960_GESTURE + 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); +#endif + + disablePower(); + + return true; +} +# 1278 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +inline 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 <= 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(OFF); + enablePower(); + setMode(AMBIENT_LIGHT, ON); +} + + + + + +void disableLightSensor(void) { + setAmbientLightIntEnable(OFF); + setMode(AMBIENT_LIGHT, OFF); +} + + + + + + +void enableProximitySensor(void) { + + setProximityGain(DEFAULT_PGAIN); + setLEDDrive(DEFAULT_LDRIVE); + setProximityIntEnable(OFF); + enablePower(); + setMode(PROXIMITY, ON); +} + + + + + +void disableProximitySensor(void) { + setProximityIntEnable(OFF); + setMode(PROXIMITY, OFF); +} + +#ifdef USE_APDS9960_GESTURE + + + + + +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(OFF); + setGestureMode(ON); + enablePower(); + setMode(WAIT, ON); + setMode(PROXIMITY, ON); + setMode(GESTURE, ON); +} + + + + + +void disableGestureSensor(void) { + resetGestureParameters(); + setGestureIntEnable(OFF); + setGestureMode(OFF); + setMode(GESTURE, OFF); +} + + + + + + +bool isGestureAvailable(void) { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + + + val &= APDS9960_GVALID; + + + return (val == 1); +} + + + + + + +int16_t readGesture(void) { + uint8_t fifo_level = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + int16_t motion; + uint16_t i; + uint8_t gesture_loop_counter = 0; + int8_t bytes_read = 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); + +#ifdef USE_DEBUG_DRIVER + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: FIFO Level : %d"), fifo_level); +#endif + + + if (fifo_level > 0) { + bytes_read = (fifo_level * 4); + + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_GFIFO_U, (uint8_t*)fifo_data, bytes_read)) { + return APDS9960_ERROR; + } + +#ifdef USE_DEBUG_DRIVER + char output[(bytes_read * 2) + 1]; + char *ptr = &output[0]; + + for ( i = 0; i < bytes_read; i++ ) { + ptr += sprintf(ptr, "%02X", fifo_data[i]); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: FIFO Dump : %s"), output); +#endif + + + 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; + } + } +} + +#endif + + + + + +inline void enablePower(void) { + setMode(POWER, ON); +} + + + + + +inline void disablePower(void) { + setMode(POWER, OFF); +} + + + + + + +#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) + + + +inline void readAllColorAndProximityData(void) { + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) { + + + } +} + +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); +} +#endif + + + + + +#ifdef USE_APDS9960_GESTURE + + + + +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, GESTURE_UP); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_UP); + break; + case DIR_DOWN: + AddLog_P(LOG_LEVEL_DEBUG, GESTURE_DOWN); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_DOWN); + break; + case DIR_LEFT: + AddLog_P(LOG_LEVEL_DEBUG, GESTURE_LEFT); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_LEFT); + break; + case DIR_RIGHT: + AddLog_P(LOG_LEVEL_DEBUG, GESTURE_RIGHT); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_RIGHT); + break; + default: + if (APDS9960_overload) { + AddLog_P(LOG_LEVEL_DEBUG, GESTURE_LONG); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_LONG); + } else { + AddLog_P(LOG_LEVEL_DEBUG, GESTURE_NONE); + snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_NONE); + } + break; + } + MqttPublishSensor(); + } + currentGesture[0] = '\0'; +} + +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; + } + } + } +} + +#endif + +void APDS9960_detect(void) { + if (APDS9960_type || I2cActive(APDS9960_I2C_ADDR)) { return; } + + APDS9960_type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); + +#ifdef USE_DEBUG_DRIVER + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: %s Chip %X"), APDS9960_TAG, APDS9960_type); +#endif + + if (APDS9960_type == APDS9960_CHIPID_1 || APDS9960_type == APDS9960_CHIPID_2 || APDS9960_type == APDS9960_CHIPID_3) { + if (APDS9960_init()) { + I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960_TAG); + + enableProximitySensor(); + +#if defined(USE_APDS9960_GESTURE) && USE_APDS9960_STARTMODE == APDS9960_MODE_GESTURE + gesture_mode = 1; + enableGestureSensor(); +#endif + +#if ( defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) ) && USE_APDS9960_STARTMODE == APDS9960_MODE_COLOR + gesture_mode = 0; + enableLightSensor(); + APDS9960_overload = false; +#endif + } else { + APDS9960_type = 0; + } + } else { + APDS9960_type = 0; + } + +#ifdef USE_APDS9960_GESTURE + currentGesture[0] = '\0'; +#endif +} + + + + + +void APDS9960_show(bool json) { + if (!APDS9960_type) { return; } + + if (!gesture_mode && !APDS9960_overload) { + +#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) + uint16_t ambient; + + readAllColorAndProximityData(); + ambient = color_data.a/4; + + + + + +#ifdef USE_APDS9960_COLOR + calculateColorTemperature(); +#endif + if (json) { +#if defined(USE_APDS9960_COLOR) && defined(USE_APDS9960_PROXIMITY) + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u,\"Proximity\":%u}"), + APDS9960_TAG, + color_data.r, + color_data.g, + color_data.b, + ambient, + color_data.cct, + color_data.p); +#else + +#ifdef USE_APDS9960_COLOR + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u}"), + APDS9960_TAG, + color_data.r, + color_data.g, + color_data.b, + ambient, + color_data.cct); +#endif + +#ifdef USE_APDS9960_PROXIMITY + ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), + APDS9960_TAG, + color_data.p); +#endif + +#endif +#ifdef USE_WEBSERVER + } else { + +#ifdef USE_APDS9960_COLOR + WSContentSend_PD(HTTP_SNS_COLOR_RED, APDS9960_TAG, color_data.r); + WSContentSend_PD(HTTP_SNS_COLOR_GREEN, APDS9960_TAG, color_data.g); + WSContentSend_PD(HTTP_SNS_COLOR_BLUE, APDS9960_TAG, color_data.b); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, APDS9960_TAG, ambient); + WSContentSend_PD(HTTP_SNS_CCT, APDS9960_TAG, color_data.cct); +#endif + +#ifdef USE_APDS9960_PROXIMITY + WSContentSend_PD(HTTP_SNS_PROXIMITY, APDS9960_TAG, color_data.p); +#endif + +#endif + } +#endif + +#ifdef USE_APDS9960_GESTURE + } else { + if (currentGesture[0] != '\0') { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960_TAG, currentGesture); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GESTURE, APDS9960_TAG, currentGesture); +#endif + currentGesture[0] = '\0'; + } + } +#endif + + } +} +# 1947 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" +bool APDS9960CommandSensor(void) { + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: +#ifdef USE_APDS9960_GESTURE + disableGestureSensor(); +#endif + gesture_mode = 0; + enableLightSensor(); + APDS9960_overload = false; + break; +#ifdef USE_APDS9960_GESTURE + case 1: + if (APDS9960_type) { + setGestureGain(DEFAULT_GGAIN); + setProximityGain(DEFAULT_PGAIN); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + case 2: + if (APDS9960_type) { + setGestureGain(GGAIN_2X); + setProximityGain(PGAIN_2X); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; +#endif + 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) { + if (!I2cEnabled(XI2C_21)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + APDS9960_detect(); + } else if (APDS9960_type) { + switch (function) { +#ifdef USE_APDS9960_GESTURE + case FUNC_EVERY_50_MSECOND: + APDS9960_loop(); + break; +#endif + 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 "/workspace/Tasmota/tasmota/xsns_28_tm1638.ino" +# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB)) { + 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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xsns_28_tm1638.ino" + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#ifdef USE_I2C +#ifdef USE_MCP230xx +# 31 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#define XSNS_29 29 +#define XI2C_22 22 + + + + + +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_oldoutpincount = 0; +#ifdef USE_MCP230xx_OUTPUT +uint8_t mcp230xx_outpinmapping[16]; +#endif +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 < mcp230xx_type; mcp230xx_port++) { + uint8_t reg_gppu = 0; + uint8_t reg_gpinten = 0; + uint8_t reg_iodir = 0xFF; +#ifdef USE_MCP230xx_OUTPUT + uint8_t reg_portpins = 0x00; +#endif + for (uint32_t idx = 0; idx < 8; idx++) { + switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { + case 0 ... 1: + reg_iodir |= (1 << idx); + break; + case 2 ... 4: + reg_iodir |= (1 << idx); + reg_gpinten |= (1 << idx); + int_en = 1; + break; +#ifdef USE_MCP230xx_OUTPUT + case 5 ... 6: + reg_iodir &= ~(1 << idx); + if (Settings.flag.save_state) { + reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); + } else { + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_portpins |= (1 << idx); + } + } + break; +#endif + default: + break; + } +#ifdef USE_MCP230xx_OUTPUT + if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { + reg_gppu |= (1 << idx); + } +#else + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_gppu |= (1 << idx); + } +#endif + } + 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(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); +#endif + } + devices_present -= mcp230xx_oldoutpincount; + mcp230xx_oldoutpincount = 0; + for (uint32_t idx=0;idx= 5) { + mcp230xx_outpinmapping[mcp230xx_oldoutpincount] = idx; + mcp230xx_oldoutpincount++; + } + int_millis[idx]=millis(); + } + devices_present += mcp230xx_oldoutpincount; + mcp230xx_int_en = int_en; + MCP230xx_CheckForIntCounter(); + MCP230xx_CheckForIntRetainer(); +} + +void MCP230xx_Detect(void) +{ + if (I2cActive(USE_MCP230xx_ADDR)) { return; } + + uint8_t buffer; + + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IOCON, 0x80); + if (I2cValidRead8(&buffer, USE_MCP230xx_ADDR, MCP230xx_IOCON)) { + if (0x00 == buffer) { + mcp230xx_type = 1; + I2cSetActiveFound(USE_MCP230xx_ADDR, "MCP23008"); + mcp230xx_pincount = 8; + MCP230xx_ApplySettings(); + } else { + if (0x80 == buffer) { + mcp230xx_type = 2; + I2cSetActiveFound(USE_MCP230xx_ADDR, "MCP23017"); + mcp230xx_pincount = 16; + + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IOCON, 0x00); + + MCP230xx_GPINTEN = 0x04; + MCP230xx_GPPU = 0x0C; + MCP230xx_INTF = 0x0E; + MCP230xx_INTCAP = 0x10; + MCP230xx_GPIO = 0x12; + MCP230xx_ApplySettings(); + } + } + } +} + +void MCP230xx_CheckForInterrupt(void) { + uint8_t intf; + uint8_t mcp230xx_intcap = 0; + uint8_t report_int; + for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { + if (I2cValidRead8(&intf,USE_MCP230xx_ADDR,MCP230xx_INTF+mcp230xx_port)) { + if (intf > 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 (Settings.flag3.hass_tele_on_power) { + MqttPublishSensor(); + } + } + 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 (json) { + 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); + uint8_t gpiob = 0; + if (2 == mcp230xx_type) { + gpiob = MCP230xx_readGPIO(1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpiob>>0)&1, (gpiob>>1)&1, (gpiob>>2)&1, (gpiob>>3)&1, (gpiob>>4)&1, (gpiob>>5)&1, (gpiob>>6)&1, (gpiob>>7)&1); + } + +#ifdef USE_MCP230xx_OUTPUT + uint8_t outputcount = 0; + for (uint32_t pinx = 0; pinx < mcp230xx_pincount; pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { outputcount++; } + } + if (outputcount) { + uint16_t gpiototal = ((uint16_t)gpiob << 8) | gpio; + ResponseAppend_P(PSTR(",\"MCP230_OUT\":{")); + char stt[7]; + 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}")); + } +#endif + 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 (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; + uint8_t relay_no = 0; + for (relay_no = 0; relay_no < mcp230xx_pincount ; relay_no ++) { + if ( mcp230xx_outpinmapping[relay_no] == pin) break; + } + relay_no = devices_present - mcp230xx_oldoutpincount + relay_no +1; + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { + ExecuteCommandPower(relay_no, 1, SRC_IGNORE); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { + ExecuteCommandPower(relay_no, 0, SRC_IGNORE); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { + ExecuteCommandPower(relay_no, 2, SRC_IGNORE); + 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) && (paramcount > 2)) { +#else + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 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 +# 771 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" +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}}")); + MqttPublishTeleSensor(); + 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); + MqttPublishTeleSensor(); +} + +#ifdef USE_MCP230xx_OUTPUT +void MCP230xx_SwitchRelay() { + for (uint32_t i = devices_present - mcp230xx_oldoutpincount; i < devices_present; i++) { + uint8_t pin = mcp230xx_outpinmapping[i - (devices_present - mcp230xx_oldoutpincount)]; + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; + uint8_t relay_state = bitRead(XdrvMailbox.index, i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MCP: relay %d pin_no %d state %d"), i,pin, relay_state); + switch (relay_state) { + case 1: + MCP230xx_SetOutPin(pin,abs(pincmd-1)); + break; + case 0: + MCP230xx_SetOutPin(pin,pincmd); + break; + } + } +} +#endif + + + + + +bool Xsns29(uint8_t function) +{ + if (!I2cEnabled(XI2C_22)) { return false; } + + bool result = false; + + if (FUNC_PRE_INIT == function) { + MCP230xx_Detect(); + } + else if (mcp230xx_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (mcp230xx_int_en) { + mcp230xx_int_prio_counter++; + if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { + MCP230xx_CheckForInterrupt(); + mcp230xx_int_prio_counter=0; + } + } + break; + case FUNC_EVERY_SECOND: + 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(); + } + + + + + + } + break; +#ifdef USE_MCP230xx_OUTPUT + case FUNC_SET_POWER: + MCP230xx_SwitchRelay(); + break; +#endif + 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 + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" +# 46 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" +#ifdef USE_I2C +#ifdef USE_MPR121 + + + + + +#define XSNS_30 30 +#define XI2C_23 23 + + + + + + + +#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) +# 195 "/workspace/Tasmota/tasmota/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 }; +}; + +bool mpr21_found = false; +# 217 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" +void Mpr121Init(struct mpr121 *pS, bool initial) +{ + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + if (initial && I2cActive(pS->i2c_addr[i])) { continue; } + + + 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]) { + + + mpr21_found = true; + char device_name[16]; + snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); + I2cSetActiveFound(pS->i2c_addr[i], device_name); + + + 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")); + } +} +# 326 "/workspace/Tasmota/tasmota/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, false); + 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, false); + 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(); + } + } + } +} +# 410 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" +bool Xsns30(uint8_t function) +{ + if (!I2cEnabled(XI2C_23)) { return false; } + + bool result = false; + + + static struct mpr121 mpr121; + + if (FUNC_INIT == function) { + + Mpr121Init(&mpr121, true); + } + else if (mpr21_found) { + + switch (function) { + + + 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 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" +#ifdef USE_I2C +#ifdef USE_CCS811 +# 30 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" +#define XSNS_31 31 +#define XI2C_24 24 + +#define EVERYNSECONDS 5 + +#include "Adafruit_CCS811.h" + +Adafruit_CCS811 ccs; +uint8_t CCS811_ready = 0; +uint8_t CCS811_type = 0;; +uint16_t eCO2; +uint16_t TVOC; +uint8_t tcnt = 0; +uint8_t ecnt = 0; + + + +void CCS811Detect(void) +{ + if (I2cActive(CCS811_ADDRESS)) { return; } + + if (!ccs.begin(CCS811_ADDRESS)) { + CCS811_type = 1; + I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); + } +} + +void CCS811Update(void) +{ + tcnt++; + if (tcnt >= EVERYNSECONDS) { + tcnt = 0; + CCS811_ready = 0; + if (ccs.available()) { + if (!ccs.readData()){ + TVOC = ccs.getTVOC(); + eCO2 = ccs.geteCO2(); + CCS811_ready = 1; + if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { + ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature_celsius); + } + 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) +{ + if (!I2cEnabled(XI2C_24)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + CCS811Detect(); + } + else if (CCS811_type) { + 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 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" +#ifdef USE_I2C +#ifdef USE_MPU6050 +# 30 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" +#define XSNS_32 32 +#define XI2C_25 25 + +#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]; + float yawPitchRoll[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); + mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &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(); +} +# 119 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" +void MPU_6050Detect(void) +{ + for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) + { + MPU_6050_address = MPU_6050_addresses[i]; + if (!I2cSetDevice(MPU_6050_address)) { break; } + 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) { + I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); + } +} + +#define D_YAW "Yaw" +#define D_PITCH "Pitch" +#define D_ROLL "Roll" + +#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}"; +#ifdef USE_MPU6050_DMP +const char HTTP_SNS_YPR[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; +#endif +#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" +#define D_JSON_YAW "Yaw" +#define D_JSON_PITCH "Pitch" +#define D_JSON_ROLL "Roll" + +void MPU_6050Show(bool json) +{ + MPU_6050PerformReading(); + + float tempConv = ConvertTemp(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); +#ifdef USE_MPU6050_DMP + char axis_yaw[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); + char axis_pitch[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); + char axis_roll[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); +#endif + + 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); +#ifdef USE_MPU6050_DMP + char json_ypr_y[25]; + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); + char json_ypr_p[25]; + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); + char json_ypr_r[25]; + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%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, + json_ypr_y, json_ypr_p, json_ypr_r); +#else + 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); +#endif +#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); +#ifdef USE_MPU6050_DMP + WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); +#endif +#endif + } +} + + + + + +bool Xsns32(uint8_t function) +{ + if (!I2cEnabled(XI2C_25)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MPU_6050Detect(); + } + else if (MPU_6050_found) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" +#ifdef USE_I2C +#ifdef USE_DS3231 +# 35 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" +#define XSNS_33 33 +#define XI2C_26 26 + + +#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) +{ + if (I2cActive(USE_RTC_ADDR)) { return; } + + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { + I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); + DS3231chipDetected = true; + } +} + + + + +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)); +} + +void DS3231EverySecond(void) +{ + TIME_T tmpTime; + if (!ds3231ReadStatus && 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"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } + else if (!ds3231WriteStatus && 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"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + SetDS3231Time (Rtc.utc_time); + ds3231WriteStatus = true; + } +} + + + + + +bool Xsns33(uint8_t function) +{ + if (!I2cEnabled(XI2C_26)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + DS3231Detect(); + } + else if (DS3231chipDetected) { + switch (function) { + case FUNC_EVERY_SECOND: + DS3231EverySecond(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_34_hx711.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_34_hx711.ino" +#ifdef USE_HX711 +# 35 "/workspace/Tasmota/tasmota/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" +#define D_JSON_WEIGHT_RAW "WeightRaw" +#define D_JSON_WEIGHT_DELTA "WeightDelta" + +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 raw = 0; + long last_weight = 0; + long sum_weight = 0; + long sum_raw = 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; + uint16_t weight_delta = 4; +} 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(void) +{ + 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")); } +} + +void SetWeightDelta() +{ + + if (Settings.weight_change == 0) { + Hx.weight_delta = 4; + return; + } + + + if (Settings.weight_change > 100) { + Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; + return; + } + + + Hx.weight_delta = Settings.weight_change - 1; +} +# 192 "/workspace/Tasmota/tasmota/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; + case 9: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + SetWeightDelta(); + } + 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,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), + Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, + item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); + } + + return serviced; +} + + + +long HxWeight(void) +{ + return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; +} + +void HxInit(void) +{ + Hx.type = 0; + if (PinUsed(GPIO_HX711_DAT) && PinUsed(GPIO_HX711_SCK)) { + 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); + + SetWeightDelta(); + + 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) +{ + long raw = HxRead(); + Hx.sum_raw += raw; + Hx.sum_weight += raw; + + Hx.sample_count++; + if (HX_SAMPLES == Hx.sample_count) { + long average = Hx.sum_weight / Hx.sample_count; + long raw_average = Hx.sum_raw / Hx.sample_count; + long value = average - Hx.offset; + Hx.weight = value / Hx.scale; + Hx.raw = raw_average / 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) > Hx.weight_delta) { + 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(); + MqttPublishTeleSensor(); + Hx.weight_changed = false; + } + } + } + + Hx.sum_weight = 0; + Hx.sum_raw = 0; + Hx.sample_count = 0; + } +} + +void HxSaveBeforeRestart(void) +{ + 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, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); +#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(PSTR("/" WEB_HANDLE_HX711), HandleHxAction); + break; +#endif +#endif + case FUNC_INIT: + HxInit(); + break; + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) +# 51 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" +#define XSNS_35 35 + +#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) +#undef USE_TX20_WIND_SENSOR +#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** +#endif + + +#define TX2X_BIT_TIME 1220 +#define TX2X_WEIGHT_AVG_SAMPLE 150 +#define TX2X_TIMEOUT 10 +#define TX23_READ_INTERVAL 4 + + + +extern "C" { +#include "gpio.h" +} + +#ifdef USE_TX20_WIND_SENSOR +#undef D_TX2x_NAME +#define D_TX2x_NAME "TX20" +#else +#undef D_TX2x_NAME +#define D_TX2x_NAME "TX23" +#endif + +#ifdef USE_WEBSERVER +#define D_TX20_WIND_AVG "∅" +#define D_TX20_WIND_ANGLE "∠" +#define D_TX20_WIND_DEGREE "°" +const char HTTP_SNS_TX2X[] PROGMEM = + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}" +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED " " D_TX20_WIND_AVG "{m}%s %s{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}" +#endif + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s" D_TX20_WIND_DEGREE "{e}" +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_AVG "{m}%s %s" D_TX20_WIND_DEGREE "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_ANGLE "{m}%s" D_TX20_WIND_DEGREE " (%s,%s)" D_TX20_WIND_DEGREE; +#endif + ; +#endif + + +float const tx2x_f_pi = 3.1415926535897932384626433; +float const tx2x_f_halfpi = tx2x_f_pi / 2.0; +float const tx2x_f_pi180 = tx2x_f_pi / 180.0; + +#define TX2X_DIRECTIONS_MAXSIZE 3 +const char kTx2xDirections[] 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; + +int32_t tx2x_wind_speed = 0; +int32_t tx2x_wind_direction = 0; + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS +int32_t tx2x_wind_speed_min = 0xfff; +int32_t tx2x_wind_speed_max = 0; +float tx2x_wind_speed_avg = 0; +float tx2x_wind_direction_avg_x = 0; +float tx2x_wind_direction_avg_y = 0; +float tx2x_wind_direction_avg = 0; +int32_t tx2x_wind_direction_min = 0; +int32_t tx2x_wind_direction_max = 0; + +uint32_t tx2x_count = 0; +uint32_t tx2x_avg_samples; +uint32_t tx2x_last_uptime = 0; +bool tx2x_valuesread = false; +#endif + +#ifdef DEBUG_TASMOTA_SENSOR +uint32_t tx2x_sa = 0; +uint32_t tx2x_sb = 0; +uint32_t tx2x_sc = 0; +uint32_t tx2x_sd = 0; +uint32_t tx2x_se = 0; +uint32_t tx2x_sf = 0; +#endif +uint32_t tx2x_last_available = 0; + +#ifdef USE_TX23_WIND_SENSOR +uint32_t tx23_stage = 0; +#endif + +void ICACHE_RAM_ATTR TX2xStartRead(void) +{ +# 180 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" +#ifdef USE_TX23_WIND_SENSOR + if (0!=tx23_stage) + { + if ((2==tx23_stage) || (3==tx23_stage)) + { +#endif +#ifdef DEBUG_TASMOTA_SENSOR + tx2x_sa = 0; + tx2x_sb = 0; + tx2x_sc = 0; + tx2x_sd = 0; + tx2x_se = 0; + tx2x_sf = 0; +#else + uint32_t tx2x_sa = 0; + uint32_t tx2x_sb = 0; + uint32_t tx2x_sc = 0; + uint32_t tx2x_sd = 0; + uint32_t tx2x_se = 0; + uint32_t tx2x_sf = 0; +#endif + + delayMicroseconds(TX2X_BIT_TIME / 2); + + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint32_t dpin = (digitalRead(Pin(GPIO_TX2X_TXD_BLACK))); +#ifdef USE_TX23_WIND_SENSOR + dpin ^= 1; +#endif + if (bitcount > 41 - 5) { + + tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + + tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + + tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + + tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + + tx2x_se = tx2x_se >> 1 | (dpin << 3); + } else { + + tx2x_sf = tx2x_sf >> 1 | (dpin << 11); + } + delayMicroseconds(TX2X_BIT_TIME); + } + + uint32_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); + chk &= 0xf; + + + ; +#ifdef USE_TX23_WIND_SENSOR + if ((chk == tx2x_sd) && (0x1b==tx2x_sa) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { +#else + if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { +#endif + tx2x_last_available = uptime; + + tx2x_wind_speed = tx2x_sc; + tx2x_wind_direction = tx2x_sb; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + if (!tx2x_valuesread) { + tx2x_wind_direction_min = tx2x_wind_direction; + tx2x_wind_direction_max = tx2x_wind_direction; + tx2x_valuesread = true; + } +#endif + } + +#ifdef USE_TX23_WIND_SENSOR + } + tx23_stage++; + } +#endif + + + + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << Pin(GPIO_TX2X_TXD_BLACK)); +} + +bool Tx2xAvailable(void) +{ + return ((uptime - tx2x_last_available) < TX2X_TIMEOUT); +} + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS +float atan2f(float a, float b) +{ + float atan2val; + if (b > 0) { + atan2val = atanf(a/b); + } else if ((b < 0) && (a >= 0)) { + atan2val = atanf(a/b) + tx2x_f_pi; + } else if ((b < 0) && (a < 0)) { + atan2val = atanf(a/b) - tx2x_f_pi; + } else if ((b == 0) && (a > 0)) { + atan2val = tx2x_f_halfpi; + } else if ((b == 0) && (a < 0)) { + atan2val = 0 - (tx2x_f_halfpi); + } else if ((b == 0) && (a == 0)) { + atan2val = 1000; + } + return atan2val; +} + +void Tx2xCheckSampleCount(void) +{ + uint32_t tx2x_prev_avg_samples = tx2x_avg_samples; + if (Settings.tele_period) { + + tx2x_avg_samples = Settings.tele_period; + } else { + + tx2x_avg_samples = TX2X_WEIGHT_AVG_SAMPLE; + } + if (tx2x_prev_avg_samples != tx2x_avg_samples) { + tx2x_wind_speed_avg = tx2x_wind_speed; + tx2x_count = 0; + } +} + +void Tx2xResetStat(void) +{ + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": reset statistics")); + tx2x_last_uptime = uptime; + Tx2xResetStatData(); +} + +void Tx2xResetStatData(void) +{ + tx2x_wind_speed_min = tx2x_wind_speed; + tx2x_wind_speed_max = tx2x_wind_speed; + + tx2x_wind_direction_min = tx2x_wind_direction; + tx2x_wind_direction_max = tx2x_wind_direction; +} +#endif + +void Tx2xRead(void) +{ +#ifdef USE_TX23_WIND_SENSOR + + + + + + + + if ((uptime % TX23_READ_INTERVAL)==0) { + + + tx23_stage = 0; + pinMode(Pin(GPIO_TX2X_TXD_BLACK), OUTPUT); + digitalWrite(Pin(GPIO_TX2X_TXD_BLACK), LOW); + } else if ((uptime % TX23_READ_INTERVAL)==1) { + + + tx23_stage = 1; + pinMode(Pin(GPIO_TX2X_TXD_BLACK), INPUT_PULLUP); + } +#endif + if (Tx2xAvailable()) { +#ifdef DEBUG_TASMOTA_SENSOR + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": sa=0x%02lx sb=%ld (0x%02lx), sc=%ld (0x%03lx), sd=0x%02lx, se=%ld, sf=%ld"), tx2x_sa,tx2x_sb,tx2x_sb,tx2x_sc,tx2x_sc,tx2x_sd,tx2x_se,tx2x_sf); +#endif +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + if (tx2x_wind_speed < tx2x_wind_speed_min) { + tx2x_wind_speed_min = tx2x_wind_speed; + } + if (tx2x_wind_speed > tx2x_wind_speed_max) { + tx2x_wind_speed_max = tx2x_wind_speed; + } + + + + + if (tx2x_count <= tx2x_avg_samples) { + tx2x_count++; + } + tx2x_wind_speed_avg -= tx2x_wind_speed_avg / tx2x_count; + tx2x_wind_speed_avg += float(tx2x_wind_speed) / tx2x_count; + + tx2x_wind_direction_avg_x -= tx2x_wind_direction_avg_x / tx2x_count; + tx2x_wind_direction_avg_x += cosf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; + tx2x_wind_direction_avg_y -= tx2x_wind_direction_avg_y / tx2x_count; + tx2x_wind_direction_avg_y += sinf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; + tx2x_wind_direction_avg = atan2f(tx2x_wind_direction_avg_y, tx2x_wind_direction_avg_x) * 180.0f / tx2x_f_pi; + if (tx2x_wind_direction_avg<0.0) { + tx2x_wind_direction_avg += 360.0; + } + if (tx2x_wind_direction_avg>360.0) { + tx2x_wind_direction_avg -= 360.0; + } + + int32_t tx2x_wind_direction_avg_int = int((tx2x_wind_direction_avg/22.5)+0.5) % 16; + + + if (tx2x_wind_direction > tx2x_wind_direction_avg_int) { + + if ((tx2x_wind_direction-tx2x_wind_direction_avg_int)>8) { + + if ((tx2x_wind_direction - 16) < tx2x_wind_direction_min) { + + tx2x_wind_direction_min = tx2x_wind_direction - 16; + } + } else { + + if (tx2x_wind_direction > tx2x_wind_direction_max) { + + tx2x_wind_direction_max = tx2x_wind_direction; + } + } + } else { + + if ((tx2x_wind_direction_avg_int-tx2x_wind_direction)>8) { + + if ((tx2x_wind_direction + 16) > tx2x_wind_direction_max) { + + tx2x_wind_direction_max = tx2x_wind_direction + 16; + } + } else { + + if (tx2x_wind_direction < tx2x_wind_direction_min) { + + tx2x_wind_direction_min = tx2x_wind_direction; + } + } + } + +#ifdef DEBUG_TASMOTA_SENSOR + char diravg[FLOATSZ]; + dtostrfd(tx2x_wind_direction_avg, 1, diravg); + char cosx[FLOATSZ]; + dtostrfd(tx2x_wind_direction_avg_x, 1, cosx); + char siny[FLOATSZ]; + dtostrfd(tx2x_wind_direction_avg_y, 1, siny); + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": dir stat - counter=%ld, actint=%ld, avgint=%ld, avg=%s (cosx=%s, siny=%s), min %d, max %d"), + (uptime-tx2x_last_uptime), + tx2x_wind_direction, + tx2x_wind_direction_avg_int, + diravg, + cosx, + siny, + tx2x_wind_direction_min, + tx2x_wind_direction_max + ); +#endif +#endif + } else { + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": not available")); + tx2x_wind_speed = 0; + tx2x_wind_direction = 0; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + tx2x_wind_speed_avg = 0; + tx2x_wind_direction_avg = 0; + Tx2xResetStatData(); +#endif + } + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + Tx2xCheckSampleCount(); + if (0==Settings.tele_period && (uptime-tx2x_last_uptime)>=tx2x_avg_samples) { + Tx2xResetStat(); + } +#endif +} + +void Tx2xInit(void) +{ + if (!Settings.flag2.speed_conversion) { + Settings.flag2.speed_conversion = 2; + } +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + tx2x_valuesread = false; + Tx2xResetStat(); + Tx2xCheckSampleCount(); +#endif +#ifdef USE_TX23_WIND_SENSOR + tx23_stage = 0; + pinMode(Pin(GPIO_TX2X_TXD_BLACK), OUTPUT); + digitalWrite(Pin(GPIO_TX2X_TXD_BLACK), LOW); +#else + pinMode(Pin(GPIO_TX2X_TXD_BLACK), INPUT); +#endif + attachInterrupt(Pin(GPIO_TX2X_TXD_BLACK), TX2xStartRead, RISING); +} + +int32_t Tx2xNormalize(int32_t value) +{ + while (value>15) { + value -= 16; + } + while (value<0) { + value += 16; + } + return value; +} + +void Tx2xShow(bool json) +{ + if (!Tx2xAvailable()) { return; } + + char wind_speed_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed)/10, 1, wind_speed_string); + char wind_direction_string[FLOATSZ]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_string); + char wind_direction_cardinal_string[TX2X_DIRECTIONS_MAXSIZE+1]; + GetTextIndexed(wind_direction_cardinal_string, sizeof(wind_direction_cardinal_string), tx2x_wind_direction, kTx2xDirections); +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + char wind_speed_min_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_min)/10, 1, wind_speed_min_string); + char wind_speed_max_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_max)/10, 1, wind_speed_max_string); + char wind_speed_avg_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_avg)/10, 1, wind_speed_avg_string); + char wind_direction_avg_string[FLOATSZ]; + dtostrfd(tx2x_wind_direction_avg, 1, wind_direction_avg_string); + char wind_direction_avg_cardinal_string[4]; + GetTextIndexed(wind_direction_avg_cardinal_string, sizeof(wind_direction_avg_cardinal_string), int((tx2x_wind_direction_avg/22.5f)+0.5f) % 16, kTx2xDirections); + char wind_direction_range_string[FLOATSZ]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_max-tx2x_wind_direction_min)*22.5, 1, wind_direction_range_string); + char wind_direction_min_string[FLOATSZ]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_min)*22.5, 1, wind_direction_min_string); + char wind_direction_max_string[FLOATSZ]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_max)*22.5, 1, wind_direction_max_string); +#endif + + if (json) { +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS +#ifdef USE_TX2x_LEGACY_JSON + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), + wind_speed_string, + wind_speed_avg_string, + wind_speed_max_string, + wind_direction_cardinal_string, + wind_direction_string + ); +#else + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"), + wind_speed_string, + wind_speed_avg_string, + wind_speed_min_string, + wind_speed_max_string, + wind_direction_cardinal_string, + wind_direction_string, + wind_direction_avg_string, + wind_direction_avg_cardinal_string, + wind_direction_min_string, + wind_direction_max_string, + wind_direction_range_string + ); +#endif +#else +#ifdef USE_TX2x_LEGACY_JSON + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), + wind_speed_string, wind_direction_cardinal_string, wind_direction_string); +#else + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"), + wind_speed_string, wind_direction_cardinal_string, wind_direction_string); +#endif +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TX2X, + wind_speed_string, + SpeedUnit().c_str(), +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + wind_speed_avg_string, + SpeedUnit().c_str(), + wind_speed_min_string, + SpeedUnit().c_str(), + wind_speed_max_string, + SpeedUnit().c_str(), +#endif + wind_direction_cardinal_string, + wind_direction_string +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + ,wind_direction_avg_cardinal_string, + wind_direction_avg_string, + wind_direction_range_string, + wind_direction_min_string, + wind_direction_max_string +#endif + ); +#endif + } +} + + + + + +bool Xsns35(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_TX2X_TXD_BLACK)) { + switch (function) { + case FUNC_INIT: + Tx2xInit(); + break; + case FUNC_EVERY_SECOND: + Tx2xRead(); + break; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + case FUNC_AFTER_TELEPERIOD: + Tx2xResetStat(); + break; +#endif + case FUNC_JSON_APPEND: + Tx2xShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tx2xShow(false); + break; +#endif + + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" +# 22 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" +#ifdef USE_I2C +#ifdef USE_MGC3130 +# 35 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" +#define XSNS_36 36 +#define XI2C_27 27 + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +uint8_t MGC3130_xfer = 0; +uint8_t MGC3130_reset = 0; +bool MGC3130_type = false; +char MGC3130stype[] = "MGC3130"; + +#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_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MqttPublishSensor(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MqttPublishSensor(); + } + } +} + +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(); +} + +void MGC3130_detect(void) +{ + if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } + + MGC3130_xfer = Pin(GPIO_MGC3130_XFER); + MGC3130_reset = Pin(GPIO_MGC3130_RESET); + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + if (MGC3130_receiveMessage()) { + I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } +} + + + + + +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 + } +} +# 557 "/workspace/Tasmota/tasmota/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) +{ + if (!I2cEnabled(XI2C_27)) { return false; } + + bool result = false; + + if ((FUNC_INIT == function) && PinUsed(GPIO_MGC3130_XFER) && PinUsed(GPIO_MGC3130_RESET)) { + 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 "/workspace/Tasmota/tasmota/xsns_37_rfsensor.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_37_rfsensor.ino" +#ifdef USE_RF_SENSOR +# 33 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{"), sensor); + ResponseAppendTHD(temp, humi); + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s}"), voltage); + + if ((0 == tele_period) && !sensor_once) { +#ifdef USE_DOMOTICZ + DomoticzTempHumPressureSensor(temp, humi); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temp); + KnxSensor(KNX_HUMIDITY, humi); +#endif + sensor_once = true; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_THD(sensor, temp, humi); +#endif + } + } + } + } +} + +#endif + +#ifdef USE_ALECTO_V2 +# 389 "/workspace/Tasmota/tasmota/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); + float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); + + 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 "\":{")); + ResponseAppendTHD(temp, humi); + ResponseAppend_P(PSTR(",\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + + + + +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_THD(D_ALECTOV2, temp, humi); + 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 (PinUsed(GPIO_RF_SENSOR) && (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(); + } + } + ssleep = 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 "/workspace/Tasmota/tasmota/xsns_38_az7798.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_38_az7798.ino" +#ifdef USE_AZ7798 + +#define XSNS_38 38 +# 112 "/workspace/Tasmota/tasmota/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); +#ifdef USE_LIGHT + LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); +#endif + 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 (PinUsed(GPIO_AZ_RXD) && PinUsed(GPIO_AZ_TXD)) { + 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) +{ + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,"), ktype, az_co2); + ResponseAppendTHD(az_temperature, az_humidity); + ResponseJsonEnd(); +#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_THD(ktype, az_temperature, az_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 "/workspace/Tasmota/tasmota/xsns_39_max31855.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_39_max31855.ino" +#ifdef USE_MAX31855 + + + + + + + +#define XSNS_39 39 + +const char kMax31855Types[] PROGMEM = "MAX31855|MAX6675"; + +bool max31855_initialized = false; + +struct MAX31855_ResultStruct { + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void) { + if (PinUsed(GPIO_MAX31855CS) && PinUsed(GPIO_MAX31855CLK) && PinUsed(GPIO_MAX31855DO)) { + + + 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); + + max31855_initialized = true; + } +} + + + + + +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; +} + + + + + +float MAX31855_GetProbeTemperature(int32_t RawData) { + if (RawData & 0x80000000) { + RawData = (RawData >> 18) | 0xFFFFC000; + } else { + RawData >>= 18; + } + float result = (RawData * 0.25); + + return ConvertTemp(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 ConvertTemp(result); +} + + + + + +void MAX31855_GetResult(void) { + if (Settings.flag4.max6675) { + int32_t RawData = MAX31855_ShiftIn(16); + int32_t temp = (RawData >> 3) & ((1 << 12) - 1); + + + if (temp == ((1 << 12) - 1)) { return; } + + MAX31855_Result.ErrorCode = 0; + MAX31855_Result.ReferenceTemperature = NAN; + MAX31855_Result.ProbeTemperature = ConvertTemp(0.25 * temp); + } else { + 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); + } + } +} + +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); + + char sensor_name[10]; + GetTextIndexed(sensor_name, sizeof(sensor_name), Settings.flag4.max6675, kMax31855Types); + + if (Json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + sensor_name, 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 +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, probetemp, TempUnit()); +#endif + } +} + + + + + +bool Xsns39(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + MAX31855_Init(); + } + else if (max31855_initialized) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_40_pn532.ino" +# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_PN532_RXD) && PinUsed(GPIO_PN532_TXD)) { + 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 "/workspace/Tasmota/tasmota/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\", \"" D_JSON_DATA "\":\"%s\"}}"), uids, card_datas); +#else + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); +#endif + + MqttPublishTeleSensor(); + +#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; + } + } + return false; +} + +#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 "/workspace/Tasmota/tasmota/xsns_41_max44009.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_41_max44009.ino" +#ifdef USE_I2C +#ifdef USE_MAX44009 + + + + + + +#define XSNS_41 41 +#define XI2C_28 28 + +#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 buffer1; + uint8_t buffer2; + for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { + + max44009_address = max44009_addresses[i]; + if (I2cActive(max44009_address)) { continue; } + + 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()) { + I2cSetActiveFound(max44009_address, max44009_types); + max44009_found = 1; + break; + } + } + } + } +} + +void Max4409EverySecond(void) +{ + 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) +{ + if (!I2cEnabled(XI2C_28)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Max4409Detect(); + } + else if (max44009_found) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_42_scd30.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_42_scd30.ino" +#ifdef USE_I2C +#ifdef USE_SCD30 + +#define XSNS_42 42 +#define XI2C_29 29 + + + +#define SCD30_ADDRESS 0x61 + +#define SCD30_MAX_MISSED_READS 3 +#define SCD30_STATE_NO_ERROR 0 +#define SCD30_STATE_ERROR_DATA_CRC 1 +#define SCD30_STATE_ERROR_READ_MEAS 2 +#define SCD30_STATE_ERROR_SOFT_RESET 3 +#define SCD30_STATE_ERROR_I2C_RESET 4 +#define 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 = 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; + +void Scd30Detect(void) +{ + if (I2cActive(SCD30_ADDRESS)) { return; } + + scd30.begin(); + + uint8_t major = 0; + uint8_t minor = 0; + if (scd30.getFirmwareVersion(&major, &minor)) { return; } + uint16_t interval_sec; + if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } + if (scd30.beginMeasuring()) { return; } + + I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); + scd30Found = true; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); +} + + +void Scd30Update(void) +{ + scd30Loop_count++; + if (scd30Loop_count > (scd30Interval_sec - 1)) { + uint32_t error = 0; + switch (scd30ErrorState) { + case 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 = SCD30_STATE_ERROR_DATA_CRC; + scd30CrcError_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("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); +#endif + break; + + case ERROR_SCD30_CO2_ZERO: + scd30Co2Zero_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("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); +#endif + break; + + default: { + scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); +#endif + return; + } + break; + } + } + break; + + case SCD30_STATE_ERROR_DATA_CRC: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); +#endif + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + break; + + case SCD30_STATE_ERROR_READ_MEAS: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); +#endif + scd30Reset_count++; + error = scd30.softReset(); + if (error) { +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); +#endif + error >>= 8; + if (error == 4) { + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } else { + scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; + } + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + case SCD30_STATE_ERROR_SOFT_RESET: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); +#endif + i2cReset_count++; + error = scd30.clearI2CBus(); + if (error) { + scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); +#endif + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + default: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); +#endif + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } + } + + if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { + scd30IsDataValid = false; + } + } +} + + +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; + } + return 0; +} + +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; + } + return 0; +} + + + + + +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 + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), 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) +{ + if (scd30IsDataValid) + { + float t = ConvertTemp(scd30_Temp); + float h = ConvertHumidity(scd30_Humid); + + if (json) { + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,"), scd30_CO2, scd30_CO2EAvg); + ResponseAppendTHD(t, h); + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); + DomoticzTempHumPressureSensor(t, h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); + WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); + WSContentSend_THD("SCD30", t, h); +#endif + } + } +} + + + + + +bool Xsns42(byte function) +{ + if (!I2cEnabled(XI2C_29)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Scd30Detect(); + } + else if (scd30Found) { + 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 "/workspace/Tasmota/tasmota/xsns_43_hre.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_43_hre.ino" +#ifdef USE_HRE +# 49 "/workspace/Tasmota/tasmota/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 (!PinUsed(GPIO_HRE_CLOCK) || !PinUsed(GPIO_HRE_DATA)) { 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 "/workspace/Tasmota/tasmota/xsns_44_sps30.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_44_sps30.ino" +#ifdef USE_I2C +#ifdef USE_SPS30 + +#define XSNS_44 44 +#define XI2C_30 30 + +#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(void) +{ + if (!I2cSetDevice(SPS30_ADDR)) { return; } + I2cSetActiveFound(SPS30_ADDR, "SPS30"); + + 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_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) +{ + if (!sps30_running) { return; } + + char str[64]; + 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\"}}")); + MqttPublishTeleSensor(); +} + +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) +{ + if (!I2cEnabled(XI2C_30)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + SPS30_Detect(); + } + else if (sps30_ready) { + switch (function) { + case FUNC_EVERY_SECOND: + SPS30_Every_Second(); + break; + case FUNC_JSON_APPEND: + SPS30_Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SPS30_Show(0); + break; + #endif + case FUNC_COMMAND_SENSOR: + if (XSNS_44 == XdrvMailbox.index) { + result = SPS30_cmd(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_45_vl53l0x.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_45_vl53l0x.ino" +#ifdef USE_I2C +#ifdef USE_VL53L0X + + + + + + +#define XSNS_45 45 +#define XI2C_31 31 + +#include +#include "VL53L0X.h" +VL53L0X sensor; + +struct { + uint16_t distance; + uint16_t distance_prev; + uint16_t buffer[5]; + uint8_t ready = 0; + uint8_t index; +} Vl53l0x; + + + +void Vl53l0Detect(void) { + if (!I2cSetDevice(0x29)) { return; } + + if (!sensor.init()) { return; } + + I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); + + sensor.setTimeout(500); + + + + + + sensor.startContinuous(); + Vl53l0x.ready = 1; + + Vl53l0x.index = 0; +} + +#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(void) { + + uint16_t dist = sensor.readRangeContinuousMillimeters(); + if ((0 == dist) || (dist > 2000)) { + dist = 9999; + } + +#ifdef USE_VL_MEDIAN + + Vl53l0x.buffer[Vl53l0x.index] = dist; + Vl53l0x.index++; + if (Vl53l0x.index >= 5) { + Vl53l0x.index = 0; + } + + + uint16_t tbuff[5]; + memmove(tbuff, Vl53l0x.buffer, sizeof(tbuff)); + uint16_t tmp; + uint8_t flag; + for (uint32_t ocnt = 0; ocnt < 5; ocnt++) { + flag = 0; + for (uint32_t 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 +} + +#ifdef USE_DOMOTICZ +void Vl53l0Every_Second(void) { + if (abs(Vl53l0x.distance - Vl53l0x.distance_prev) > 8) { + Vl53l0x.distance_prev = Vl53l0x.distance; + DomoticzSensor(DZ_ILLUMINANCE, Vl53l0x.distance); + } +} +#endif + +void Vl53l0Show(boolean json) { + if (json) { + ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), Vl53l0x.distance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, Vl53l0x.distance); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L0X, Vl53l0x.distance); +#endif + } +} + + + + + +bool Xsns45(byte function) +{ + if (!I2cEnabled(XI2C_31)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Vl53l0Detect(); + } + else if (Vl53l0x.ready) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + Vl53l0Every_250MSecond(); + break; +#ifdef USE_DOMOTICZ + case FUNC_EVERY_SECOND: + Vl53l0Every_Second(); + break; +#endif + case FUNC_JSON_APPEND: + Vl53l0Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l0Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_46_MLX90614.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_46_MLX90614.ino" +#ifdef USE_I2C +#ifdef USE_MLX90614 + +#define XSNS_46 46 +#define XI2C_32 32 + +#define I2_ADR_IRT 0x5a + +#define MLX90614_RAWIR1 0x04 +#define MLX90614_RAWIR2 0x05 +#define MLX90614_TA 0x06 +#define MLX90614_TOBJ1 0x07 +#define MLX90614_TOBJ2 0x08 + +struct { + union { + uint16_t value; + uint32_t i2c_buf; + }; + float obj_temp; + float amb_temp; + bool ready = false; +} mlx90614; + +void MLX90614_Init(void) +{ + if (!I2cSetDevice(I2_ADR_IRT)) { return; } + I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); + mlx90614.ready = true; +} + +void MLX90614_Every_Second(void) +{ + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); + if (mlx90614.value & 0x8000) { + mlx90614.obj_temp = -999; + } else { + mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; + } + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); + if (mlx90614.value & 0x8000) { + mlx90614.amb_temp = -999; + } else { + mlx90614.amb_temp = ((float)mlx90614.value * 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}"; +#endif + +void MLX90614_Show(uint8_t json) +{ + char obj_tstr[16]; + dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); + char amb_tstr[16]; + dtostrfd(mlx90614.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 + } +} + + + + + +bool Xsns46(byte function) +{ + if (!I2cEnabled(XI2C_32)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MLX90614_Init(); + } + else if (mlx90614.ready) { + switch (function) { + 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 "/workspace/Tasmota/tasmota/xsns_47_max31865.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_47_max31865.ino" +#ifdef USE_MAX31865 + + + + +#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 + +#include "Adafruit_MAX31865.h" + +int8_t max31865_init_status = 0; +uint8_t max31865_pins_used = 0; + +Adafruit_MAX31865 max31865[MAX_MAX31865S]; + +struct MAX31865_Result_Struct { + uint8_t ErrorCode; + uint16_t Rtd; + float PtdResistance; + float PtdTemp; +} MAX31865_Result[MAX_MAX31865S]; + +void MAX31865_Init(void) { + if (max31865_init_status) { return; } + + max31865_init_status = 1; + for (uint32_t i = 0; i < MAX_MAX31865S; i++) { + if (PinUsed(GPIO_SSPI_MAX31865_CS1, i)) { + max31865_pins_used |= 1 << i; + max31865[0].setPins( + Pin(GPIO_SSPI_MAX31865_CS1, i), + Pin(GPIO_SSPI_MOSI), + Pin(GPIO_SSPI_MISO), + Pin(GPIO_SSPI_SCLK) + ); + + if (!max31865[i].begin(PTD_WIRES)) { + max31865_init_status = -1; + } + } + } +} + + + + + +void MAX31865_GetResult(void) { + for (uint32_t i = 0; i < MAX_MAX31865S; i++) { + if (max31865_pins_used & (1 << i)) { + uint16_t rtd; + + rtd = max31865[i].readRTD(); + MAX31865_Result[i].Rtd = rtd; + MAX31865_Result[i].PtdResistance = max31865[i].rtd_to_resistance(rtd, MAX31865_REF_RES); + MAX31865_Result[i].PtdTemp = max31865[i].rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; + } + } +} + +void MAX31865_Show(bool Json) { + uint8_t report_once = 0; + for (uint32_t i = 0; i < MAX_MAX31865S; i++) { + if (max31865_pins_used & (1 << i)) { + char temperature[33]; + char resistance[33]; + + dtostrfd(MAX31865_Result[i].PtdResistance, Settings.flag2.temperature_resolution, resistance); + dtostrfd(MAX31865_Result[i].PtdTemp, Settings.flag2.temperature_resolution, temperature); + + if (Json) { + ResponseAppend_P(PSTR(",\"MAX31865%c%d\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + IndexSeparator(), i, temperature, resistance, MAX31865_Result[i].ErrorCode); + if ((0 == tele_period) && (!report_once)) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, MAX31865_Result[i].PtdTemp); +#endif + report_once++; + } +#ifdef USE_WEBSERVER + } else { + char sensorname[33]; + sprintf(sensorname, "MAX31865%c%d", IndexSeparator(), i); + WSContentSend_PD(HTTP_SNS_TEMP, sensorname, temperature, TempUnit()); +#endif + } + } + } +} + + + + + +bool Xsns47(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_SSPI_MAX31865_CS1, GPIO_ANY) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) { + switch (function) { + case FUNC_INIT: + MAX31865_Init(); + break; + + case FUNC_EVERY_SECOND: + MAX31865_GetResult(); + break; + + case FUNC_JSON_APPEND: + MAX31865_Show(1); + break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31865_Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" +# 37 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" +#ifdef USE_I2C +#ifdef USE_CHIRP +# 49 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" +#define XSNS_48 48 +#define XI2C_33 33 + +#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 + + + + + +void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { + Wire.beginTransmission(addr); + Wire.write(reg); + Wire.endTransmission(); +} + +uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { + Wire.requestFrom(addr,(uint8_t)2); + uint16_t t = Wire.read() << 8; + t = t | Wire.read(); + return t; +} + + + + + +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) { + ChirpWriteI2CRegister(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) { + ChirpWriteI2CRegister(addr, CHIRP_SLEEP); +} +# 187 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" +void ChirpSelect(uint8_t sensor) { + if(sensor < chirp_found_sensors) { + chirp_current = sensor; + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); + } + if (sensor == 255) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); + } +} + + + +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)){ + 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); + + } + 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){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); + chirp_sensor[chirp_current].version == 0; + } + return true; + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); + 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) { + I2cSetActiveFound(address, "CHIRP"); + if (chirp_found_sensors 0); +} + + + +void ChirpDetect(void) +{ + if (chirp_next_job > 0) { return; } + + DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); + if (ChirpScan()) { + uint8_t chirp_model = 0; + GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); + } +} + + +void ChirpServiceAllSensors(uint8_t job){ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); + switch(job){ + case 0: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); + break; + case 1: + chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 2: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); + break; + case 3: + chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 4: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); + break; + case 5: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); + break; + case 6: + chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + default: + break; + } + } + } +} + + + +void ChirpEvery100MSecond(void) +{ + + if(chirp_timeout_count == 0) { + switch(chirp_next_job) { + case 0: + DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); + ChirpResetAll(); + chirp_timeout_count = 10; + chirp_next_job++; + break; + case 1: + + + chirp_next_job++; + break; + case 2: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 3: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 4: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 5: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 6: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 7: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 8: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 9: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 10: + DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); + ChirpServiceAllSensors(4); + chirp_timeout_count = 90; + chirp_next_job++; + break; + case 11: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); + ChirpServiceAllSensors(5); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 12: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); + ChirpServiceAllSensors(6); + chirp_next_job++; + break; + case 13: + DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); + chirp_next_job++; + break; + case 14: + if (Settings.tele_period > 16){ + chirp_timeout_count = (Settings.tele_period - 16) * 10; + 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 !")); + + } + chirp_next_job = 1; + break; + } + } + else { + chirp_timeout_count--; + } +} + + + + +#ifdef USE_WEBSERVER + + +const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{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_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[7]; + if(chirp_sensor[i].version == 0xff){ + 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 "\":%d"), chirp_name, i, chirp_sensor[i].moisture); + if(chirp_sensor[i].temperature!=-1){ + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); + } + ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); + } + else { + ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); + } + #ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumPressureSensor(t_temperature, chirp_sensor[i].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, "", chirp_sensor[i].moisture); + WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); + if (chirp_sensor[i].temperature!=-1) { + 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) +{ + if (!I2cEnabled(XI2C_33)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if(chirp_found_sensors > 0){ + ChirpEvery100MSecond(); + } + break; + case FUNC_COMMAND: + result = ChirpCmd(); + break; + case FUNC_JSON_APPEND: + ChirpShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ChirpShow(0); + break; +#endif + case FUNC_INIT: + ChirpDetect(); + break; + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" +# 31 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" +#ifdef USE_I2C +#ifdef USE_PAJ7620 + + + + + + +#define XSNS_50 50 +#define XI2C_34 34 + +#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} +}; + + + + + +const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; + +const uint8_t PAJ7620_PIN[]= {1,2,3,4}; + + + + + +char PAJ7620_name[] = "PAJ7620"; + +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 PAJ7620SelectBank(uint8_t bank) +{ + I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); +} + + + +void PAJ7620DecodeGesture(void) +{ + uint32_t index = 0; + switch (PAJ7620_gesture.current) { + case PAJ7620_LEFT: + index++; + case PAJ7620_RIGHT: + index++; + case PAJ7620_UP: + index++; + case PAJ7620_DOWN: + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_NEAR: + index = 4; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_FAR: + index = 5; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_CW: + index = 6; + PAJ7620_finished_gesture = true; + break; + case PAJ7620_CCW: + index = 7; + PAJ7620_finished_gesture = true; + break; + default: + index = 8; + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + } + break; + } + if (index < 8) { + GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); + } + + 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; + MqttPublishSensor(); + } +} + + + +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("PAJ: 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("PAJ: Proximity: %u"), PAJ7620_state.proximity); + MqttPublishSensor(); + } + } + 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("PAJ: 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; + } + 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("PAJ: 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("PAJ: PIN valid!!")); + PAJ7620_state.PIN.countdown = 0; + } + MqttPublishSensor(); + } + } + break; + } +} + + + +void PAJ7620Detect(void) +{ + if (I2cActive(PAJ7620_ADDR)) { return; } + + PAJ7620SelectBank(0); + PAJ7620SelectBank(0); + uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); + uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); + if (0x7620 == PAJ7620_id) { + I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); + PAJ7620_next_job = 1; + } + else { + DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); + } +} + + + +void PAJ7620Init(void) +{ + DEBUG_SENSOR_LOG(PSTR("PAJ: 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("PAJ: %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("PAJ: init sensor done %u"),millis()); + PAJ7620_next_job = 2; +} + + + +void PAJ7620Loop(void) +{ + if (0 == PAJ7620_timeout_counter) { + switch (PAJ7620_next_job) { + case 1: + PAJ7620Init(); + break; + case 2: + if (PAJ7620_mode != 0) { + PAJ7620ReadGesture(); + } + break; + } + } else { + PAJ7620_timeout_counter--; + } +} + + + +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: + ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); + break; + case 3: + if (PAJ7620_state.corner > 0) { + ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); + } + break; + case 4: + if (PAJ7620_state.PIN.valid) { + ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); + PAJ7620_state.PIN.valid = 0; + } + break; + case 5: + ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); + break; + } + } +} +# 411 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" +bool PAJ7620CommandSensor(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + PAJ7620_mode = XdrvMailbox.payload; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); + + return true; +} + + + + + +bool Xsns50(uint8_t function) +{ + if (!I2cEnabled(XI2C_34)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PAJ7620Detect(); + } + else if (PAJ7620_next_job) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_50 == XdrvMailbox.index){ + result = PAJ7620CommandSensor(); + } + break; + case FUNC_EVERY_100_MSECOND: + PAJ7620Loop(); + break; + case FUNC_JSON_APPEND: + PAJ7620Show(1); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" +#ifdef USE_RDM6300 +# 31 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" +#define XSNS_51 51 + +#define RDM6300_BAUDRATE 9600 +#define RDM_TIMEOUT 100 +#define RDM6300_BLOCK 2 * 10 + +#include +TasmotaSerial *RDM6300Serial = nullptr; + +struct { + uint32_t uid = 0; + uint8_t block_time = 0; +} Rdm; + + + +uint8_t RDM6300HexNibble(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; +} + + +void RDM6300HexStringToArray(uint8_t array[], uint8_t len, char buffer[]) { + char *cp = buffer; + for (uint32_t i = 0; i < len; i++) { + uint8_t val = RDM6300HexNibble(*cp++) << 4; + array[i] = val | RDM6300HexNibble(*cp++); + } +} + + + +void RDM6300Init() { + if (PinUsed(GPIO_RDM6300_RX)) { + RDM6300Serial = new TasmotaSerial(Pin(GPIO_RDM6300_RX), -1, 1); + if (RDM6300Serial->begin(RDM6300_BAUDRATE)) { + if (RDM6300Serial->hardwareSerial()) { + ClaimSerial(); + } + } + } +} + +void RDM6300ScanForTag() { + if (!RDM6300Serial) { return; } + + if (Rdm.block_time > 0) { + Rdm.block_time--; + while (RDM6300Serial->available()) { + RDM6300Serial->read(); + } + return; + } + + if (RDM6300Serial->available()) { + + char c = RDM6300Serial->read(); + if (c != 2) { return; } + + + char rdm_buffer[14]; + uint8_t rdm_index = 0; + + rdm_buffer[rdm_index++] = c; + + uint32_t cmillis = millis(); + while (1) { + if (RDM6300Serial->available()) { + c = RDM6300Serial->read(); + rdm_buffer[rdm_index++] = c; + + if (3 == c) { break; } + if (rdm_index > 14) { break; } + } + if ((millis() - cmillis) > RDM_TIMEOUT) { + return; + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)rdm_buffer, sizeof(rdm_buffer)); + + if (rdm_buffer[13] != 3) { return; } + + Rdm.block_time = RDM6300_BLOCK; + + uint8_t rdm_array[6]; + RDM6300HexStringToArray(rdm_array, sizeof(rdm_array), (char*)rdm_buffer +1); + uint8_t accu = 0; + for (uint32_t count = 0; count < 5; count++) { + accu ^= rdm_array[count]; + } + if (accu != rdm_array[5]) { return; } + + rdm_buffer[11] = '\0'; + uint32_t uid = strtoul(rdm_buffer +3, nullptr, 16); + if (uid > 0) { + Rdm.uid = uid; + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%08X\"}}"), Rdm.uid); + MqttPublishTeleSensor(); + } + } +} + +#ifdef USE_WEBSERVER +void RDM6300Show(void) { + if (!RDM6300Serial) { return; } + WSContentSend_PD(PSTR("{s}RDM6300 UID{m}%08X {e}"), Rdm.uid); +} +#endif + + + + + +bool Xsns51(byte function) { + bool result = false; + + switch (function) { + case FUNC_INIT: + RDM6300Init(); + break; + case FUNC_EVERY_100_MSECOND: + RDM6300ScanForTag(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RDM6300Show(); + break; +#endif + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_52_ibeacon.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_52_ibeacon.ino" +#ifdef USE_IBEACON + + + +#define XSNS_52 52 + +#include + +#define TMSBSIZ52 512 + +#define HM17_BAUDRATE 9600 + +#define IBEACON_DEBUG + + +#define HM17_V110 + + + +#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]; + char UID[32]; + char MAJOR[4]; + char MINOR[4]; + uint8_t FLAGS; + uint8_t TIME; +} ibeacons[MAX_IBEACONS]; + + +void IBEACON_Init() { + + hm17_found=0; + + + if (PinUsed(GPIO_IBEACON_RX) && PinUsed(GPIO_IBEACON_TX)) { + IBEACON_Serial = new TasmotaSerial(Pin(GPIO_IBEACON_RX), Pin(GPIO_IBEACON_TX),1,0,TMSBSIZ52); + 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",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR); + } + } + } + } else { + if (uptime%20==0) { + hm17_sendcmd(HM17_TEST); + } + } +} + +void hm17_sbclr(void) { + memset(hm17_sbuffer,0,HM17_BSIZ); + hm17_sindex=0; + +} + +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->RSSI,"0",1)) { + return 0; + } + + + if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { + for (uint32_t cnt=0;cntUID,PSTR("00000000000000000000000000000000"),32)) { + if (!strncmp(ibeacons[cnt].MAC,ib->MAC,12)) { + + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].TIME=0; + return 1; + } + } else { + if (!strncmp(ibeacons[cnt].UID,ib->UID,32)) { + + 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); + memcpy(ibeacons[cnt].UID,ib->UID,32); + memcpy(ibeacons[cnt].MAJOR,ib->MAJOR,4); + memcpy(ibeacons[cnt].MINOR,ib->MINOR,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+DISIS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS 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_cmd==HM17_DISI) { +#ifdef HM17_V110 + goto hm17_v110; +#endif + } else { + 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)) { +hm17_v110: + 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,ib.UID,ib.MAJOR,ib.MINOR); + } + 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_mac[] PROGMEM = + "{s}IBEACON-MAC : %s" " - RSSI : %s" "{m}{e}"; +const char HTTP_IBEACON_uid[] PROGMEM = + "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; + +void IBEACON_Show(void) { +char mac[14]; +char rssi[6]; +char uid[34]; + + 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 + + +#ifndef ESP32 +#define SPECIAL_SS +#endif + +#undef TMSBSIZ +#define TMSBSIZ 256 + + + + + + +#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 +# 440 "/workspace/Tasmota/tasmota/xsns_53_sml.ino" +#define USE_SML_MEDIAN_FILTER + + +#ifndef SML_MAX_VARS +#define SML_MAX_VARS 20 +#endif + + +#ifndef MAX_METERS +#define MAX_METERS 5 +#endif +double meter_vars[SML_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]; + + +#ifdef ESP32 +HardwareSerial *meter_ss[MAX_METERS]; +#else +TasmotaSerial *meter_ss[MAX_METERS]; +#endif + + +#ifndef SML_BSIZ +#define SML_BSIZ 48 +#endif +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[SML_MAX_VARS]; + +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif + +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); +# 552 "/workspace/Tasmota/tasmota/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; + if (!meter_ss[num-1]) return 0; + return meter_ss[num-1]->available(); +} + +uint8_t Serial_read() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + if (!meter_ss[num-1]) return 0; + return meter_ss[num-1]->read(); +} + +uint8_t Serial_peek() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + if (!meter_ss[num-1]) return 0; + 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 (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 { + if (meter_desc_p[(dump2log&7)-1].type=='o') { + + 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_logindex2) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + } + } + } +} + +#ifdef ED300L +uint8_t sml_status[MAX_METERS]; +uint8_t g_mindex; +#endif + + +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; + + + +#ifdef ED300L + unsigned char *cpx=cp-5; + + if (*cp==0x64 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { + sml_status[g_mindex]=*(cp+3); + } + if (*cp==0x63 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { + sml_status[g_mindex]=*(cp+2); + } +#endif + + 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!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R') { + + 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' || meter_desc_p[meters].type=='M') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=SML_BSIZ) { + meter_spos[meters]=0; + } + if (meter_spos[meters]>=8) { + uint32_t mlen=smltbuf[meters][2]+5; + if (mlen>SML_BSIZ) mlen=SML_BSIZ; + if (meter_spos[meters]>=mlen) { + 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 (meter_desc_p[meters].type=='R') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=SML_BSIZ) { + 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!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R') 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) { + + if (*mp==0) break; + + + 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>SML_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>SML_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>SML_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[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (!strncmp(mp,"SSssSSss",8)) { + int32_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++; + mbus_dval=val; + 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); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { + int16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } + else if (*mp=='s' && *(mp+1)=='s') { + int8_t val = *cp++; + mbus_dval=val; + 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++; +#ifdef ED300L + g_mindex=mindex; +#endif + 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 pos = smltbuf[mindex][2]+3; + if (pos>32) pos=32; + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos); + if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect; + if (highByte(crc)!=smltbuf[mindex][pos+1]) 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) { + if (*mp==0) break; + + mindex=((*mp)&7)-1; + + if (mindex<0 || mindex>=meters_used) mindex=0; + if (meter_desc_p[mindex].prefix[0]=='*' && meter_desc_p[mindex].prefix[1]==0) { + nojson=1; + } else { + nojson=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]++; + sml_counters[index].sml_cnt_updated=1; + + } + } else { + + sml_counters[index].sml_counter_ltime=millis(); + } +} + +void ICACHE_RAM_ATTR SML_CounterUpd1(void) { + SML_CounterUpd(0); +} + +void ICACHE_RAM_ATTR SML_CounterUpd2(void) { + SML_CounterUpd(1); +} + +void ICACHE_RAM_ATTR SML_CounterUpd3(void) { + SML_CounterUpd(2); +} + +void ICACHE_RAM_ATTR SML_CounterUpd4(void) { + SML_CounterUpd(3); +} + +#ifdef USE_SCRIPT +struct METER_DESC script_meter_desc[MAX_METERS]; +uint8_t *script_meter; +#endif + +#ifndef METER_DEF_SIZE +#define METER_DEF_SIZE 3000 +#endif + + + +#ifdef SML_REPLACE_VARS + +#define SML_SRCBSIZE 256 + +uint32_t SML_getlinelen(char *lp) { +uint32_t cnt; + for (cnt=0; cnt') break; + if (*lp==0) break; + } + + return mlen+32; +} +#else +uint32_t SML_getscriptsize(char *lp) { + uint32_t mlen=0; + for (uint32_t cnt=0;cnt 0)) { + return true; + } + return false; +} + +void SML_Init(void) { + meters_used=METERS_USED; + meter_desc_p=meter_desc; + meter_p=meter; + + sml_desc_cnt=0; + + for (uint32_t cnt=0;cntM",-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=SML_getscriptsize(lp); + if (mlen==0) return; + script_meter=(uint8_t*)calloc(mlen,1); + if (!script_meter) { + goto dddef_exit; + } + tp=script_meter; + goto next_line; + } + } + else { + if (!*lp || *lp=='#' || *lp=='>') { + 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 (*lp1==0) { + *tp++='|'; + goto next_line; + } + *tp++=*lp1++; + index++; + if (index>=METER_DEF_SIZE) break; + } + } +#else + + if (*lp=='-' || isdigit(*lp)) { + + + if (*lp=='-') lp++; + uint8_t mnum=strtol(lp,0,10); + if (mnum<1 || mnum>meters_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; + } + } +#endif + + } + +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(); + } + uint32_t uart_index=2; + for (uint8_t meters=0; meterssetRxBufferSize(TMSBSIZ); +#else + meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,0,TMSBSIZ); +#endif +#endif + +#ifdef ESP32 + if (meter_desc_p[meters].type=='M') { + meter_ss[meters]->begin(meter_desc_p[meters].params, SERIAL_8E1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin); + } else { + meter_ss[meters]->begin(meter_desc_p[meters].params,SERIAL_8N1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin); + } +#else + if (meter_ss[meters]->begin(meter_desc_p[meters].params)) { + meter_ss[meters]->flush(); + } + if (meter_ss[meters]->hardwareSerial()) { + if (meter_desc_p[meters].type=='M') { + Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); + } + ClaimSerial(); + + } +#endif + } + } + +} + + +#ifdef USE_SML_SCRIPT_CMD +uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + +#ifdef ESP32 + meter_ss[meter]->flush(); + meter_ss[meter]->updateBaudRate(br); + + + + + + +#else + if (meter_ss[meter]->begin(br)) { + meter_ss[meter]->flush(); + } + if (meter_ss[meter]->hardwareSerial()) { + if (meter_desc_p[meter].type=='M') { + Serial.begin(br, SERIAL_8E1); + } + } +#endif + return 1; +} + +uint32_t SML_Status(uint32_t meter) { + if (meter<1 || meter>meters_used) return 0; + meter--; +#ifdef ED300L + return sml_status[meter]; +#else + return 0; +#endif +} + + +uint32_t SML_Write(uint32_t meter,char *hstr) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + SML_Send_Seq(meter,hstr); + return 1; +} + +uint32_t SML_Read(int32_t meter,char *str, uint32_t slen) { +uint8_t hflg=0; + if (meter<0) { + meter=abs(meter); + hflg=1; + } + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + + if (!meter_spos[meter]) { + return 0; + } + + smltbuf[meter][meter_spos[meter]]=0; + + if (!hflg) { + strlcpy(str,(char*)&smltbuf[meter][0],slen); + } else { + uint32_t index=0; + for (uint32_t cnt=0; cnt=slen-2) break; + } + } + meter_spos[meter]=0; + return 1; +} + +float SML_GetVal(uint32_t index) { + if (index<1 && index>SML_MAX_VARS) { index = 1;} + return meter_vars[index-1]; +} + +#endif + + +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 + } + + if (sml_counters[cindex].sml_cnt_updated) { + InjektCounterValue(sml_counters[cindex].sml_cnt_old_state,RtcSettings.pulse_counter[cindex]); + sml_counters[cindex].sml_cnt_updated=0; + } + + + } + 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; + } + } + } + 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)) { + sml_100ms_cnt=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; + uint8_t rflg = 0; + if (*cp=='r') { + rflg = 1; + cp++; + } + 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' || script_meter_desc[meter].type=='M') { + if (!rflg) { + *ucp++=0; + *ucp++=2; + slen+=2; + } + + uint16_t crc = MBUS_calculateCRC(sbuff,slen); + *ucp++=lowByte(crc); + *ucp++=highByte(crc); + slen+=2; + } + if (script_meter_desc[meter].type=='o') { + for (uint32_t cnt=0;cntwrite(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); +} + + +uint8_t CalcEvenParity(uint8_t data) { +uint8_t parity=0; + + while(data) { + parity^=(data &1); + data>>=1; + } + return parity; +} +# 2540 "/workspace/Tasmota/tasmota/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++; + uint8_t index=atoi(cp); + if ((index&7)>meters_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') { + + 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( Ina226Info[device].address, INA226_REG_CONFIG ); + + + if (config != Ina226Info[device].config) + return false; + + return true; + +} + +void Ina226ResetActive(void) +{ + Ina226Info_t *p = Ina226Info; + + for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { + p = &Ina226Info[i]; + + uint8_t addr = p->address; + if (addr) { + I2cResetActive(addr); + } + } +} + + + + + +void Ina226Init() +{ + uint32_t i; + + Ina226sFound = 0; + + Ina226Info_t *p = Ina226Info; +# 215 "/workspace/Tasmota/tasmota/xsns_54_ina226.ino" + 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 (I2cActive(addr)) { continue; } + + + + + 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 = &Ina226Info[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); + + I2cSetActiveFound(addr, Ina226Str); + + Ina226sFound++; + } +} + + + + + +float Ina226ReadBus_v(uint8_t device) +{ + uint8_t addr = Ina226Info[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 = Ina226Info[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); + + float result = ((float) reg_shunt_i) * Ina226Info[device].i_lsb; + + return result; +} + + + + + +float Ina226ReadPower_w(uint8_t device) +{ + uint8_t addr = Ina226Info[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); + + float result = ((float) reg_shunt_i) * (Ina226Info[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 (Ina226sFound && Ina226Info[device].present && Ina226TestPresence(device)){ + Ina226Read(device); + } + else { + powers[device] = currents[device] = voltages[device] = 0.0f; + + + + + + + Ina226Info[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: + Ina226ResetActive(); + Ina226Init(); + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Ina226sFound\":%d}}"),Ina226sFound); + 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 (!Ina226Info[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\":%d,\"" 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 + } + + } + +} +# 546 "/workspace/Tasmota/tasmota/xsns_54_ina226.ino" +bool Xsns54(byte callback_id) +{ + if (!I2cEnabled(XI2C_35)) { return false; } + + + bool result = false; + + + switch (callback_id) { + case FUNC_EVERY_SECOND: + Ina226EverySecond(); + 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; + case FUNC_INIT: + Ina226Init(); + break; + } + + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" +#ifdef USE_I2C +#ifdef USE_HIH6 +# 33 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" +#define XSNS_55 55 +#define XI2C_36 36 + +#define HIH6_ADDR 0x27 + +struct HIH6 { + float temperature = 0; + float humidity = 0; + uint8_t valid = 0; + uint8_t type = 0; + char types[4] = "HIH"; +} Hih6; + +bool Hih6Read(void) +{ + Wire.beginTransmission(HIH6_ADDR); + if (Wire.endTransmission() != 0) { return false; } + + delay(40); + + uint8_t data[4]; + Wire.requestFrom(HIH6_ADDR, 4); + if (4 == Wire.available()) { + data[0] = Wire.read(); + data[1] = Wire.read(); + data[2] = Wire.read(); + data[3] = Wire.read(); + } else { return false; } + + + + Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); + + int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; + Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); + + Hih6.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Hih6Detect(void) +{ + if (I2cActive(HIH6_ADDR)) { return; } + + if (uptime < 2) { delay(20); } + Hih6.type = Hih6Read(); + if (Hih6.type) { + I2cSetActiveFound(HIH6_ADDR, Hih6.types); + } +} + +void Hih6EverySecond(void) +{ + if (uptime &1) { + + if (!Hih6Read()) { + AddLogMissed(Hih6.types, Hih6.valid); + } + } +} + +void Hih6Show(bool json) +{ + if (Hih6.valid) { + TempHumDewShow(json, (0 == tele_period), Hih6.types, Hih6.temperature, Hih6.humidity); + } +} + + + + + +bool Xsns55(uint8_t function) +{ + if (!I2cEnabled(XI2C_36)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Hih6Detect(); + } + else if (Hih6.type) { + switch (function) { + case FUNC_EVERY_SECOND: + Hih6EverySecond(); + break; + case FUNC_JSON_APPEND: + Hih6Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Hih6Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" +# 21 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" +#ifdef USE_HPMA +# 31 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" +#define XSNS_56 56 + +#include +#include + +TasmotaSerial *HpmaSerial; +HPMA115S0 *hpma115S0; + +uint8_t hpma_type = 1; +uint8_t hpma_valid = 0; + +struct hpmadata { + unsigned int pm10; + unsigned int pm2_5; +} hpma_data; + + + +void HpmaSecond(void) +{ + unsigned int pm2_5, pm10; + + + + + if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { + hpma_data.pm2_5 = pm2_5; + hpma_data.pm10 = pm10; + hpma_valid = 1; + } + +} + +void HpmaInit(void) +{ + hpma_type = 0; + if (PinUsed(GPIO_HPMA_RX) && PinUsed(GPIO_HPMA_TX)) { + HpmaSerial = new TasmotaSerial(Pin(GPIO_HPMA_RX), Pin(GPIO_HPMA_TX), 1); + hpma115S0 = new HPMA115S0(*HpmaSerial); + + if (HpmaSerial->begin(9600)) { + if (HpmaSerial->hardwareSerial()) { + ClaimSerial(); + } + hpma_type = 1; + hpma115S0->Init(); + hpma115S0->StartParticleMeasurement(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_HPMA_SNS[] PROGMEM = + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void HpmaShow(bool json) +{ + if (hpma_valid) { + char pm10[33]; + snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); + char pm2_5[33]; + snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); + + if (json) { + ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.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_HPMA_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns56(uint8_t function) +{ + bool result = false; + + if (hpma_type) { + switch (function) { + case FUNC_INIT: + HpmaInit(); + break; + case FUNC_EVERY_SECOND: + HpmaSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_56 == XdrvMailbox.index) { + return true; + } + break; + case FUNC_JSON_APPEND: + HpmaShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HpmaShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_57_tsl2591.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_57_tsl2591.ino" +#ifdef USE_I2C +#ifdef USE_TSL2591 + + + + + + + +#define XSNS_57 57 +#define XI2C_40 40 + +#define TSL2591_ADDRESS 0x29 + +#include + +Adafruit_TSL2591 tsl = Adafruit_TSL2591(); + +uint8_t tsl2591_type = 0; +uint8_t tsl2591_valid = 0; +float tsl2591_lux = 0; + +void Tsl2591Init(void) +{ + + if (I2cSetDevice(0x29)) { + if (tsl.begin()) { + tsl.setGain(TSL2591_GAIN_MED); + tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); + tsl2591_type = 1; + I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); + } + } +} + +bool Tsl2591Read(void) +{ + uint32_t lum = tsl.getFullLuminosity(); + uint16_t ir, full; + ir = lum >> 16; + full = lum & 0xFFFF; + tsl2591_lux = tsl.calculateLux(full, ir); + tsl2591_valid = 1; +} + +void Tsl2591EverySecond(void) +{ + Tsl2591Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2591[] PROGMEM = + "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; +#endif + +void Tsl2591Show(bool json) +{ + if (tsl2591_valid) { + char lux_str[10]; + dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); + if (json) { + ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); +#endif + } + } +} + + + + + +bool Xsns57(uint8_t function) +{ + if (!I2cEnabled(XI2C_40)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2591Init(); + } + else if (tsl2591_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Tsl2591EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2591Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2591Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_58_dht12.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_58_dht12.ino" +#ifdef USE_I2C +#ifdef USE_DHT12 + + + + + + +#define XSNS_58 58 +#define XI2C_41 41 + +#define DHT12_ADDR 0x5C + +struct DHT12 { + float temperature = NAN; + float humidity = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "DHT12"; +} Dht12; + +bool Dht12Read(void) +{ + if (Dht12.valid) { Dht12.valid--; } + + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { return false; } + + delay(50); + + Wire.requestFrom(DHT12_ADDR, 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + + Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); + Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); + + if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } + + Dht12.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Dht12Detect(void) +{ + if (I2cActive(DHT12_ADDR)) { return; } + + if (Dht12Read()) { + I2cSetActiveFound(DHT12_ADDR, Dht12.name); + Dht12.count = 1; + } +} + +void Dht12EverySecond(void) +{ + if (uptime &1) { + + if (!Dht12Read()) { + AddLogMissed(Dht12.name, Dht12.valid); + } + } +} + +void Dht12Show(bool json) +{ + if (Dht12.valid) { + TempHumDewShow(json, (0 == tele_period), Dht12.name, Dht12.temperature, Dht12.humidity); + } +} + + + + + +bool Xsns58(uint8_t function) +{ + if (!I2cEnabled(XI2C_41)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Dht12Detect(); + } + else if (Dht12.count) { + switch (function) { + case FUNC_EVERY_SECOND: + Dht12EverySecond(); + break; + case FUNC_JSON_APPEND: + Dht12Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Dht12Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_59_ds1624.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_59_ds1624.ino" +#ifdef USE_I2C +#ifdef USE_DS1624 + + + + + + + +#define XSNS_59 59 +#define XI2C_42 42 + +#define DS1624_MEM_REGISTER 0x17 +#define DS1624_CONF_REGISTER 0xAC +#define DS1624_TEMP_REGISTER 0xAA +#define DS1624_START_REGISTER 0xEE +#define DS1624_STOP_REGISTER 0x22 + +#define DS1621_COUNTER_REGISTER 0xA8 +#define DS1621_SLOPE_REGISTER 0xA9 + +#define DS1621_CFG_1SHOT (1<<0) +#define DS1621_CFG_DONE (1<<7) + +enum { + DS1624_TYPE_DS1624, + DS1624_TYPE_DS1621 +}; + +#define DS1624_MAX_SENSORS 8 + +bool ds1624_init = false; + +struct { + float value; + uint8_t type; + int errcnt; + int misscnt; + bool valid; + char name[9]; +} ds1624_sns[DS1624_MAX_SENSORS]; + +uint32_t DS1624_Idx2Addr(uint32_t idx) { + return 0x48 + idx; +} + +void DS1624_Restart(uint8_t config, uint32_t idx) { + uint32_t addr = DS1624_Idx2Addr(idx); + if ((config & 1) == 1) { + config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + delay(10); + AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); + } + I2cValidRead(addr, DS1624_START_REGISTER, 1); +} + +void DS1624_HotPlugUp(uint32_t idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + if (I2cActive(addr)) { return; } + if (!I2cSetDevice(addr)) { return; } + + uint8_t config; + if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + uint8_t tmp; + ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; + + snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), + (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); + I2cSetActiveFound(addr, ds1624_sns[idx].name); + + ds1624_sns[idx].valid = true; + ds1624_sns[idx].errcnt = 0; + ds1624_sns[idx].misscnt = 0; + DS1624_Restart(config,idx); + AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); + } +} + +void DS1624_HotPlugDown(int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + if (!I2cActive(addr)) { return; } + I2cResetActive(addr); + ds1624_sns[idx].valid = false; + AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); +} + +bool DS1624GetTemp(float *value, int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + uint8_t config; + if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + ds1624_sns[idx].misscnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); + return false; + } + ds1624_sns[idx].misscnt=0; + if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { + ds1624_sns[idx].errcnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); + DS1624_Restart(config, idx); + return false; + } + + uint16_t t; + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } + if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { + *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; + } else { + + *value = ((float)(int8_t)(t>>8)); + uint8_t remain; + if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } + uint8_t perc; + if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } + float fix=(float)(perc - remain)/(float)perc; + *value+=fix; + } + ds1624_sns[idx].errcnt=0; + config &= ~(DS1621_CFG_DONE); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + return true; +} + +void DS1624HotPlugScan(void) +{ + uint16_t t; + + for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { + uint32_t addr = DS1624_Idx2Addr(idx); + if (I2cActive(addr) && !ds1624_sns[idx].valid) { + continue; + } + if (ds1624_sns[idx].valid) { + if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { + DS1624_HotPlugDown(idx); + continue; + } + } + DS1624_HotPlugUp(idx); + } +} + +void DS1624EverySecond(void) +{ + float t; + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + if (!DS1624GetTemp(&t, i)) { continue; } + ds1624_sns[i].value = ConvertTemp(t); + } +} + +void DS1624Show(bool json) +{ + char temperature[33]; + bool once = true; + + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + + dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, ds1624_sns[i].name, temperature); + if ((0 == tele_period) && once) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, ds1624_sns[i].value); +#endif + once = false; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns59(uint8_t function) +{ + if (!I2cEnabled(XI2C_42)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + if (!ds1624_init) { + memset(ds1624_sns, 0, sizeof(ds1624_sns)); + ds1624_init = true; + DS1624HotPlugScan(); + } + } + switch (function) { + case FUNC_HOTPLUG_SCAN: + DS1624HotPlugScan(); + break; + case FUNC_EVERY_SECOND: + DS1624EverySecond(); + break; + case FUNC_JSON_APPEND: + DS1624Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DS1624Show(0); + break; +#endif + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" +#ifdef USE_GPS +#if defined(ESP32) && defined(USE_FLOG) + #undef USE_FLOG + #warning FLOG deactivated on ESP32 +#endif +# 117 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" +#define XSNS_60 60 + +#include "NTPServer.h" +#include "NTPPacket.h" + + + + + +#define D_CMND_UBX "UBX" + +const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; + +const char kUBXTypes[] PROGMEM = "UBX"; + +#define UBX_LAT_LON_THRESHOLD 1000 + +#define UBX_SERIAL_BUFFER_SIZE 256 +#define UBX_TCP_PORT 1234 +#define NTP_MILLIS_OFFSET 50 + + + + + +const char UBLOX_INIT[] PROGMEM = { + + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, + + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, + + + + + + +}; + +char UBX_name[4]; + +struct UBX_t { + const char UBX_HEADER[2] = { 0xB5, 0x62 }; + const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; + const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; + const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; + + struct entry_t { + int32_t lat; + int32_t lon; + uint32_t time; + }; + + union { + entry_t values; + uint8_t bytes[sizeof(entry_t)]; + } rec_buffer; + + struct POLL_MSG { + uint8_t cls; + uint8_t id; + uint16_t zero; + }; + + struct NAV_POSLLH { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + int32_t lon; + int32_t lat; + int32_t alt; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + }; + + struct NAV_STATUS { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint8_t gpsFix; + uint8_t flags; + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; + }; + + struct NAV_TIME_UTC { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint32_t tAcc; + int32_t nano; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + struct { + uint8_t UTC:1; + uint8_t WKN:1; + uint8_t TOW:1; + uint8_t padding:5; + } valid; + }; + + struct CFG_RATE { + uint8_t cls; + uint8_t id; + uint16_t len; + uint16_t measRate; + uint16_t navRate; + uint16_t timeRef; + char CK[2]; + }; + + struct { + uint32_t last_iTOW; + int32_t last_alt; + uint32_t last_hAcc; + uint32_t last_vAcc; + uint8_t gpsFix; + uint8_t non_empty_loops; + uint16_t log_interval; + int32_t timeOffset; + } state; + + struct { + uint32_t init:1; + uint32_t filter_noise:1; + uint32_t send_when_new:1; + uint32_t send_UI_only:1; + uint32_t runningNTP:1; + + uint32_t forceUTCupdate:1; + uint32_t runningVPort:1; + + } mode; + + union { + NAV_POSLLH navPosllh; + NAV_STATUS navStatus; + NAV_TIME_UTC navTime; + POLL_MSG pollMsg; + CFG_RATE cfgRate; + } Message; + + uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; + size_t TCPbufSize; +} UBX; + +enum UBXMsgType { + MT_NONE, + MT_NAV_POSLLH, + MT_NAV_STATUS, + MT_NAV_TIME, + MT_POLL +}; + +#ifdef USE_FLOG +FLOG *Flog = nullptr; +#endif +TasmotaSerial *UBXSerial; + +NtpServer timeServer(PortUdp); + +WiFiServer vPortServer(UBX_TCP_PORT); +WiFiClient vPortClient; + + + + + +void UBXcalcChecksum(char* CK, size_t msgSize) +{ + memset(CK, 0, 2); + for (int i = 0; i < msgSize; i++) { + CK[0] += ((char*)(&UBX.Message))[i]; + CK[1] += CK[0]; + } +} + +bool UBXcompareMsgHeader(const char* msgHeader) +{ + char* ptr = (char*)(&UBX.Message); + return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; +} + +void UBXinitCFG(void) +{ + for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); +} + +void UBXsendCFGLine(uint8_t _line) +{ + if (_line>sizeof(UBLOX_INIT)/16) return; + for (uint32_t i = 0; i < 16; i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line); +} + +void UBXTriggerTele(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } +} + + + +void UBXDetect(void) +{ + UBX.mode.init = 0; + if (PinUsed(GPIO_GPS_RX) && PinUsed(GPIO_GPS_TX)) { + UBXSerial = new TasmotaSerial(Pin(GPIO_GPS_RX), Pin(GPIO_GPS_TX), 1, 0, UBX_SERIAL_BUFFER_SIZE); + if (UBXSerial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); + } + } + } + else { + return; + } + + UBXinitCFG(); + UBX.mode.init = 1; + +#ifdef USE_FLOG + if (!Flog) { + Flog = new FLOG; + Flog->init(); + } +#endif + + UBX.state.log_interval = 10; + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + +uint32_t UBXprocessGPS() +{ + static uint32_t fpos = 0; + static char checksum[2]; + static uint8_t currentMsgType = MT_NONE; + static size_t payloadSize = sizeof(UBX.Message); + + + uint32_t data_bytes = 0; + while ( UBXSerial->available() ) { + data_bytes++; + byte c = UBXSerial->read(); + if (UBX.mode.runningVPort){ + UBX.TCPbuf[data_bytes-1] = c; + UBX.TCPbufSize = data_bytes; + } + if ( fpos < 2 ) { + + if ( c == UBX.UBX_HEADER[fpos] ) { + fpos++; + } else { + fpos = 0; + } + } else { + + + + + + if ( (fpos-2) < payloadSize ) { + ((char*)(&UBX.Message))[fpos-2] = c; + } + fpos++; + + if ( fpos == 4 ) { + + + if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { + currentMsgType = MT_NAV_POSLLH; + payloadSize = sizeof(UBX_t::NAV_POSLLH); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { + currentMsgType = MT_NAV_STATUS; + payloadSize = sizeof(UBX_t::NAV_STATUS); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { + currentMsgType = MT_NAV_TIME; + payloadSize = sizeof(UBX_t::NAV_TIME_UTC); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); + } + else { + + fpos = 0; + continue; + } + } + + if ( fpos == (payloadSize+2) ) { + + + UBXcalcChecksum(checksum, payloadSize); + } + else if ( fpos == (payloadSize+3) ) { + + + if ( c != checksum[0] ) { + + fpos = 0; + } + } + else if ( fpos == (payloadSize+4) ) { + + + fpos = 0; + if ( c == checksum[1] ) { + + return currentMsgType; + } + } + else if ( fpos > (payloadSize+4) ) { + + + fpos = 0; + } + } + } + + if (data_bytes!=0) { + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + } else { + UBX.state.non_empty_loops = 0; + } + return MT_NONE; +} + + + + + +#ifdef USE_FLOG +void UBXsendHeader(void) +{ + Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); + Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + WSSend(200, CT_STREAM, F( + "\r\n" + "\r\n" + "\r\n\r\n")); +} + +void UBXsendRecord(uint8_t *buf) +{ + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + + Webserver->sendContent_P(record); +} + +void UBXsendFooter(void) +{ + Webserver->sendContent(F("\n\n")); + Webserver->sendContent(""); + Rtc.user_time_entry = false; +} + + + +void UBXsendFile(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); +} +#endif + + + +void UBXSetRate(uint16_t interval) +{ + UBX.Message.cfgRate.cls = 0x06; + UBX.Message.cfgRate.id = 0x08; + UBX.Message.cfgRate.len = 6; + uint32_t measRate = (1000*(uint32_t)interval); + if (measRate > 0xffff) { + measRate = 0xffff; + } + UBX.Message.cfgRate.measRate = (uint16_t)measRate; + UBX.Message.cfgRate.navRate = 1; + UBX.Message.cfgRate.timeRef = 1; + UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); + DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); + UBXSerial->write(UBX.UBX_HEADER[0]); + UBXSerial->write(UBX.UBX_HEADER[1]); + for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); + DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); + } + UBX.state.log_interval = 10*interval; +} + +void UBXSelectMode(uint16_t mode) +{ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ +#ifdef USE_FLOG + case 0: + Flog->mode = 0; + break; + case 1: + Flog->mode = 1; + break; + case 2: + UBX.mode.filter_noise = true; + break; + case 3: + UBX.mode.filter_noise = false; + break; + case 4: + Flog->startRecording(true); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; + case 5: + Flog->startRecording(false); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; + case 6: + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; +#endif + case 7: + UBX.mode.send_when_new = 1; + break; + case 8: + UBX.mode.send_when_new = 0; + break; + case 9: + if (timeServer.beginListening()) { + UBX.mode.runningNTP = true; + } + break; + case 10: + UBX.mode.runningNTP = false; + UBXsendCFGLine(10); + UBXsendCFGLine(11); + break; + case 11: + UBX.mode.forceUTCupdate = true; + break; + case 12: + UBX.mode.forceUTCupdate = false; + break; + case 13: + Settings.latitude = UBX.rec_buffer.values.lat/10; + Settings.longitude = UBX.rec_buffer.values.lon/10; + break; + case 14: + vPortServer.begin(); + UBX.mode.runningVPort = 1; + break; + case 15: + + UBX.mode.runningVPort = 0; + break; + default: + if (mode>1000 && mode <1066) { + UBXSetRate(mode-1000); + } + break; + } + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + + + +bool UBXHandlePOSLLH() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); + if (UBX.state.gpsFix>1) { + if (UBX.mode.filter_noise) { + if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { + if(UBX.mode.runningVPort) return; + UBXinitCFG(); + AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); + UBXSerial->flush(); + UBX.state.non_empty_loops = 0; + } +} + + + +void UBXLoop50msec(void) +{ + + if (UBX.mode.runningVPort){ + if(!vPortClient.connected()) { + vPortClient = vPortServer.available(); + } + while(vPortClient.available()) { + byte _newByte = vPortClient.read(); + UBXSerial->write(_newByte); + } + + if (UBX.TCPbufSize!=0){ + vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); + UBX.TCPbufSize = 0; + } + } + + if(UBX.mode.runningNTP){ + timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET); + } +} + +void UBXLoop(void) +{ + static uint16_t counter; + static bool new_position; + + uint32_t msgType = UBXprocessGPS(); + + switch(msgType){ + case MT_NAV_POSLLH: + new_position = UBXHandlePOSLLH(); + break; + case MT_NAV_STATUS: + UBXHandleSTATUS(); + break; + case MT_NAV_TIME: + UBXHandleTIME(); + break; + default: + UBXHandleOther(); + break; + } + +#ifdef USE_FLOG + if (counter>UBX.state.log_interval) { + if (Flog->recording && new_position) { + UBX.rec_buffer.values.time = Rtc.local_time; + Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); + counter = 0; + } + } +#endif + + counter++; +} + + + + +#ifdef USE_WEBSERVER + + +#ifdef USE_FLOG +#ifdef DEBUG_TASMOTA_SENSOR + const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" + "{s} FLOG next sector for REC: {m} %u {e}" + "{s} %u sector(s) with data at sector: {m} %u {e}"; + const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; +#endif + + const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; + const char kFLOG_STATE0[] PROGMEM = "ready"; + const char kFLOG_STATE1[] PROGMEM = "recording"; + const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; + + const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; + +#endif + const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; + + const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" + "{s} GPS longitude {m}%s{e}" + "{s} GPS altitude {m}%s m{e}" + "{s} GPS hor. Accuracy {m}%s m{e}" + "{s} GPS vert. Accuracy {m}%s m{e}" + "{s} GPS sat-fix status {m}%s{e}"; + + const char kGPSFix0[] PROGMEM = "no fix"; + const char kGPSFix1[] PROGMEM = "dead reckoning only"; + const char kGPSFix2[] PROGMEM = "2D-fix"; + const char kGPSFix3[] PROGMEM = "3D-fix"; + const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; + const char kGPSFix5[] PROGMEM = "Time only fix"; + const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; + + + + +#endif + + + +void UBXShow(bool json) +{ + char lat[12]; + char lon[12]; + char alt[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + + if (json) { + ResponseAppend_P(PSTR(",\"GPS\":{")); + if (UBX.mode.send_UI_only) { + uint32_t i = UBX.state.log_interval / 10; + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); + } else { + ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); + } +#ifdef USE_FLOG + ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); +#endif + UBX.mode.send_UI_only = false; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); + +#ifdef DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); + if (Flog->recording) { + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + } +#endif +#endif +#ifdef USE_FLOG + if (Flog->ready) { + WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); + } + if (!Flog->recording && Flog->found_saved_data) { + WSContentSend_P(HTTP_BTN_FLOG_DL); + } +#endif + if (UBX.mode.runningNTP) { + WSContentSend_P(HTTP_SNS_NTPSERVER); + } +#endif + } +} + + + + + +bool UBXCmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; +} + + + + + +bool Xsns60(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + UBXDetect(); + } + + if (UBX.mode.init) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_60 == XdrvMailbox.index) { + result = UBXCmd(); + } + break; + case FUNC_EVERY_50_MSECOND: + UBXLoop50msec(); + break; + case FUNC_EVERY_100_MSECOND: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXLoop(); + } + break; +#ifdef USE_FLOG + case FUNC_WEB_ADD_HANDLER: + WebServer_on(PSTR("/UBX"), UBXsendFile); + break; +#endif + case FUNC_JSON_APPEND: + UBXShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXShow(0); + } + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +# 55 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 +#ifdef USE_MIBLE + +#ifdef DEBUG_TASMOTA_SENSOR + #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); +#else + #define MINRF_LOG_BUFFER(x) +#endif + +#define USE_MI_DECRYPTION + + + + + + + +#define XSNS_61 61 + +#include +#ifdef USE_MI_DECRYPTION +#include +#endif + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03 4 +#define CGG1 5 +#define CGD1 6 +#define NLIGHT 7 +#define MJYD2S 8 +#define YEERC 9 +#define MHOC401 10 +#define MHOC303 11 +#define ATC 12 + +#define MI_TYPES 12 + +#define D_CMND_NRF "NRF" + +const char S_JSON_NRF_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NRF "%s\":%d}"; +const char S_JSON_NRF_COMMAND[] PROGMEM = "{\"" D_CMND_NRF "%s\":\"%s\"}"; +const char kNRF_Commands[] PROGMEM = "Ignore|Use|Page|Scan|Beacon|Chan|Nlight" +#ifdef USE_MI_DECRYPTION + "|Mjyd2s" + "|Key" +#endif + ; + +enum NRF_Commands { + CMND_NRF_IGNORE, + CMND_NRF_USE, + CMND_NRF_PAGE, + CMND_NRF_SCAN, + CMND_NRF_BEACON, + CMND_NRF_CHAN, + CMND_NRF_NLIGHT +#ifdef USE_MI_DECRYPTION + , CMND_NRF_MJYD2S + , CMND_NRF_KEY +#endif + }; + +const uint16_t kMINRFDeviceID[MI_TYPES]={ 0x0098, + 0x01aa, + 0x045b, + 0x055b, + 0x0347, + 0x0576, + 0x03dd, + 0x07f6, + 0x0153, + 0x0387, + 0x06d3, + 0x0a1c + }; + +const char kMINRFDeviceType1[] PROGMEM = "Flora"; +const char kMINRFDeviceType2[] PROGMEM = "MJ_HT_V1"; +const char kMINRFDeviceType3[] PROGMEM = "LYWSD02"; +const char kMINRFDeviceType4[] PROGMEM = "LYWSD03"; +const char kMINRFDeviceType5[] PROGMEM = "CGG1"; +const char kMINRFDeviceType6[] PROGMEM = "CGD1"; +const char kMINRFDeviceType7[] PROGMEM = "NLIGHT"; +const char kMINRFDeviceType8[] PROGMEM = "MJYD2S"; +const char kMINRFDeviceType9[] PROGMEM = "YEERC"; +const char kMINRFDeviceType10[] PROGMEM = "MHOC401"; +const char kMINRFDeviceType11[] PROGMEM = "MHOC303"; +const char kMINRFDeviceType12[] PROGMEM = "ATC"; +const char * kMINRFDeviceType[] PROGMEM = {kMINRFDeviceType1,kMINRFDeviceType2,kMINRFDeviceType3,kMINRFDeviceType4,kMINRFDeviceType5,kMINRFDeviceType6,kMINRFDeviceType7,kMINRFDeviceType8,kMINRFDeviceType9,kMINRFDeviceType10,kMINRFDeviceType11,kMINRFDeviceType12}; + + +const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; +const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; +const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46}; +const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0x33049deb}; + +const uint32_t kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; +const uint32_t kMINRFCGDPDU[3] = {0x5da0d752,0xc10c16e7,0x29c497c1}; + +const uint32_t kMINRFYRCPDU[3] = {0x216D63E2,0x5C3DD47E,0x0A5D0E96}; +const uint32_t kMINRFATCPDU[3] = {0xA6E4D00A,0xD0CDAD5A,0x8B03FB3A}; + + +const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; +const uint8_t kMINRFlsfrList_C[3] = {0x38,0x25,0x2e}; +const uint8_t kMINRFlsfrList_D[3] = {0x26,0x23,0x20}; + + +#pragma pack(1) +struct mi_beacon_t{ + uint16_t PID; + uint8_t counter; + uint8_t MAC[6]; + uint8_t spare; + uint8_t type; + uint8_t ten; + uint8_t size; + union { + struct{ + int16_t temp; + uint16_t hum; + }HT; + uint8_t bat; + uint16_t temp; + uint16_t hum; + uint32_t lux:24; + uint8_t moist; + uint16_t fert; + struct{ + uint16_t num; + uint8_t longPress; + }Btn; + }; +}; + +struct CGDPacket_t { + uint8_t MAC[6]; + uint16_t mode; + union { + struct { + int16_t temp; + uint16_t hum; + }; + uint8_t bat; + }; +}; + +struct bleAdvPacket_t { + uint8_t pduType; + uint8_t payloadSize; + uint8_t MAC[6]; +}; + +#ifdef USE_MI_DECRYPTION +struct encPayload_t { + uint8_t cipher[5]; + uint8_t ExtCnt[3]; + uint8_t tag[4]; +}; + +struct encPacket_t{ + + uint16_t PID; + uint8_t frameCnt; + uint8_t MAC[6]; + encPayload_t payload; +}; + +struct mjysd02_Packet_t{ + uint8_t padding[11]; + uint8_t payloadSize; + uint8_t padding3; + uint16_t UUID; + uint16_t frameCtrl; + uint16_t PID; + uint8_t frameCnt; + uint8_t data[18]; +}; + +struct ATCPacket_t{ + uint8_t MAC[6]; + int16_t temp; + uint8_t hum; + uint8_t batPer; + uint16_t batMV; + uint8_t frameCnt; +}; + +union mi_bindKey_t{ + struct{ + uint8_t key[16]; + uint8_t MAC[6]; + }; + uint8_t buf[22]; +}; +#endif +union FIFO_t{ + bleAdvPacket_t bleAdv; + mi_beacon_t miBeacon; + CGDPacket_t CGDPacket; + uint8_t raw[32]; +}; + +#pragma pack(0) + +struct { + const uint8_t channel[3] = {37,38,39}; + const uint8_t frequency[3] = { 2,26,80}; + + uint16_t timer; + uint16_t ignore = 0; + uint8_t currentChan=0; + uint8_t channelIgnore = 0; + uint8_t confirmedSensors = 0; + uint8_t packetMode; + uint8_t perPage = 4; + uint8_t firstUsedPacketMode = 1; + uint8_t activeLight = 0; + + FIFO_t buffer; + + struct { + uint8_t MAC[6]; + uint32_t time; + uint32_t PDU[3]; + bool active = false; + } beacon; + + struct { + uint32_t allwaysAggregate:1; + + uint32_t noSummary:1; + uint32_t minimalSummary:1; + uint32_t directBridgeMode:1; + } option; + + struct { + uint32_t shallTriggerTele:1; + uint32_t triggeredTele:1; + uint32_t activeScan:1; + uint32_t stopScan:1; + + } mode; + + + + + +#ifdef DEBUG_TASMOTA_SENSOR + uint8_t streamBuffer[sizeof(buffer)]; + uint8_t lsfrBuffer[sizeof(buffer)]; +#endif +} MINRF; + +struct mi_sensor_t{ + uint8_t type; + uint8_t lastCnt; + uint8_t shallSendMQTT; + uint8_t showedUp; + uint8_t MAC[6]; + + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t PIR:1; + uint32_t Btn:1; + }; + uint32_t raw; + } feature; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t motion:1; + uint32_t noMotion:1; + uint32_t Btn:1; + }; + uint32_t raw; + } eventType; + + uint32_t lastTime; + uint32_t lux; + float temp; + union { + struct { + uint8_t moisture; + uint16_t fertility; + }; + struct { + float hum; + }; + struct { + uint16_t events; + uint32_t NMT; + }; + uint16_t Btn; + }; + union { + uint8_t bat; + }; +}; + +struct mi_light_t{ + uint8_t MAC[6]; + uint32_t PDU[3]; + uint8_t type; + uint8_t bat; + struct { + uint16_t events; + uint8_t lastCnt; + uint8_t shallSendMQTT; + }; + uint32_t NMT; + uint32_t lastTime; + uint8_t lux; + uint8_t eventType; +}; + +struct scan_entry_t { + uint8_t MAC[6]; + uint16_t cid; + uint16_t svc; + uint16_t uuid; + uint8_t showedUp; +}; + +std::vector MIBLEsensors; +std::vector MINRFscanResult; +#ifdef USE_MI_DECRYPTION +std::vector MIBLEbindKeys; +#endif +std::vector MIBLElights; + +static union{ + scan_entry_t MINRFdummyEntry; + uint8_t MINRFtempBuf[23]; +}; + + + +void MINRFinit(void){ + MINRFinitBLE(1); + + MINRF.option.allwaysAggregate = 1; + + MINRF.option.noSummary = 0; + MINRF.option.minimalSummary = 0; + MINRF.option.directBridgeMode = 0; +} +# 431 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +bool MINRFinitBLE(uint8_t _mode) +{ + if (MINRF.timer%1000 == 0){ + NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); + NRF24radio.setAutoAck(false); + NRF24radio.setDataRate(RF24_1MBPS); + NRF24radio.disableCRC(); + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); + NRF24radio.setRetries(0,0); + NRF24radio.setPALevel(RF24_PA_MIN); + NRF24radio.setAddressWidth(4); + + + NRF24radio.powerUp(); + } + if(NRF24radio.isChipConnected()){ + + MINRFchangePacketModeTo(_mode); + return true; + } + + return false; +} + + + + + +void MINRFhopChannel() +{ + for (uint32_t i = 0; i<3;i++){ + MINRF.currentChan++; + if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue; + if(MINRF.currentChan >= sizeof(MINRF.channel)) { + MINRF.currentChan = 0; + if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue; + } + break; + } + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); +} + + + + + + + +bool MINRFreceivePacket(void) +{ + if(!NRF24radio.available()) { + return false; + } + while(NRF24radio.available()) { + + + NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); +#ifdef DEBUG_TASMOTA_SENSOR + memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); +#endif + MINRFswapbuf((uint8_t*)&MINRF.buffer, sizeof(MINRF.buffer) ); + + + + switch (MINRF.packetMode) { + case 0: case NLIGHT: case MJYD2S: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); + break; + case FLORA: case LYWSD02: case MHOC303: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); + break; + case MJ_HT_V1: case LYWSD03: case CGG1: case CGD1: case MHOC401: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + case YEERC: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_C[MINRF.currentChan]); + break; + case ATC: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_D[MINRF.currentChan]); + break; + } + + + } + + return true; +} + + +void MINRFshowBuffer(uint8_t (&buf)[32]){ + + + + + DEBUG_SENSOR_LOG(PSTR("NRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x ") + ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], + buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], + buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] + ); +} + + + + + + + +void MINRFswapbuf(uint8_t *buf, uint8_t len) +{ + + while(len--) { + uint8_t a = *buf; + uint8_t v = 0; + if (a & 0x80) v |= 0x01; + if (a & 0x40) v |= 0x02; + if (a & 0x20) v |= 0x04; + if (a & 0x10) v |= 0x08; + if (a & 0x08) v |= 0x10; + if (a & 0x04) v |= 0x20; + if (a & 0x02) v |= 0x40; + if (a & 0x01) v |= 0x80; + *(buf++) = v; + } +} +# 566 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) +{ + while(len--) { + uint8_t res = 0; + + for (uint8_t i = 1; i; i <<= 1) { + if (lfsr & 0x01) { + lfsr ^= 0x88; + res |= i; + } + lfsr >>= 1; + } + *(buf++) ^= res; +#ifdef DEBUG_TASMOTA_SENSOR + MINRF.lsfrBuffer[31-len] = lfsr; +#endif + } +} + + + + +bool MINRFhandleBeacon(scan_entry_t * entry, uint32_t offset); + + + + + +void MINRFhandleScan(void){ + if(MINRFscanResult.size()>20 || MINRF.mode.stopScan) { + MINRF.mode.activeScan=false; + MINRFcomputefirstUsedPacketMode(); + uint32_t i = 0; + MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(), + MINRFscanResult.end(), + [&i](scan_entry_t e) { + if(e.showedUp>2) AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF: Beacon %02u: %02X%02X%02X%02X%02X%02X Cid: %04X Svc: %04X UUID: %04X"),i,e.MAC[0],e.MAC[1],e.MAC[2],e.MAC[3],e.MAC[4],e.MAC[5],e.cid,e.svc,e.uuid); + i++; + return ((e.showedUp < 3)); + }), + MINRFscanResult.end()); + MINRF.mode.stopScan=false; + return; + } + + MINRFreverseMAC(MINRF.buffer.bleAdv.MAC); + for(uint32_t i=0; i30) break; + uint32_t ADtype = _buf[i+1]; + + if (size+i>32+offset) size=32-i+offset-2; + if (size>30) break; + char _stemp[(size*2)]; + uint32_t backupSize; + switch(ADtype){ + case 0x01: + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Flags: %02x"), _buf[i+2]); + break; + case 0x02: case 0x03: + entry->uuid = _buf[i+3]*256 + _buf[i+2]; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: UUID: %04x"), entry->uuid); + success = true; + break; + case 0x08: case 0x09: + backupSize = _buf[i+size+1]; + _buf[i+size+1] = 0; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Name: %s"), (char*)&_buf[i+2]); + success = true; + _buf[i+size+1] = backupSize; + break; + case 0x0a: + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: TxPow: %02u"), _buf[i+2]); + break; + case 0xff: + entry->cid = _buf[i+3]*256 + _buf[i+2]; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Cid: %04x"), entry->cid); + ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2)); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); + success = true; + break; + case 0x16: + entry->svc = _buf[i+3]*256 + _buf[i+2]; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Svc: %04x"), entry->svc); + ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2)); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); + success = true; + break; + default: + ToHex_P((unsigned char*)&_buf+i+2,size-1,_stemp,(size*2)); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); + } + i+=size; + } + MINRF.beacon.time = 0; + } + return success; +} + + + + + +void MINRFbeaconCounter(void) { + if (MINRF.beacon.active) { + MINRF.beacon.time++; + + + + + + + Response_P(PSTR("{%s:{\"Beacon\":%u}}"), D_CMND_NRF, MINRF.beacon.time); + XdrvRulesProcess(); + } +} + + + + + +void MINRFcomputeBeaconPDU(uint8_t (&_MAC)[6], uint32_t (&PDU)[3], uint32_t offset){ + uint32_t _PDU[3]; + for (uint32_t i = 0; i<3; i++){ + bleAdvPacket_t packet; + memcpy((uint8_t *)&packet.MAC, (uint8_t *)&_MAC, sizeof(packet.MAC)); + MINRFreverseMAC(packet.MAC); + MINRFwhiten((uint8_t *)&packet, sizeof(packet), MINRF.channel[i] | 0x40); + MINRFswapbuf((uint8_t*)&packet,sizeof(packet)); + uint32_t pdu = packet.MAC[0+offset]<<24 | packet.MAC[1+offset]<<16 | packet.MAC[2+offset]<<8 | packet.MAC[3+offset]; + _PDU[i] = pdu; + } + memcpy(PDU,_PDU,sizeof(_PDU)); +} + +#ifdef USE_MI_DECRYPTION +int MINRFdecryptPacket(char *_buf){ + encPacket_t *packet = (encPacket_t*)_buf; + + + + + int ret = 0; + unsigned char output[16] = {0}; + uint8_t nonce[12]; + const unsigned char authData[1] = {0x11}; + + + for (uint32_t i = 0; i<6; i++){ + nonce[i] = packet->MAC[5-i]; + } + memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); + nonce[8] = packet->frameCnt; + memcpy((uint8_t*)&nonce+9,(uint8_t*)&packet->payload.ExtCnt,3); + + uint8_t _bindkey[16] = {0x0}; + for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ + + memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); + break; + } + + + + + } + + memcpy(output,packet->payload.cipher, sizeof(packet->payload.cipher)); + + br_aes_small_ctrcbc_keys keyCtx; + br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); + + br_ccm_context ctx; + br_ccm_init(&ctx, &keyCtx.vtable); + br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData),sizeof(packet->payload.cipher),sizeof(packet->payload.tag)); + br_ccm_aad_inject(&ctx, authData, sizeof(authData)); + br_ccm_flip(&ctx); + br_ccm_run(&ctx, 0, output, sizeof(packet->payload.cipher)); + + ret = br_ccm_check_tag(&ctx, packet->payload.tag); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, output[0],output[1],output[2],output[3],output[4]); + memcpy((uint8_t*)(packet->payload.cipher)+1,output,sizeof(packet->payload.cipher)); + return ret; +} + +int MINRFdecryptMJYD2SPacket(char *_buf, uint8_t _light, char* _output){ + int ret = 0; + uint8_t nonce[12]; + const unsigned char authData[1] = {0x11}; + uint8_t tag[4]; + mjysd02_Packet_t *packet = (mjysd02_Packet_t*)_buf; + + + for (uint32_t i = 0; i<6; i++){ + nonce[i] = MIBLElights[_light-1].MAC[5-i]; + } + memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); + nonce[8] = packet->frameCnt; + memcpy((uint8_t*)&nonce+9,(uint8_t*)&packet->padding[0] + packet->payloadSize + 5, 3); + + + uint8_t _bindkey[16]; + for(uint32_t i=0; ipayloadSize){ + case 22: + _size = 7; + _offset = 2; + _tagSize = 4; + break; + case 25: + _size = packet->payloadSize - 21; + _offset = -1; + _tagSize = 4; + break; + case 27: + _size = packet->payloadSize - 21; + _offset = 1; + _tagSize = 3; + break; + default: + return 0; + break; + } + + memcpy(_output,(uint8_t*)&packet->padding[0] + packet->payloadSize - _offset, _size); + + + br_aes_small_ctrcbc_keys keyCtx; + br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); + + br_ccm_context ctx; + br_ccm_init(&ctx, &keyCtx.vtable); + br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData),_size,4); + br_ccm_aad_inject(&ctx, authData, sizeof(authData)); + br_ccm_flip(&ctx); + br_ccm_run(&ctx, 0, _output, _size); + + + br_ccm_get_tag(&ctx, tag); + ret = memcmp(tag,(uint8_t*)&packet->padding[0] + packet->payloadSize + 8, _tagSize); + return ret; +} +#endif +# 891 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +void MINRFreverseMAC(uint8_t _MAC[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _MAC[i]; + } + memcpy(_MAC,_reversedMAC, sizeof(_reversedMAC)); +} +#ifdef USE_MI_DECRYPTION +void MINRFAddKey(char* payload){ + mi_bindKey_t keyMAC; + memset(keyMAC.buf,0,sizeof(keyMAC)); + MINRFKeyMACStringToBytes(payload,keyMAC.buf); + bool unknownKey = true; + for(uint32_t i=0; i= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _keyMAC[(index/2)] += value << (((index + 1) % 2) * 4); + index++; + } + DEBUG_SENSOR_LOG(PSTR("NRF: %s to:"),_string); + DEBUG_SENSOR_LOG(PSTR("NRF: key-array: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"),_keyMAC[0],_keyMAC[1],_keyMAC[2],_keyMAC[3],_keyMAC[4],_keyMAC[5],_keyMAC[6],_keyMAC[7],_keyMAC[8],_keyMAC[9],_keyMAC[10],_keyMAC[11],_keyMAC[12],_keyMAC[13],_keyMAC[14],_keyMAC[15]); + DEBUG_SENSOR_LOG(PSTR("NRF: MAC-array: %02X%02X%02X%02X%02X%02X"),_keyMAC[16],_keyMAC[17],_keyMAC[18],_keyMAC[19],_keyMAC[20],_keyMAC[21]); +} +#endif + + + + + + +void MINRFMACStringToBytes(char* _string, uint8_t _MAC[]) { + uint32_t index = 0; + UpperCase(_string,_string); + while (index < 12) { + char c = _string[index]; + uint8_t value = 0; + if(c >= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _MAC[(index/2)] += value << (((index + 1) % 2) * 4); + index++; + } + +} + + + + + +void MINRFcomputefirstUsedPacketMode(void){ + for (uint32_t i = 0; iMI_TYPES) MINRF.firstUsedPacketMode=0; + break; + } + } +} +# 985 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +void MINRFrecalcBuffer(uint8_t *_buf, uint32_t offset){ + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); + MINRFswapbuf((uint8_t*)&MINRF.buffer,sizeof(MINRF.buffer)); + memcpy(_buf+offset,MINRF.buffer.raw,32); + MINRFswapbuf(_buf,32+offset); + MINRFwhiten(_buf, 32+offset, MINRF.channel[MINRF.currentChan] | 0x40); +} + + + + + + +void MINRFchangePacketModeTo(uint8_t _mode) { + uint32_t (_nextchannel) = MINRF.currentChan+1; + if (_nextchannel>2) _nextchannel=0; + + switch(_mode){ + case 0: + NRF24radio.openReadingPipe(0,0x6B7D9171); + break; + case FLORA: + NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); + break; + case MJ_HT_V1: + NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); + break; + case LYWSD02: case MHOC303: + NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); + break; + case LYWSD03: case MHOC401: + NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); + break; + case CGG1: + NRF24radio.openReadingPipe(0,kMINRFCGGPDU[_nextchannel]); + break; + case CGD1: + NRF24radio.openReadingPipe(0,kMINRFCGDPDU[_nextchannel]); + break; + case NLIGHT: case MJYD2S: + if (MIBLElights.size()==0) break; + NRF24radio.openReadingPipe(0,MIBLElights[MINRF.activeLight].PDU[_nextchannel]); + MINRF.activeLight++; + break; + case YEERC: + NRF24radio.openReadingPipe(0,kMINRFYRCPDU[_nextchannel]); + break; + case ATC: + NRF24radio.openReadingPipe(0,kMINRFATCPDU[_nextchannel]); + break; + } + + MINRF.packetMode = _mode; +} +# 1047 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +uint32_t MINRFgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type){ + + DEBUG_SENSOR_LOG(PSTR("NRF: will test ID-type: %x"), _type); + bool _success = false; + for (uint32_t i=0;i 2){ + MINRF.confirmedSensors++; + } + } +} + + + + + +void MINRFtriggerTele(void){ + MINRF.mode.triggeredTele= true; + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + #ifdef USE_RULES + RulesTeleperiod(); + #endif + } +} + + + + + +void MINRFhandleMiBeaconPacket(void){ + MINRFreverseMAC(MINRF.buffer.miBeacon.MAC); + uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.MAC, MINRF.buffer.miBeacon.PID); + if(_slot==0xff) return; + DEBUG_SENSOR_LOG(PSTR("NRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size()); + mi_sensor_t *_sensorVec = &MIBLEsensors[_slot]; + DEBUG_SENSOR_LOG(PSTR("NRF: %u %u %u"),_slot,_sensorVec->type,MINRF.buffer.miBeacon.type); + float _tempFloat; + int decryptRet; + + switch(_sensorVec->type){ + case MJ_HT_V1: case CGG1: case YEERC: + memcpy(MINRFtempBuf,(uint8_t*)&MINRF.buffer.miBeacon.spare, 32-9); + memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); + break; +#ifdef USE_MI_DECRYPTION + case LYWSD03: case MHOC401: + decryptRet = MINRFdecryptPacket((char*)&MINRF.buffer); + if(decryptRet==1) _sensorVec->showedUp=255; + break; +#endif + } + + DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kNRFSlaveType[_sensorVec->type-1],_slot); + switch(MINRF.buffer.miBeacon.type){ + case 0x1: + if(MINRF.buffer.miBeacon.counter==_sensorVec->lastCnt) break; + + _sensorVec->lastCnt=MINRF.buffer.miBeacon.counter; + _sensorVec->Btn=MINRF.buffer.miBeacon.Btn.num + (MINRF.buffer.miBeacon.Btn.longPress/2)*6; + _sensorVec->eventType.Btn = 1; + break; + case 0x04: + _tempFloat=(float)(MINRF.buffer.miBeacon.temp)/10.0f; + if(_tempFloat<60){ + _sensorVec->temp=_tempFloat; + _sensorVec->eventType.temp = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), MINRF.buffer.miBeacon.temp ); + break; + case 0x06: + _tempFloat=(float)(MINRF.buffer.miBeacon.hum)/10.0f; + if(_tempFloat<101){ + _sensorVec->hum=_tempFloat; + _sensorVec->eventType.hum = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), MINRF.buffer.miBeacon.hum); + break; + case 0x07: + _sensorVec->lux=MINRF.buffer.miBeacon.lux & 0x00ffffff; + _sensorVec->eventType.lux = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), MINRF.buffer.miBeacon.lux & 0x00ffffff); + break; + case 0x08: + _tempFloat =(float)MINRF.buffer.miBeacon.moist; + if(_tempFloat<100){ + _sensorVec->moisture=_tempFloat; + _sensorVec->eventType.moist = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), MINRF.buffer.miBeacon.moist); + break; + case 0x09: + _tempFloat=(float)(MINRF.buffer.miBeacon.fert); + if(_tempFloat<65535){ + _sensorVec->fertility=_tempFloat; + _sensorVec->eventType.fert = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), MINRF.buffer.miBeacon.fert); + break; + case 0x0a: + if(MINRF.buffer.miBeacon.bat<101){ + _sensorVec->bat = MINRF.buffer.miBeacon.bat; + _sensorVec->eventType.bat = 1; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), MINRF.buffer.miBeacon.bat); + break; + case 0x0d: + _tempFloat=(float)(MINRF.buffer.miBeacon.HT.temp)/10.0f; + if(_tempFloat<60){ + _sensorVec->temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); + } + _tempFloat=(float)(MINRF.buffer.miBeacon.HT.hum)/10.0f; + if(_tempFloat<100){ + _sensorVec->hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); + } + _sensorVec->eventType.tempHum = 1; + DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), MINRF.buffer.miBeacon.HT.temp, MINRF.buffer.miBeacon.HT.hum); + break; + } + if(MIBLEsensors[_slot].eventType.raw == 0) return; + MIBLEsensors[_slot].shallSendMQTT = 1; + if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; +} + + + + + +void MINRFhandleCGD1Packet(void){ + MINRFreverseMAC(MINRF.buffer.CGDPacket.MAC); + uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.CGDPacket.MAC, 0x0576); + DEBUG_SENSOR_LOG(PSTR("NRF: Sensor slot: %u"), _slot); + if(_slot==0xff) return; + + switch (MINRF.buffer.CGDPacket.mode){ + case 0x0401: + float _tempFloat; + _tempFloat=(float)(MINRF.buffer.CGDPacket.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); + } + _tempFloat=(float)(MINRF.buffer.CGDPacket.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), MINRF.buffer.CGDPacket.temp, MINRF.buffer.CGDPacket.hum); + MIBLEsensors[_slot].eventType.tempHum = 1; + break; + case 0x0102: + if(MINRF.buffer.CGDPacket.bat<101){ + MIBLEsensors[_slot].bat = MINRF.buffer.CGDPacket.bat; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + } + MIBLEsensors[_slot].eventType.bat = 1; + break; + default: + DEBUG_SENSOR_LOG(PSTR("NRF: unexpected CGD1-packet")); + MINRF_LOG_BUFFER(MINRF.buffer.raw); + } + if(MIBLEsensors[_slot].eventType.raw == 0) return; + MIBLEsensors[_slot].shallSendMQTT = 1; + if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; +} + +void MINRFhandleNlightPacket(void){ + uint32_t offset = 6; + uint8_t _buf[32+offset]; + MINRFrecalcBuffer((uint8_t*)&_buf,offset); + + uint32_t _frame_PID = _buf[15]<<24 | _buf[16]<<16 | _buf[17]<<8 | _buf[18]; + if(_frame_PID!=0x4030dd03) return; + + uint32_t _idx = MINRF.activeLight-1; + if((millis() - MIBLElights[_idx].lastTime)<1500) return; + if(_buf[19]!=MIBLElights[_idx].lastCnt){ + MIBLElights[_idx].lastCnt = _buf[19]; + MIBLElights[_idx].events++; + MIBLElights[_idx].shallSendMQTT = 1; + MIBLElights[_idx].lastTime = millis(); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: NLIGHT %u: events: %u, Cnt:%u"), _idx,MIBLElights[_idx].events, MIBLElights[_idx].lastCnt); + } +} + +void MINRFhandleMJYD2SPacket(void){ + uint32_t offset = 8; + uint8_t _buf[32+offset]; + MINRFrecalcBuffer((uint8_t*)&_buf,offset); + mjysd02_Packet_t *_packet = (mjysd02_Packet_t*)&_buf; + if(_packet->PID!=0x07f6) return; + + + uint32_t _idx = MINRF.activeLight-1; + switch(_packet->frameCtrl){ + case 0x5910: + if(_packet->frameCnt!=MIBLElights[_idx].lastCnt){ + + MIBLElights[_idx].lastCnt = _packet->frameCnt; + if(millis()-MIBLElights[_idx].lastTime>120000){ + MIBLElights[_idx].eventType = 1; + MIBLElights[_idx].events++; + MIBLElights[_idx].shallSendMQTT = 1; + MIBLElights[_idx].lastTime = millis(); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: MJYD2S secondary PIR")); + } + } + break; + case 0x5948: case 0x5958: + uint8_t output[16]; + if(_packet->frameCnt==MIBLElights[_idx].lastCnt) break; + int32_t ret = MINRFdecryptMJYD2SPacket((char*)&_buf, MINRF.activeLight,(char*)&output); + if(ret==0){ + MIBLElights[_idx].lastCnt = _packet->frameCnt; + switch(output[0]){ + case 0x0f: + if(output[1] == 0){ + if(millis()-MIBLElights[_idx].lastTime>1000){ + MIBLElights[_idx].eventType = 1; + MIBLElights[_idx].shallSendMQTT = 1; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: MJYD2S primary PIR")); + MIBLElights[_idx].events++; + } + MIBLElights[_idx].lastTime = millis(); + MIBLElights[_idx].lux = output[3]; + } + break; + case 0x07: + if(output[1] == 0x10){ + MIBLElights[_idx].eventType = 2; + MIBLElights[_idx].lux = output[3]; + MIBLElights[_idx].shallSendMQTT = 1; + } + break; + case 0x0a: + MIBLElights[_idx].bat = output[3]; + break; + case 0x17: + MIBLElights[_idx].NMT = output[6]<<24 | output[5]<<16 | output[4]<<8 | output[3]; + MIBLElights[_idx].eventType = 3; + MIBLElights[_idx].shallSendMQTT = 1; + + break; + } + } + } + +} + + +void MINRFhandleLightPacket(void){ + switch(MIBLElights[MINRF.activeLight-1].type){ + case NLIGHT: + + MINRFhandleNlightPacket(); + break; + case MJYD2S: + + MINRFhandleMJYD2SPacket(); + break; + } + if(MIBLElights[MINRF.activeLight-1].shallSendMQTT==1) MINRFtriggerTele(); +} + +void MINRFaddLight(uint8_t _MAC[], uint8_t _type){ + for(uint32_t i=0; iMAC, 0x0a1c); + + + if(_slot==0xff) return; + + MIBLEsensors[_slot].temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; + MIBLEsensors[_slot].hum = (float)_packet->hum; + MIBLEsensors[_slot].bat = _packet->batPer; + MIBLEsensors[_slot].eventType.tempHum = 1; + MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; +} + + + + + +void MINRF_EVERY_50_MSECOND() { + + if(MINRF.timer>6000){ + DEBUG_SENSOR_LOG(PSTR("NRF: check for FAKE sensors")); + MINRFpurgeFakeSensors(); + MINRF.timer=0; + } + MINRF.timer++; + + if (!MINRFreceivePacket()){ + if(MINRF.mode.shallTriggerTele){ + MINRFtriggerTele(); + MINRF.mode.shallTriggerTele = 0; + } + + + } + + else { + switch (MINRF.packetMode) { + case 0: + if (MINRF.beacon.active){ + MINRFhandleBeacon(&MINRFdummyEntry,6); + } + else MINRFhandleScan(); + break; + case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03: case YEERC: case MHOC401: case MHOC303: + MINRFhandleMiBeaconPacket(); + break; + case CGD1: + MINRFhandleCGD1Packet(); + break; + case NLIGHT: + MINRFhandleLightPacket(); + break; + case ATC: + MINRFhandleATCPacket(); + break; + default: + break; + } + } + if (MINRF.beacon.active || MINRF.mode.activeScan) { + MINRF.firstUsedPacketMode=0; + } + + if(MINRF.packetMode==NLIGHT){ + if(MINRF.activeLight+1>MIBLElights.size()){ + MINRF.activeLight=0; + MINRF.packetMode+=2; + } + else MINRF.packetMode+=2; + } + else{ + MINRF.packetMode = (MINRF.packetMode+1>MI_TYPES) ? MINRF.firstUsedPacketMode : MINRF.packetMode+1; + for (uint32_t i = MINRF.packetMode; i 0) { + if (XdrvMailbox.payload == 0) XdrvMailbox.payload = MINRF.perPage; + MINRF.perPage = XdrvMailbox.payload; + } + else XdrvMailbox.payload = MINRF.perPage; + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_NRF_IGNORE: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload == 0){ + MINRF.ignore = 0; + MINRF.firstUsedPacketMode = 1; + } + else if (XdrvMailbox.payload < MI_TYPES+1) { + bitSet(MINRF.ignore,XdrvMailbox.payload); + MINRFcomputefirstUsedPacketMode(); + MINRF.timer = 5900; + Response_P(S_JSON_NRF_COMMAND, command, kMINRFDeviceType[XdrvMailbox.payload-1]); + } + else if (XdrvMailbox.payload == 65535) { + MINRF.ignore = 65535; + } + } + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.ignore); + break; + case CMND_NRF_USE: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload == 0){ + MINRF.ignore = 65535; + MINRF.firstUsedPacketMode = 1; + } + else if (XdrvMailbox.payload < MI_TYPES+1) { + bitClear(MINRF.ignore,XdrvMailbox.payload); + MINRFcomputefirstUsedPacketMode(); + MINRF.timer = 5900; + Response_P(S_JSON_NRF_COMMAND, command, kMINRFDeviceType[XdrvMailbox.payload-1]); + } + else if (XdrvMailbox.payload == 65535) { + MINRF.ignore = 0; + } + } + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.ignore); + break; + case CMND_NRF_SCAN: + if (XdrvMailbox.data_len > 0) { + MINRF.beacon.active = false; + switch(XdrvMailbox.payload){ + case 0: + MINRF.mode.activeScan = true; + MINRF.mode.stopScan = false; + MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(), + MINRFscanResult.end(), + [](scan_entry_t&) { return true; }), + MINRFscanResult.end()); + break; + case 1: + MINRF.mode.activeScan = true; + MINRF.mode.stopScan = false; + break; + case 2: + MINRF.mode.stopScan = true; + break; + } + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + break; + case CMND_NRF_BEACON: + if (XdrvMailbox.data_len > 0) { + if(XdrvMailbox.data_len<3){ + if (XdrvMailbox.payload < MINRFscanResult.size()) { + MINRFstartBeacon(XdrvMailbox.payload); + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + } + if (XdrvMailbox.data_len==12){ + memset(MINRF.beacon.MAC,0,sizeof(MINRF.beacon.MAC)); + MINRFMACStringToBytes(XdrvMailbox.data, MINRF.beacon.MAC); + MINRF.beacon.time=0; + MINRF.beacon.active=true; + Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); + } + MINRFcomputeBeaconPDU(MINRF.beacon.MAC,MINRF.beacon.PDU,0); + } + break; + case CMND_NRF_NLIGHT: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len==12){ + uint8_t _MAC[6] = {0}; + MINRFMACStringToBytes(XdrvMailbox.data, _MAC); + Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); + MINRFaddLight(_MAC, 7); + } + } + break; + case CMND_NRF_CHAN: + if (XdrvMailbox.data_len == 1) { + switch(XdrvMailbox.payload){ + case 0: case 1: case 2: + bitRead(MINRF.channelIgnore,XdrvMailbox.payload) == 0 ? bitSet(MINRF.channelIgnore,XdrvMailbox.payload) : bitClear(MINRF.channelIgnore,XdrvMailbox.payload); + break; + } + } + Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore); + break; +#ifdef USE_MI_DECRYPTION + case CMND_NRF_MJYD2S: + if (XdrvMailbox.data_len==44){ + MINRFAddKey(XdrvMailbox.data); + uint8_t _MAC[6] = {0}; + MINRFMACStringToBytes((XdrvMailbox.data)+32, _MAC); + MINRFaddLight(_MAC, 8); + Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); + } + break; + + case CMND_NRF_KEY: + if (XdrvMailbox.data_len==44){ + MINRFAddKey(XdrvMailbox.data); + Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); + } + break; +#endif + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%dus/cm{e}"; +const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; +const char HTTP_NRF24NEW[] PROGMEM = "{s}%sL01%c{m}%u%s / %u{e}"; + +void MINRFShow(bool json) +{ + if (json) { +#ifdef USE_HOME_ASSISTANT + bool _noSummarySave = MINRF.option.noSummary; + bool _minimalSummarySave = MINRF.option.minimalSummary; + if(hass_mode==2){ + MINRF.option.noSummary = false; + MINRF.option.minimalSummary = false; + } +#endif + if(!MINRF.mode.triggeredTele){ + if(MINRF.option.noSummary) return; + } + + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MINRF.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; + if(MINRF.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; + + if(MIBLEsensors[i].showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("NRF: sensor not fully registered yet")); + if(MIBLEsensors[i].type != YEERC) break; + } + + ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"),kMINRFDeviceType[MIBLEsensors[i].type-1],MIBLEsensors[i].MAC[3],MIBLEsensors[i].MAC[4],MIBLEsensors[i].MAC[5]); + + uint32_t _positionCurlyBracket = strlen(mqtt_data); + + if((!MINRF.mode.triggeredTele && !MINRF.option.minimalSummary)||MINRF.mode.triggeredTele){ + bool tempHumSended = false; + if(MIBLEsensors[i].feature.tempHum){ + if(MIBLEsensors[i].eventType.tempHum || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ + if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp) +#ifdef USE_HOME_ASSISTANT + ||(!hass_mode==2) +#endif + ) { + ResponseAppend_P(PSTR(",")); + ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); + tempHumSended = true; + } + } + } + if(MIBLEsensors[i].feature.temp && !tempHumSended){ + if(MIBLEsensors[i].eventType.temp || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].temp) +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ) { + char temperature[FLOATSZ]; + dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + } + } + if(MIBLEsensors[i].feature.hum && !tempHumSended){ + if(MIBLEsensors[i].eventType.hum || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].hum)) { + char hum[FLOATSZ]; + dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); + } + } + } + if (MIBLEsensors[i].feature.lux){ + if(MIBLEsensors[i].eventType.lux || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ + if (MIBLEsensors[i].lux!=0x0ffffff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ) { + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); + } + } + } + if (MIBLEsensors[i].feature.moist){ + if(MIBLEsensors[i].eventType.moist || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ + if (MIBLEsensors[i].moisture!=0xff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ) { + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); + } + } + } + if (MIBLEsensors[i].feature.fert){ + if(MIBLEsensors[i].eventType.fert || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ + if (MIBLEsensors[i].fertility!=0xffff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ) { + ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); + } + } + } + if (MIBLEsensors[i].feature.Btn){ + if(MIBLEsensors[i].eventType.Btn){ + ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); + } + } + } + if (MIBLEsensors[i].feature.PIR){ + if(MIBLEsensors[i].eventType.motion || !MINRF.mode.triggeredTele){ + if(MINRF.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); + ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); + } + else if(MIBLEsensors[i].eventType.noMotion && MINRF.mode.triggeredTele){ + ResponseAppend_P(PSTR(",\"PIR\":0")); + } + } + + if (MIBLEsensors[i].feature.NMT || !MINRF.mode.triggeredTele){ + if(MIBLEsensors[i].eventType.NMT){ + ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); + } + } + if (MIBLEsensors[i].feature.bat){ + if(MIBLEsensors[i].eventType.bat || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ + if (MIBLEsensors[i].bat != 0x00 +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ) { + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); + } + } + } + if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); + ResponseAppend_P(PSTR("}")); + mqtt_data[_positionCurlyBracket] = '{'; + MIBLEsensors[i].eventType.raw = 0; + if(MIBLEsensors[i].shallSendMQTT==1){ + MIBLEsensors[i].shallSendMQTT = 0; + continue; + } + } + for(uint32_t i=0; iMINRF.confirmedSensors){ + j = MINRF.confirmedSensors; + } + char stemp[5] ={0}; + if (MINRF.confirmedSensors-(_page*MINRF.perPage)>1 && MINRF.perPage!=1) { + sprintf_P(stemp,"-%u",j); + } + if (MINRF.confirmedSensors==0) i=-1; + + WSContentSend_PD(HTTP_NRF24NEW, NRF24type, NRF24.chipType, i+1,stemp,MINRF.confirmedSensors); + for (i ; iFLORA){ + WSContentSend_THD(kMINRFDeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); + if(MIBLEsensors[i].bat!=0x00){ + WSContentSend_PD(HTTP_BATTERY, kMINRFDeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); + } + } + } + if(MINRF.beacon.active){ + WSContentSend_PD(HTTP_MINRF_HL); + WSContentSend_PD(HTTP_MINRF_HL); + WSContentSend_PD(HTTP_MINRF_MAC, F("Beacon"), D_MAC_ADDRESS, MINRF.beacon.MAC[0], MINRF.beacon.MAC[1],MINRF.beacon.MAC[2],MINRF.beacon.MAC[3],MINRF.beacon.MAC[4],MINRF.beacon.MAC[5]); + WSContentSend_PD(PSTR("{s}Beacon Time{m}%u seconds{e}"),MINRF.beacon.time); + } + + for(uint32_t i=0; i0){ + WSContentSend_PD(HTTP_BATTERY, kMINRFDeviceType[MIBLElights[i].type-1], MIBLElights[i].bat); + } + if(MIBLElights[i].lux>0){ + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFDeviceType[MIBLElights[i].type-1], MIBLElights[i].lux); + } + } + } + + if(counter>3) { + _page++; + counter = 0; + } + counter++; + if(MINRF.confirmedSensors%MINRF.perPage==0 && _page==MINRF.confirmedSensors/MINRF.perPage) _page=0; + if(_page>MINRF.confirmedSensors/MINRF.perPage) _page=0; +#endif + } +} + + + + + +bool Xsns61(uint8_t function) +{ + bool result = false; + if (NRF24.chipType) { + switch (function) { + case FUNC_INIT: + MINRFinit(); + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF: started")); + break; + case FUNC_EVERY_50_MSECOND: + MINRF_EVERY_50_MSECOND(); + break; + case FUNC_EVERY_SECOND: + MINRFbeaconCounter(); + break; + case FUNC_COMMAND: + result = NRFCmd(); + break; + case FUNC_JSON_APPEND: + MINRFShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MINRFShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +# 46 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +#ifdef ESP32 + +#ifdef USE_MI_ESP32 + +#define XSNS_62 62 +#define USE_MI_DECRYPTION + +#include +#include +#ifdef USE_MI_DECRYPTION +#include +#endif + +void MI32scanEndedCB(NimBLEScanResults results); +void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); + +struct { + uint16_t perPage = 4; + uint32_t period; + union { + struct { + uint32_t init:1; + uint32_t connected:1; + uint32_t autoScan:1; + uint32_t canScan:1; + uint32_t runningScan:1; + uint32_t canConnect:1; + uint32_t willConnect:1; + uint32_t readingDone:1; + uint32_t shallSetTime:1; + uint32_t willSetTime:1; + uint32_t shallReadBatt:1; + uint32_t willReadBatt:1; + uint32_t shallSetUnit:1; + uint32_t willSetUnit:1; + uint32_t shallTriggerTele:1; + uint32_t triggeredTele:1; + uint32_t shallClearResults:1; + uint32_t shallShowStatusInfo:1; + uint32_t firstAutodiscoveryDone:1; + uint32_t activeBeacon; + }; + uint32_t all = 0; + } mode; + struct { + uint8_t sensor; + uint8_t beaconScanCounter; + } state; + struct { + uint32_t allwaysAggregate:1; + uint32_t noSummary:1; + uint32_t directBridgeMode:1; + uint32_t holdBackFirstAutodiscovery:1; + uint32_t showRSSI:1; + uint32_t ignoreBogusBattery:1; + uint32_t minimalSummary:1; + } option; +} MI32; + +#pragma pack(1) + + struct { + uint16_t temp; + uint8_t hum; + uint16_t volt; + } LYWSD0x_HT; + struct { + uint8_t spare; + uint16_t temp; + uint16_t hum; + } CGD1_HT; + struct { + uint16_t temp; + uint8_t spare; + uint32_t lux; + uint8_t moist; + uint16_t fert; + } Flora_TLMF; + + +struct mi_beacon_t{ + uint16_t frame; + uint16_t productID; + uint8_t counter; + uint8_t MAC[6]; + uint8_t spare; + uint8_t type; + uint8_t ten; + uint8_t size; + union { + struct{ + uint16_t temp; + uint16_t hum; + }HT; + uint8_t bat; + uint16_t temp; + uint16_t hum; + uint32_t lux; + uint8_t moist; + uint16_t fert; + uint32_t NMT; + struct{ + uint16_t num; + uint8_t longPress; + }Btn; + }; + uint8_t padding[12]; +}; + +struct cg_packet_t { + uint16_t frameID; + uint8_t MAC[6]; + uint16_t mode; + union { + struct { + int16_t temp; + uint16_t hum; + }; + uint8_t bat; + }; +}; + +struct encPacket_t{ + + uint16_t PID; + uint8_t frameCnt; + uint8_t MAC[6]; + uint8_t payload[16]; +}; + +union mi_bindKey_t{ + struct{ + uint8_t key[16]; + uint8_t MAC[6]; + }; + uint8_t buf[22]; +}; + +struct ATCPacket_t{ + uint8_t MAC[6]; + int16_t temp; + uint8_t hum; + uint8_t batPer; + uint16_t batMV; + uint8_t frameCnt; +}; + +#pragma pack(0) + +struct mi_sensor_t{ + uint8_t type; + uint8_t lastCnt; + uint8_t shallSendMQTT; + uint8_t MAC[6]; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t PIR:1; + uint32_t Btn:1; + }; + uint32_t raw; + } feature; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t motion:1; + uint32_t noMotion:1; + uint32_t Btn:1; + }; + uint32_t raw; + } eventType; + + int RSSI; + uint32_t lastTime; + uint32_t lux; + float temp; + union { + struct { + uint8_t moisture; + uint16_t fertility; + char firmware[6]; + }; + struct { + float hum; + }; + struct { + uint16_t events; + uint32_t NMT; + }; + uint16_t Btn; + }; + union { + uint8_t bat; + }; +}; + +struct scan_entry_t { + uint8_t MAC[6]; + uint16_t CID; + uint16_t SVC; + uint16_t UUID; + int32_t RSSI; +}; + +struct generic_beacon_t { + uint8_t MAC[6]; + uint32_t time; + int32_t RSSI; + uint16_t CID; + uint16_t UUID; + uint16_t SVC; + bool active = false; +}; + +std::vector MIBLEsensors; +std::vector MIBLEbindKeys; +std::array MIBLEbeacons; +std::vector MINBLEscanResult; + +static BLEScan* MI32Scan; + + + + + +#define D_CMND_MI32 "MI32" + +const char S_JSON_MI32_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s\":%d}"; +const char S_JSON_MI32_COMMAND[] PROGMEM = "{\"" D_CMND_MI32 "%s%s\"}"; + +const char S_JSON_MI32_BCOMMAND_SVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s%u\":\"%s\"}"; +const char kMI32_Commands[] PROGMEM = "Period|Time|Page|Battery|Unit|Key|Beacon"; + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 +#define CGG1 5 +#define CGD1 6 +#define NLIGHT 7 +#define MJYD2S 8 +#define YEERC 9 +#define MHOC401 10 +#define MHOC303 11 +#define ATC 12 + +#define MI32_TYPES 12 + +const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, + 0x01aa, + 0x045b, + 0x055b, + 0x0347, + 0x0576, + 0x03dd, + 0x07f6, + 0x0153, + 0x0387, + 0x06d3, + 0x0a1c + }; + +const char kMI32DeviceType1[] PROGMEM = "Flora"; +const char kMI32DeviceType2[] PROGMEM = "MJ_HT_V1"; +const char kMI32DeviceType3[] PROGMEM = "LYWSD02"; +const char kMI32DeviceType4[] PROGMEM = "LYWSD03"; +const char kMI32DeviceType5[] PROGMEM = "CGG1"; +const char kMI32DeviceType6[] PROGMEM = "CGD1"; +const char kMI32DeviceType7[] PROGMEM = "NLIGHT"; +const char kMI32DeviceType8[] PROGMEM = "MJYD2S"; +const char kMI32DeviceType9[] PROGMEM = "YEERC"; +const char kMI32DeviceType10[] PROGMEM ="MHOC401"; +const char kMI32DeviceType11[] PROGMEM ="MHOC303"; +const char kMI32DeviceType12[] PROGMEM ="ATC"; +const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12}; + + + + + +enum MI32_Commands { + CMND_MI32_PERIOD, + CMND_MI32_TIME, + CMND_MI32_PAGE, + CMND_MI32_BATTERY, + CMND_MI32_UNIT, + CMND_MI32_KEY, + CMND_MI32_BEACON + }; + +enum MI32_TASK { + MI32_TASK_SCAN = 0, + MI32_TASK_CONN = 1, + MI32_TASK_TIME = 2, + MI32_TASK_BATT = 3, + MI32_TASK_UNIT = 4, +}; + +enum MI32_BEACON_CMND { + MI32_BEACON_ON = 0, + MI32_BEACON_OFF = 1, + MI32_BEACON_DEL = 2, +}; + + + + + +class MI32SensorCallback : public NimBLEClientCallbacks { + void onConnect(NimBLEClient* pclient) { + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("connected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); + MI32.mode.willConnect = 0; + MI32.mode.connected = 1; + } + void onDisconnect(NimBLEClient* pclient) { + MI32.mode.connected = 0; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("disconnected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); + } + bool onConnParamsUpdateRequest(NimBLEClient* MI32Client, const ble_gap_upd_params* params) { + if(params->itvl_min < 24) { + return false; + } else if(params->itvl_max > 40) { + return false; + } else if(params->latency > 2) { + return false; + } else if(params->supervision_timeout > 100) { + return false; + } + return true; + } +}; + +class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks { + void onResult(NimBLEAdvertisedDevice* advertisedDevice) { + + int RSSI = advertisedDevice->getRSSI(); + uint8_t addr[6]; + memcpy(addr,advertisedDevice->getAddress().getNative(),6); + MI32_ReverseMAC(addr); + if (advertisedDevice->getServiceDataCount() == 0) { + + if(MI32.state.beaconScanCounter==0 && !MI32.mode.activeBeacon){ + MI32Scan->erase(advertisedDevice->getAddress()); + return; + } + else{ + MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); + return; + } + + } + uint16_t UUID = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value; + + + size_t ServiceDataLength = advertisedDevice->getServiceData(0).length(); + if(UUID==0xfe95) { + MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); + } + else if(UUID==0xfdcd) { + MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); + } + else if(UUID==0x181a) { + MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); + } + else { + if(MI32.state.beaconScanCounter!=0 || MI32.mode.activeBeacon){ + MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); + } + + MI32Scan->erase(advertisedDevice->getAddress()); + } + }; +}; + + +static MI32AdvCallbacks MI32ScanCallbacks; +static MI32SensorCallback MI32SensorCB; +static NimBLEClient* MI32Client; + + + + + +void MI32scanEndedCB(NimBLEScanResults results){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Scan ended")); + MI32.mode.runningScan = 0; +} + +void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Notified length: %u"),length); + switch(MIBLEsensors[MI32.state.sensor].type){ + case LYWSD03MMC: case LYWSD02: case MHOC401: + MI32readHT_LY((char*)pData); + MI32.mode.readingDone = 1; + break; + default: + MI32.mode.readingDone = 1; + break; + } +} +# 469 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +void MI32stripColon(char* _string){ + uint32_t _length = strlen(_string); + uint32_t _index = 0; + while (_index < _length) { + char c = _string[_index]; + if(c==':'){ + memmove(_string+_index,_string+_index+1,_length-_index); + } + _index++; + } + _string[_index] = 0; +} +# 489 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +void MI32HexStringToBytes(char* _string, uint8_t* _byteArray) { + MI32stripColon(_string); + UpperCase(_string,_string); + uint32_t index = 0; + uint32_t _end = strlen(_string); + memset(_byteArray,0,_end/2); + while (index < _end) { + char c = _string[index]; + uint8_t value = 0; + if(c >= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _byteArray[(index/2)] += value << (((index + 1) % 2) * 4); + index++; + } +} + + + + + + +void MI32_ReverseMAC(uint8_t _mac[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _mac[i]; + } + memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); +} + +#ifdef USE_MI_DECRYPTION +void MI32AddKey(char* payload){ + mi_bindKey_t keyMAC; + MI32HexStringToBytes(payload,keyMAC.buf); + bool unknownKey = true; + for(uint32_t i=0; iMAC[i]; + } + memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); + nonce[8] = packet->frameCnt; + memcpy((uint8_t*)&nonce+9,(uint8_t*)&_buf[_bufSize-9],3); + + memcpy((uint8_t*)&tag,(uint8_t*)&_buf[_bufSize-6],4); + + + MI32_ReverseMAC(packet->MAC); + uint8_t _bindkey[16] = {0x0}; + bool foundNoKey = true; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: search key for MAC: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]); + for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ + memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: decryption Key found")); + foundNoKey = false; + break; + } + } + if(foundNoKey){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: no Key found !!")); + return -2; + } + + br_aes_small_ctrcbc_keys keyCtx; + br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); + + br_ccm_context ctx; + br_ccm_init(&ctx, &keyCtx.vtable); + br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData), data_len, sizeof(tag)); + br_ccm_aad_inject(&ctx, authData, sizeof(authData)); + br_ccm_flip(&ctx); + + + memcpy(payload,packet->payload,data_len); + br_ccm_run(&ctx, 0, payload, data_len); + memcpy((uint8_t*)packet->payload+1,payload,data_len); + + ret = br_ccm_check_tag(&ctx, &tag); + + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]); + return ret-1; +} +#endif + +#ifdef USE_HOME_ASSISTANT + + + + +void MI32nullifyEndOfMQTT_DATA(){ + char *p = mqtt_data + strlen(mqtt_data); + while(true){ + *p--; + if(p[0]==':'){ + p[1] = 0; + break; + } + } + ResponseAppend_P(PSTR("null")); +} +#endif +# 636 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter){ + + DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_MI32, _type); + bool _success = false; + for (uint32_t i=0;i= NIMBLE_MAX_CONNECTIONS) { + MI32.mode.willConnect = 0; + DEBUG_SENSOR_LOG(PSTR("%s: max connection already reached"),D_CMND_MI32); + return false; + } + if(!MI32Client) { + + MI32Client = NimBLEDevice::createClient(); + MI32Client->setClientCallbacks(&MI32SensorCB , false); + MI32Client->setConnectionParams(12,12,0,48); + MI32Client->setConnectTimeout(30); + + } + vTaskDelay(300/ portTICK_PERIOD_MS); + if (!MI32Client->connect(_address,false)) { + MI32.mode.willConnect = 0; + + + return false; + } + return true; + +} + +void MI32StartScanTask(){ + if (MI32.mode.connected) return; + MI32.mode.runningScan = 1; + xTaskCreatePinnedToCore( + MI32ScanTask, + "MI32ScanTask", + 4096, + NULL, + 0, + NULL, + 0); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Start scanning"),D_CMND_MI32); +} + +void MI32ScanTask(void *pvParameters){ + if (MI32Scan == nullptr) MI32Scan = NimBLEDevice::getScan(); + + MI32Scan->setInterval(70); + MI32Scan->setWindow(50); + MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks,true); + MI32Scan->setActiveScan(false); + MI32Scan->start(0, MI32scanEndedCB, true); + + uint32_t timer = 0; + for(;;){ + if(MI32.mode.shallClearResults){ + MI32Scan->clearResults(); + MI32.mode.shallClearResults=0; + } + vTaskDelay(10000/ portTICK_PERIOD_MS); + } + vTaskDelete( NULL ); +} + +void MI32StartSensorTask(){ + MI32.mode.willConnect = 1; + switch(MIBLEsensors[MI32.state.sensor].type){ + case LYWSD03MMC: case MHOC401: + break; + default: + MI32.mode.willConnect = 0; + return; + } + + xTaskCreatePinnedToCore( + MI32SensorTask, + "MI32SensorTask", + 4096, + NULL, + 15, + NULL, + 0); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Start sensor connections"),D_CMND_MI32); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: with sensor: %u"),D_CMND_MI32, MI32.state.sensor); +} + +void MI32SensorTask(void *pvParameters){ + if (MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + MI32Client->disconnect(); + + MI32.mode.willConnect = 0; + MI32.mode.willReadBatt = 0; + vTaskDelay(100/ portTICK_PERIOD_MS); + vTaskDelete( NULL ); + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); + } + + timer = 150; + switch(MIBLEsensors[MI32.state.sensor].type){ + case LYWSD03MMC: case MHOC401: + MI32.mode.readingDone = 0; + if(MI32connectLYWSD03forNotification()) timer=0; + break; + default: + break; + } + + while (!MI32.mode.readingDone){ + if (timer>150){ + break; + } + timer++; + vTaskDelay(100/ portTICK_PERIOD_MS); + } + MI32Client->disconnect(); + DEBUG_SENSOR_LOG(PSTR("%s: requested disconnect"),D_CMND_MI32); + } + + MI32.mode.connected = 0; + vTaskDelete( NULL ); +} + +bool MI32connectLYWSD03forNotification(){ + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; + static BLEUUID serviceUUID(0xebe0ccb0,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); + static BLEUUID charUUID(0xebe0ccc1,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); + pSvc = MI32Client->getService(serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(charUUID); + } + if (pChr){ + if(pChr->canNotify()) { + if(pChr->subscribe(true,MI32notifyCB,false)) { + return true; + } + } + } + return false; +} + +void MI32StartTimeTask(){ + MI32.mode.willConnect = 1; + xTaskCreatePinnedToCore( + MI32TimeTask, + "MI32TimeTask", + 4096, + NULL, + 15, + NULL, + 0); + + +} + +void MI32TimeTask(void *pvParameters){ + if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { + MI32.mode.shallSetTime = 0; + vTaskDelete( NULL ); + } + if(MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); + } + + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; + static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + static BLEUUID charUUID(0xEBE0CCB7,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + pSvc = MI32Client->getService(serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(charUUID); + + } + if (pChr){ + if(pChr->canWrite()) { + union { + uint8_t buf[5]; + uint32_t time; + } _utc; + _utc.time = Rtc.utc_time; + _utc.buf[4] = Rtc.time_timezone / 60; + + if(!pChr->writeValue(_utc.buf,sizeof(_utc.buf),true)) { + MI32.mode.willConnect = 0; + MI32Client->disconnect(); + } + else { + MI32.mode.shallSetTime = 0; + MI32.mode.willSetTime = 0; + } + } + } + MI32Client->disconnect(); + } + + MI32.mode.connected = 0; + MI32.mode.canScan = 1; + vTaskDelete( NULL ); +} + +void MI32StartUnitTask(){ + MI32.mode.willConnect = 1; + xTaskCreatePinnedToCore( + MI32UnitTask, + "MI32UnitTask", + 4096, + NULL, + 15, + NULL, + 0); + + +} + +void MI32UnitTask(void *pvParameters){ + if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { + MI32.mode.shallSetUnit = 0; + vTaskDelete( NULL ); + } + + if(MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); + } + + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; + static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + static BLEUUID charUUID(0xEBE0CCBE,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + pSvc = MI32Client->getService(serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(charUUID); + } + + if(pChr->canRead()){ + uint8_t curUnit; + const char *buf = pChr->readValue().c_str(); + if( buf[0] != 0 && buf[0]<101 ){ + curUnit = buf[0]; + } + + if(pChr->canWrite()) { + curUnit = curUnit == 0x01?0xFF:0x01; + + if(!pChr->writeValue(&curUnit,sizeof(curUnit),true)) { + MI32.mode.willConnect = 0; + MI32Client->disconnect(); + } + else { + MI32.mode.shallSetUnit = 0; + MI32.mode.willSetUnit = 0; + } + } + } + MI32Client->disconnect(); + } + + MI32.mode.connected = 0; + MI32.mode.canScan = 1; + vTaskDelete( NULL ); +} + +void MI32StartBatteryTask(){ + if (MI32.mode.connected) return; + MI32.mode.willReadBatt = 1; + MI32.mode.willConnect = 1; + MI32.mode.canScan = 0; + + switch (MIBLEsensors[MI32.state.sensor].type){ + case LYWSD03MMC: case MJ_HT_V1: case CGG1: case NLIGHT: case MJYD2S: case YEERC: case MHOC401: + MI32.mode.willConnect = 0; + MI32.mode.willReadBatt = 0; + return; + } + + xTaskCreatePinnedToCore( + MI32BatteryTask, + "MI32BatteryTask", + 4096, + NULL, + 15, + NULL, + 0); +} + +void MI32BatteryTask(void *pvParameters){ + + + MI32.mode.connected = 0; + if(MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(30/ portTICK_PERIOD_MS); + } + + switch(MIBLEsensors[MI32.state.sensor].type){ + case FLORA: case LYWSD02: case CGD1: + MI32batteryRead(MIBLEsensors[MI32.state.sensor].type); + break; + } + MI32Client->disconnect(); + } + MI32.mode.willReadBatt = 0; + MI32.mode.connected = 0; + vTaskDelete( NULL ); +} + +void MI32batteryRead(uint32_t _type){ + uint32_t timer = 0; + while (!MI32.mode.connected){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); + } + DEBUG_SENSOR_LOG(PSTR("%s connected for battery"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; + + switch(_type){ + case FLORA: + { + static BLEUUID _serviceUUID(0x00001204,0x0000,0x1000,0x800000805f9b34fb); + static BLEUUID _charUUID(0x00001a02,0x0000,0x1000,0x800000805f9b34fb); + pSvc = MI32Client->getService(_serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(_charUUID); + } + } + break; + case LYWSD02: + { + static BLEUUID _serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + static BLEUUID _charUUID(0xEBE0CCC4,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + pSvc = MI32Client->getService(_serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(_charUUID); + } + } + break; + case CGD1: + { + static BLEUUID _serviceUUID((uint16_t)0x180F); + static BLEUUID _charUUID((uint16_t)0x2A19); + pSvc = MI32Client->getService(_serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(_charUUID); + } + } + break; + } + + if (pChr){ + DEBUG_SENSOR_LOG(PSTR("%s: got %s char %s"),D_CMND_MI32, kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1], pChr->getUUID().toString().c_str()); + if(pChr->canRead()) { + const char *buf = pChr->readValue().c_str(); + MI32readBat((char*)buf); + } + } + MI32.mode.readingDone = 1; +} + + + + + +void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize){ + float _tempFloat; + mi_beacon_t _beacon; + + if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1 || MIBLEsensors[_slot].type==YEERC){ + memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); + memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); + _beacon.counter = _buf[4]; + } + else{ + memcpy((char *)&_beacon, _buf, _bufSize); + } + + MIBLEsensors[_slot].lastCnt = _beacon.counter; +#ifdef USE_MI_DECRYPTION + int decryptRet = 0; + switch(MIBLEsensors[_slot].type){ + case LYWSD03MMC: case MHOC401: + if (_beacon.frame == 0x5858){ + decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize, LYWSD03MMC); + + } + else return; + break; + case MJYD2S: + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: %x"),_beacon.frame); + if (_beacon.frame == 0x5948){ + memmove((uint8_t*)&_beacon.MAC+6,(uint8_t*)&_beacon.MAC, _bufSize); + memcpy((uint8_t*)&_beacon.MAC,MIBLEsensors[_slot].MAC,6); + _bufSize+=6; + MI32_ReverseMAC(_beacon.MAC); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: special packet")); + } + if (_beacon.frame != 0x5910){ + decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize,MJYD2S); + } + break; + } +if(decryptRet!=0){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: decryption failed with error: %d"),decryptRet); + return; +} +#endif + + if(MIBLEsensors[_slot].type==6){ + DEBUG_SENSOR_LOG(PSTR("CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); + return; + } + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u with payload type: %02x"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot,_beacon.type); + switch(_beacon.type){ + case 0x01: + MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6; + MIBLEsensors[_slot].eventType.Btn = 1; + MI32.mode.shallTriggerTele = 1; + + break; + case 0x04: + _tempFloat=(float)(_beacon.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + MIBLEsensors[_slot].eventType.temp = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); + } + + break; + case 0x06: + _tempFloat=(float)(_beacon.hum)/10.0f; + if(_tempFloat<101){ + MIBLEsensors[_slot].hum=_tempFloat; + MIBLEsensors[_slot].eventType.hum = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); + } + + break; + case 0x07: + MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; + if(MIBLEsensors[_slot].type==MJYD2S){ + MIBLEsensors[_slot].eventType.noMotion = 1; + } + MIBLEsensors[_slot].eventType.lux = 1; + + break; + case 0x08: + MIBLEsensors[_slot].moisture=_beacon.moist; + MIBLEsensors[_slot].eventType.moist = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); + + break; + case 0x09: + MIBLEsensors[_slot].fertility=_beacon.fert; + MIBLEsensors[_slot].eventType.fert = 1; + DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); + + break; + case 0x0a: + if(MI32.option.ignoreBogusBattery){ + if(MIBLEsensors[_slot].type==LYWSD03MMC || MIBLEsensors[_slot].type==MHOC401){ + break; + } + } + if(_beacon.bat<101){ + MIBLEsensors[_slot].bat = _beacon.bat; + MIBLEsensors[_slot].eventType.bat = 1; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + } + + break; + case 0x0d: + _tempFloat=(float)(_beacon.HT.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); + } + _tempFloat=(float)(_beacon.HT.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + + break; +#ifdef USE_MI_DECRYPTION + case 0x0f: + if (_beacon.ten!=0) break; + MIBLEsensors[_slot].eventType.motion = 1; + MIBLEsensors[_slot].lastTime = millis(); + MIBLEsensors[_slot].events++; + MIBLEsensors[_slot].lux = _beacon.lux; + MIBLEsensors[_slot].eventType.lux = 1; + MIBLEsensors[_slot].NMT = 0; + MI32.mode.shallTriggerTele = 1; + + break; + case 0x17: + MIBLEsensors[_slot].NMT = _beacon.NMT; + MIBLEsensors[_slot].eventType.NMT = 1; + MI32.mode.shallTriggerTele = 1; + + break; +#endif + default: + if (MIBLEsensors[_slot].type==NLIGHT){ + MIBLEsensors[_slot].eventType.motion = 1; + MIBLEsensors[_slot].events++; + MIBLEsensors[_slot].NMT = 0; + MIBLEsensors[_slot].lastTime = millis(); + MI32.mode.shallTriggerTele = 1; + + } + else{ + AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)_buf,_bufSize); + } + break; + } + if(MIBLEsensors[_slot].eventType.raw == 0) return; + MIBLEsensors[_slot].shallSendMQTT = 1; + if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; +} + +void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ + ATCPacket_t *_packet = (ATCPacket_t*)_buf; + uint32_t _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->frameCnt); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if(_slot==0xff) return; + + MIBLEsensors[_slot].RSSI=RSSI; + + MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; + MIBLEsensors.at(_slot).hum = (float)_packet->hum; + MIBLEsensors[_slot].eventType.tempHum = 1; + MIBLEsensors.at(_slot).bat = _packet->batPer; + MIBLEsensors[_slot].eventType.bat = 1; + + MIBLEsensors[_slot].shallSendMQTT = 1; + if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; + +} + +void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ + uint8_t _addr[6]; + memcpy(_addr,addr,6); + uint32_t _slot = MIBLEgetSensorSlot(_addr, 0x0576, 0); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if(_slot==0xff) return; + MIBLEsensors[_slot].RSSI=RSSI; + cg_packet_t _packet; + memcpy((char*)&_packet,_buf,sizeof(_packet)); + switch (_packet.mode){ + case 0x0401: + float _tempFloat; + _tempFloat=(float)(_packet.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp = _tempFloat; + MIBLEsensors[_slot].eventType.temp = 1; + DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); + } + _tempFloat=(float)(_packet.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + MIBLEsensors[_slot].eventType.hum = 1; + DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), _packet.temp, _packet.hum); + break; + case 0x0102: + if(_packet.bat<101){ + MIBLEsensors.at(_slot).bat = _packet.bat; + MIBLEsensors[_slot].eventType.bat = 1; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + } + break; + default: + DEBUG_SENSOR_LOG(PSTR("MI32: unexpected CGD1-packet")); + } + if(MIBLEsensors[_slot].eventType.raw == 0) return; + MIBLEsensors[_slot].shallSendMQTT = 1; + if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; +} + +void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { + if(bufsize<9) { + return; + } + uint16_t _type= buf[3]*256 + buf[2]; + + uint8_t _addr[6]; + memcpy(_addr,addr,6); + uint16_t _slot = MIBLEgetSensorSlot(_addr, _type, buf[4]); + if(_slot!=0xff) { + MIBLEsensors[_slot].RSSI=RSSI; + MI32parseMiBeacon(buf,_slot,bufsize); + } +} +# 1456 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID){ + AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("MI32: Beacon:____________")); + for (uint32_t i = 0; i19) { + AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full")); + MI32.state.beaconScanCounter = 1; + return; + } + for(auto _scanResult : MINBLEscanResult){ + if(memcmp(addr,_scanResult.MAC,6)==0){ + + return; + } + } + scan_entry_t _new; + _new.RSSI = RSSI; + _new.CID = 0; + _new.SVC = 0; + _new.UUID = 0; + memcpy(_new.MAC,addr,sizeof(_new.MAC)); + MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID); + MINBLEscanResult.push_back(_new); +} +# 1542 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" +void MI32addBeacon(uint8_t index, char* data){ + auto &_new = MIBLEbeacons[index-1]; + MI32HexStringToBytes(data,_new.MAC); + char _MAC[18]; + ToHex_P(MIBLEbeacons[index-1].MAC,6,_MAC,18,':'); + char _empty[6] = {0}; + _new.time = 0; + if(memcmp(_empty,_new.MAC,6) == 0){ + _new.active = false; + AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon%u deactivated"), index); + } + else{ + _new.active = true; + MI32.mode.activeBeacon = 1; + AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon added with MAC: %s"), _MAC); + } +} + + + + + +void MI32showScanResults(){ + AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: found %u devices in scan:"), MINBLEscanResult.size()); + for(auto _scanResult : MINBLEscanResult){ + char _MAC[18]; + ToHex_P(_scanResult.MAC,6,_MAC,18,':'); + AddLog_P2(LOG_LEVEL_INFO,PSTR("MAC: %s _ CID: %04x _ SVC: %04x _ UUID: %04x _ RSSI: %d"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI); + } + MINBLEscanResult.clear(); +} + + + + +void MI32readHT_LY(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0 && _buf[1] != 0){ + memcpy(&LYWSD0x_HT,(void *)_buf,sizeof(LYWSD0x_HT)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u, V: %u"),D_CMND_MI32,LYWSD0x_HT.temp,LYWSD0x_HT.hum, LYWSD0x_HT.volt); + uint32_t _slot = MI32.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + + } + _tempFloat=(float)LYWSD0x_HT.hum; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){ + MIBLEsensors[_slot].bat = ((float)LYWSD0x_HT.volt-2100.0f)/12.0f; + MI32.mode.willReadBatt = 0; + MIBLEsensors[_slot].eventType.bat = 1; + } + MIBLEsensors[_slot].shallSendMQTT = 1; + MI32.mode.shallTriggerTele = 1; + } +} + +bool MI32readBat(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_MI32,_buf[0]); + uint32_t _slot = MI32.state.sensor; + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + if(_buf[0]<101){ + MIBLEsensors[_slot].bat=_buf[0]; + if(MIBLEsensors[_slot].type==FLORA){ + memcpy(MIBLEsensors[_slot].firmware, _buf+2, 5); + MIBLEsensors[_slot].firmware[5] = '\0'; + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Firmware: %s"),D_CMND_MI32,MIBLEsensors[_slot].firmware); + } + MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + MI32.mode.shallTriggerTele = 1; + return true; + } + } + return false; +} + + + + + + +void MI32Every50mSecond(){ + if(MI32.mode.shallTriggerTele){ + MI32.mode.shallTriggerTele = 0; + MI32triggerTele(); + } +} + + + + + + +void MI32EverySecond(bool restart){ + static uint32_t _counter = MI32.period - 15; + static uint32_t _nextSensorSlot = 0; + + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MIBLEsensors[i].type==NLIGHT || MIBLEsensors[i].type==MJYD2S){ + MIBLEsensors[i].NMT++; + } + } + + uint32_t _idx = 0; + uint32_t _activeBeacons = 0; + for (auto &_beacon : MIBLEbeacons){ + _idx++; + if(_beacon.active == false) continue; + _activeBeacons++; + _beacon.time++; + Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _beacon.time); + XdrvRulesProcess(); + } + if(_activeBeacons==0) MI32.mode.activeBeacon = 0; + + if(MI32.state.beaconScanCounter!=0){ + MI32.state.beaconScanCounter--; + if(MI32.state.beaconScanCounter==0){ + MI32showScanResults(); + } + } + + if(MI32.mode.shallShowStatusInfo == 1){ + MI32StatusInfo(); + } + + if(restart){ + _counter = 0; + MI32.mode.canScan = 0; + MI32.mode.canConnect = 1; + MI32.mode.willReadBatt = 0; + MI32.mode.willConnect = 0; + return; + } + + if (MI32.mode.shallSetTime) { + MI32.mode.canScan = 0; + MI32.mode.canConnect = 0; + if (MI32.mode.willSetTime == 0){ + MI32.mode.willSetTime = 1; + MI32StartTask(MI32_TASK_TIME); + } + } + + if (MI32.mode.shallSetUnit) { + MI32.mode.canScan = 0; + MI32.mode.canConnect = 0; + if (MI32.mode.willSetUnit == 0){ + MI32.mode.willSetUnit = 1; + MI32StartTask(MI32_TASK_UNIT); + } + } + + if (MI32.mode.willReadBatt) return; + + if (_counter>MI32.period) { + _counter = 0; + MI32.mode.canScan = 0; + MI32.mode.canConnect = 1; + } + + if(MI32.mode.connected == 1 || MI32.mode.willConnect == 1) return; + + if(MIBLEsensors.size()==0) { + if (MI32.mode.runningScan == 0 && MI32.mode.canScan == 1) MI32StartTask(MI32_TASK_SCAN); + return; + } + + if(_counter==0) { + + MI32.state.sensor = _nextSensorSlot; + MI32.mode.canScan = 0; + + if (MI32.mode.connected || MI32.mode.willConnect) return; + _nextSensorSlot++; + MI32.mode.canConnect = 1; + if(MI32.mode.connected == 0) { + if (MI32.mode.shallReadBatt) { + + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("will connect to %s"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); + + MI32StartTask(MI32_TASK_BATT); + } +#ifndef USE_MI_DECRYPTION + else{ + MI32StartTask(MI32_TASK_CONN); + } +#endif + } + if (_nextSensorSlot>(MIBLEsensors.size()-1)) { + _nextSensorSlot= 0; + _counter++; + if (MI32.mode.shallReadBatt){ + MI32.mode.shallReadBatt = 0; + } + MI32.mode.canConnect = 0; + MI32.mode.canScan = 1; + } + } + else _counter++; + if (MI32.state.sensor>MIBLEsensors.size()-1) { + _nextSensorSlot = 0; + MI32.mode.canScan = 1; + } + MI32StartTask(MI32_TASK_SCAN); +} + + + + + +bool MI32Cmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_MI32); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MI32), disp_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMI32_Commands); + switch (command_code) { + case CMND_MI32_PERIOD: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload==1) { + MI32EverySecond(true); + XdrvMailbox.payload = MI32.period; + } + else { + MI32.period = XdrvMailbox.payload; + } + } + else { + XdrvMailbox.payload = MI32.period; + } + Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MI32_TIME: + if (XdrvMailbox.data_len > 0) { + if(MIBLEsensors.size()>XdrvMailbox.payload){ + if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02 || MIBLEsensors[XdrvMailbox.payload].type == MHOC303){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: will set Time"),D_CMND_MI32); + MI32.state.sensor = XdrvMailbox.payload; + MI32.mode.canScan = 0; + MI32.mode.canConnect = 0; + MI32.mode.shallSetTime = 1; + MI32.mode.willSetTime = 0; + } + } + } + Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MI32_UNIT: + if (XdrvMailbox.data_len > 0) { + if(MIBLEsensors.size()>XdrvMailbox.payload){ + if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02 || MIBLEsensors[XdrvMailbox.payload].type == MHOC303){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: will set Unit"),D_CMND_MI32); + MI32.state.sensor = XdrvMailbox.payload; + MI32.mode.canScan = 0; + MI32.mode.canConnect = 0; + MI32.mode.shallSetUnit = 1; + MI32.mode.willSetUnit = 0; + } + } + } + Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MI32_PAGE: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload == 0) XdrvMailbox.payload = MI32.perPage; + MI32.perPage = XdrvMailbox.payload; + } + else XdrvMailbox.payload = MI32.perPage; + Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MI32_BATTERY: + MI32EverySecond(true); + MI32.mode.shallReadBatt = 1; + MI32.mode.canConnect = 1; + XdrvMailbox.payload = MI32.period; + Response_P(S_JSON_MI32_COMMAND, command, ""); + break; +#ifdef USE_MI_DECRYPTION + case CMND_MI32_KEY: + if (XdrvMailbox.data_len==44){ + MI32AddKey(XdrvMailbox.data); + Response_P(S_JSON_MI32_COMMAND, command, XdrvMailbox.data); + } + break; +#endif + case CMND_MI32_BEACON: + if (XdrvMailbox.data_len == 0) { + switch(XdrvMailbox.index){ + case 0: + MI32.state.beaconScanCounter = 8; + Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("\"scanning\"")); + break; + case 1: case 2: case 3: case 4: + char _MAC[18]; + ToHex_P(MIBLEbeacons[XdrvMailbox.index-1].MAC,6,_MAC,18,':'); + Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,_MAC); + break; + } + } + else { + if(XdrvMailbox.data_len == 12 || XdrvMailbox.data_len == 17){ + switch(XdrvMailbox.index){ + case 1: case 2: case 3: case 4: + MI32addBeacon(XdrvMailbox.index,XdrvMailbox.data); + break; + } + } + Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,XdrvMailbox.data); + } + break; + + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + + +const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916{m}%u%s / %u{e}"; +const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; +const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; +const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; +const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; +const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; +const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; +const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; + +void MI32Show(bool json) +{ + if (json) { +#ifdef USE_HOME_ASSISTANT + bool _noSummarySave = MI32.option.noSummary; + bool _minimalSummarySave = MI32.option.minimalSummary; + if(hass_mode==2){ + if(MI32.option.holdBackFirstAutodiscovery){ + if(!MI32.mode.firstAutodiscoveryDone){ + MI32.mode.firstAutodiscoveryDone = 1; + return; + } + } + MI32.option.noSummary = false; + MI32.option.minimalSummary = false; + } +#endif + + if(!MI32.mode.triggeredTele){ + MI32.mode.shallClearResults=1; + if(MI32.option.noSummary) return; + } + + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MI32.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; + if(MI32.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; + + ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), + kMI32DeviceType[MIBLEsensors[i].type-1], + MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); + + uint32_t _positionCurlyBracket = strlen(mqtt_data); + + if((!MI32.mode.triggeredTele && !MI32.option.minimalSummary)||MI32.mode.triggeredTele){ + bool tempHumSended = false; + if(MIBLEsensors[i].feature.tempHum){ + if(MIBLEsensors[i].eventType.tempHum || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ + if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp) +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + ResponseAppend_P(PSTR(",")); + ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); + tempHumSended = true; + } + } + } + if(MIBLEsensors[i].feature.temp && !tempHumSended){ + if(MIBLEsensors[i].eventType.temp || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].temp) +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + char temperature[FLOATSZ]; + dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + } + } + if(MIBLEsensors[i].feature.hum && !tempHumSended){ + if(MIBLEsensors[i].eventType.hum || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].hum) +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + char hum[FLOATSZ]; + dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); + } + } + } + if (MIBLEsensors[i].feature.lux){ + if(MIBLEsensors[i].eventType.lux || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ + if (MIBLEsensors[i].lux!=0x0ffffff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); +#ifdef USE_HOME_ASSISTANT + if (MIBLEsensors[i].lux==0x0ffffff) MI32nullifyEndOfMQTT_DATA(); +#endif + } + } + } + if (MIBLEsensors[i].feature.moist){ + if(MIBLEsensors[i].eventType.moist || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ + if (MIBLEsensors[i].moisture!=0xff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); +#ifdef USE_HOME_ASSISTANT + if (MIBLEsensors[i].moisture==0xff) MI32nullifyEndOfMQTT_DATA(); +#endif + } + } + } + if (MIBLEsensors[i].feature.fert){ + if(MIBLEsensors[i].eventType.fert || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ + if (MIBLEsensors[i].fertility!=0xffff +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); +#ifdef USE_HOME_ASSISTANT + if (MIBLEsensors[i].fertility==0xffff) MI32nullifyEndOfMQTT_DATA(); +#endif + } + } + } + if (MIBLEsensors[i].feature.Btn){ + if(MIBLEsensors[i].eventType.Btn +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif + ){ + ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); + } + } + } + if (MIBLEsensors[i].feature.PIR){ + if(MIBLEsensors[i].eventType.motion || !MI32.mode.triggeredTele){ + if(MI32.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); + ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); + } + else if(MIBLEsensors[i].eventType.noMotion && MI32.mode.triggeredTele){ + ResponseAppend_P(PSTR(",\"PIR\":0")); + } + } + + if (MIBLEsensors[i].type == FLORA && !MI32.mode.triggeredTele) { + if (MIBLEsensors[i].firmware[0] != '\0') { + ResponseAppend_P(PSTR(",\"Firmware\":\"%s\""), MIBLEsensors[i].firmware); + } + } + + if (MIBLEsensors[i].feature.NMT || !MI32.mode.triggeredTele){ + if(MIBLEsensors[i].eventType.NMT){ + ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); + } + } + if (MIBLEsensors[i].feature.bat){ + if(MIBLEsensors[i].eventType.bat || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ + if (MIBLEsensors[i].bat != 0x00 +#ifdef USE_HOME_ASSISTANT + ||(hass_mode!=-1) +#endif + ) { + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); +#ifdef USE_HOME_ASSISTANT + if (MIBLEsensors[i].bat == 0x00) MI32nullifyEndOfMQTT_DATA(); +#endif + } + } + } + if (MI32.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].RSSI); + + if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); + ResponseAppend_P(PSTR("}")); + mqtt_data[_positionCurlyBracket] = '{'; + MIBLEsensors[i].eventType.raw = 0; + if(MIBLEsensors[i].shallSendMQTT==1){ + MIBLEsensors[i].shallSendMQTT = 0; + continue; + } + } + MI32.mode.triggeredTele = 0; + + uint32_t _idx = 0; + for (auto _beacon : MIBLEbeacons){ + _idx++; + if(!_beacon.active) continue; + char _MAC[18]; + ToHex_P(_beacon.MAC,6,_MAC,18,':'); + ResponseAppend_P(PSTR(",\"Beacon%u\":{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\"," + "\"UUID\":\"0x%04x\",\"Time\":%u,\"RSSI\":%d}"), + _idx,_MAC,_beacon.CID,_beacon.SVC,_beacon.UUID,_beacon.time,_beacon.RSSI); + } +#ifdef USE_HOME_ASSISTANT + if(hass_mode==2){ + MI32.option.noSummary = _noSummarySave; + MI32.option.minimalSummary = _minimalSummarySave; + } +#endif +#ifdef USE_WEBSERVER + } else { + static uint16_t _page = 0; + static uint16_t _counter = 0; + int32_t i = _page * MI32.perPage; + uint32_t j = i + MI32.perPage; + if (j+1>MIBLEsensors.size()){ + j = MIBLEsensors.size(); + } + char stemp[5] ={0}; + if (MIBLEsensors.size()-(_page*MI32.perPage)>1 && MI32.perPage!=1) { + sprintf_P(stemp,"-%u",j); + } + if (MIBLEsensors.size()==0) i=-1; + + WSContentSend_PD(HTTP_MI32, i+1,stemp,MIBLEsensors.size()); + for (i; iFLORA) { + if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)) { + WSContentSend_THD(kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); + } + } +#ifdef USE_MI_DECRYPTION + if (MIBLEsensors[i].type==NLIGHT || MIBLEsensors[i].type==MJYD2S) { +#else + if (MIBLEsensors[i].type==NLIGHT) { +#endif + WSContentSend_PD(HTTP_EVENTS, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].events); + if(MIBLEsensors[i].NMT>0) WSContentSend_PD(HTTP_NMT, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].NMT); + } + if (MIBLEsensors[i].lux!=0x00ffffff) { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux); + } + if(MIBLEsensors[i].bat!=0x00){ + WSContentSend_PD(HTTP_BATTERY, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); + } + if (MIBLEsensors[i].type==YEERC){ + WSContentSend_PD(HTTP_LASTBUTTON, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].Btn); + } + } + _counter++; + if(_counter>3) { + _page++; + _counter=0; + } + if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; } + if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; } + + + uint32_t _idx=0; + if(MI32.mode.activeBeacon){ + WSContentSend_PD(HTTP_MI32_HL); + char _sbeacon[] = "Beacon1"; + for (auto &_beacon : MIBLEbeacons){ + _idx++; + if(!_beacon.active) continue; + WSContentSend_PD(HTTP_MI32_HL); + _sbeacon[6] = _idx + 0x30; + char _MAC[18]; + ToHex_P(_beacon.MAC,6,_MAC,18,':'); + WSContentSend_PD(HTTP_MI32_MAC, _sbeacon, D_MAC_ADDRESS, _MAC); + WSContentSend_PD(HTTP_RSSI, _sbeacon, _beacon.RSSI); + if(_beacon.CID!=0) WSContentSend_PD(PSTR("{s}Beacon%u CID{m}0x%04X{e}"),_idx, _beacon.CID); + if(_beacon.SVC!=0) WSContentSend_PD(PSTR("{s}Beacon%u SVC{m}0x%04X{e}"),_idx, _beacon.SVC); + if(_beacon.UUID!=0) WSContentSend_PD(PSTR("{s}Beacon%u UUID{m}0x%04X{e}"),_idx, _beacon.UUID); + WSContentSend_PD(PSTR("{s}Beacon%u Time{m}%u seconds{e}"),_idx, _beacon.time); + } + } +#endif + } +} + + + + + +bool Xsns62(uint8_t function) +{ + bool result = false; + if (FUNC_INIT == function){ + MI32Init(); + } + + if (MI32.mode.init) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MI32Every50mSecond(); + break; + case FUNC_EVERY_SECOND: + MI32EverySecond(false); + break; + case FUNC_COMMAND: + result = MI32Cmd(); + break; + case FUNC_JSON_APPEND: + MI32Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MI32Show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" +# 42 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" +#ifdef ESP8266 + +#ifdef USE_HM10 + +#define XSNS_62 62 + +#include +#include + +TasmotaSerial *HM10Serial; +#define HM10_BAUDRATE 115200 + +#define HM10_MAX_TASK_NUMBER 12 +uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; + +#define HM10_MAX_RX_BUF 384 + +struct { + uint8_t current_task_delay; + uint8_t last_command; + uint16_t perPage = 4; + uint16_t firmware; + uint32_t period; + uint32_t serialSpeed; + union { + uint32_t time; + uint8_t timebuf[4]; + }; + uint16_t autoScanInterval; + struct { + uint32_t awaiting:8; + uint32_t init:1; + uint32_t pending_task:1; + uint32_t connected:1; + uint32_t subscribed:1; + uint32_t autoScan:1; + uint32_t shallTriggerTele:1; + uint32_t triggeredTele:1; + } mode; + struct { + uint8_t sensor; + + } state; + struct { + uint32_t allwaysAggregate:1; + uint32_t showRSSI:1; + uint32_t ignoreBogusBattery:1; + uint32_t noSummary:1; + uint32_t minimalSummary:1; + uint32_t noRealTime:1; + } option; + char *rxBuffer; +} HM10; + +#pragma pack(1) + +struct LYWSD0x_HT_t{ + uint16_t temp; + uint8_t hum; + uint16_t volt; +}; +struct CGD1_HT_t{ + uint8_t spare; + uint16_t temp; + uint16_t hum; +}; +struct Flora_TLMF_t{ + uint16_t temp; + uint8_t spare; + uint32_t lux; + uint8_t moist; + uint16_t fert; + uint32_t ID; +}; + +struct mi_beacon_t{ + uint16_t frame; + uint16_t productID; + uint8_t counter; + uint8_t MAC[6]; + uint8_t spare; + uint8_t type; + uint8_t ten; + uint8_t size; + union { + struct{ + uint16_t temp; + uint16_t hum; + }HT; + uint8_t bat; + uint16_t temp; + uint16_t hum; + uint32_t lux; + uint8_t moist; + uint16_t fert; + uint32_t NMT; + struct{ + uint16_t num; + uint8_t longPress; + }Btn; + }; + uint8_t padding[12]; +}; + +struct ATCPacket_t{ + uint8_t MAC[6]; + int16_t temp; + uint8_t hum; + uint8_t batPer; + uint16_t batMV; + uint8_t frameCnt; +}; + +#pragma pack(0) + +struct mi_sensor_t{ + uint8_t type; + uint8_t lastCnt; + uint8_t shallSendMQTT; + uint8_t showedUp; + uint8_t MAC[6]; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t PIR:1; + uint32_t Btn:1; + }; + uint32_t raw; + } feature; + union { + struct { + uint32_t temp:1; + uint32_t hum:1; + uint32_t tempHum:1; + uint32_t lux:1; + uint32_t moist:1; + uint32_t fert:1; + uint32_t bat:1; + uint32_t NMT:1; + uint32_t motion:1; + uint32_t noMotion:1; + uint32_t Btn:1; + }; + uint32_t raw; + } eventType; + + int rssi; + uint32_t lastTime; + uint32_t lux; + float temp; + union { + struct { + uint8_t moisture; + uint16_t fertility; + char firmware[6]; + }; + struct { + float hum; + }; + struct { + uint16_t events; + uint32_t NMT; + }; + uint16_t Btn; + }; + union { + uint8_t bat; + }; +}; + + +std::vector MIBLEsensors; + + + + + +#define D_CMND_HM10 "HM10" + +const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; +const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; +const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto|Page"; + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 +#define CGG1 5 +#define CGD1 6 +#define NLIGHT 7 +#define MJYD2S 8 +#define YEERC 9 +#define MHOC401 10 +#define MHOC303 11 +#define ATC 12 + +#define HM10_TYPES 12 + +const uint16_t kHM10SlaveID[HM10_TYPES]={ + 0x0098, + 0x01aa, + 0x045b, + 0x055b, + 0x0347, + 0x0576, + 0x03dd, + 0x07f6, + 0x0153, + 0x0387, + 0x06d3, + 0x0a1c + }; + +const char kHM10DeviceType1[] PROGMEM = "Flora"; +const char kHM10DeviceType2[] PROGMEM = "MJ_HT_V1"; +const char kHM10DeviceType3[] PROGMEM = "LYWSD02"; +const char kHM10DeviceType4[] PROGMEM = "LYWSD03"; +const char kHM10DeviceType5[] PROGMEM = "CGG1"; +const char kHM10DeviceType6[] PROGMEM = "CGD1"; +const char kHM10DeviceType7[] PROGMEM = "NLIGHT"; +const char kHM10DeviceType8[] PROGMEM = "MJYD2S"; +const char kHM10DeviceType9[] PROGMEM = "YEERC"; +const char kHM10DeviceType10[] PROGMEM ="MHOC401"; +const char kHM10DeviceType11[] PROGMEM ="MHOC303"; +const char kHM10DeviceType12[] PROGMEM ="ATC"; + +const char * kHM10DeviceType[] PROGMEM = {kHM10DeviceType1,kHM10DeviceType2,kHM10DeviceType3,kHM10DeviceType4,kHM10DeviceType5,kHM10DeviceType6,kHM10DeviceType7,kHM10DeviceType8,kHM10DeviceType9,kHM10DeviceType10,kHM10DeviceType11,kHM10DeviceType12}; + + + + + +enum HM10_Commands { + CMND_HM10_DISC_SCAN, + CMND_HM10_AT, + CMND_HM10_PERIOD, + CMND_HM10_BAUD, + CMND_HM10_TIME, + CMND_HM10_AUTO, + CMND_HM10_PAGE + }; + +enum HM10_awaitData: uint8_t { + none = 0, + tempHumLY = 1, + TLMF = 2, + bat = 3, + tempHumCGD1 = 4, + discScan = 5, + tempHumMJ = 6 + }; + + + + + +#define TASK_HM10_NOTASK 0 +#define TASK_HM10_ROLE1 1 +#define TASK_HM10_IMME1 2 +#define TASK_HM10_RENEW 3 +#define TASK_HM10_RESET 4 +#define TASK_HM10_DISC 5 +#define TASK_HM10_CONN 6 +#define TASK_HM10_VERSION 7 +#define TASK_HM10_NAME 8 +#define TASK_HM10_FEEDBACK 9 +#define TASK_HM10_DISCONN 10 +#define TASK_HM10_SUB_L3 11 + +#define TASK_HM10_SCAN9 13 +#define TASK_HM10_UN_L3 14 + +#define TASK_HM10_READ_BT_L3 16 +#define TASK_HM10_SUB_L2 17 +#define TASK_HM10_UN_L2 18 +#define TASK_HM10_READ_BT_L2 19 +#define TASK_HM10_TIME_L2 20 +#define TASK_HM10_SHOW0 21 +#define TASK_HM10_READ_BF_FL 22 +#define TASK_HM10_CALL_TLMF_FL 23 +#define TASK_HM10_READ_TLMF_FL 24 +#define TASK_HM10_SUB_HT_CGD1 25 +#define TASK_HM10_UN_HT_CGD1 26 +#define TASK_HM10_READ_B_CGD1 27 + +#define TASK_HM10_READ_B_MJ 29 +#define TASK_HM10_SUB_HT_MJ 30 + +#define TASK_HM10_STATUS_EVENT 32 + +#define TASK_HM10_DONE 99 + + + + + +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ + HM10_TASK_LIST[slot][0] = task; + HM10_TASK_LIST[slot][1] = delay; + HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; + HM10.current_task_delay = HM10_TASK_LIST[0][1]; +} + +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ + HM10.last_command = HM10_TASK_LIST[slot][0]; + HM10_TASK_LIST[slot][0] = task; +} + +void HM10_ReverseMAC(uint8_t _mac[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _mac[i]; + } + memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); +} + + + + + +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_ROLE1,1,1); + HM10_Launchtask(TASK_HM10_IMME1,2,1); + HM10_Launchtask(TASK_HM10_RESET,3,1); + HM10_Launchtask(TASK_HM10_VERSION,4,10); + HM10_Launchtask(TASK_HM10_SCAN9,5,2); + HM10_Launchtask(TASK_HM10_DISC,6,2); + HM10_Launchtask(TASK_HM10_STATUS_EVENT,7,2); + } + +void HM10_Discovery_Scan(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_DISC,1,1); + HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); + } + +void HM10_Read_LYWSD03(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L3,2,20); + HM10_Launchtask(TASK_HM10_UN_L3,3,80); + + HM10_Launchtask(TASK_HM10_DISCONN,4,5); + } + +void HM10_Read_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L2,2,20); + HM10_Launchtask(TASK_HM10_UN_L2,3,80); + HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Time_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,0); + HM10_Launchtask(TASK_HM10_CONN,1,5); + HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); + HM10_Launchtask(TASK_HM10_TIME_L2,3,20); + HM10_Launchtask(TASK_HM10_DISCONN,4,5); + } + +void HM10_Read_Flora(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,0); + HM10_Launchtask(TASK_HM10_CONN,1,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,2,5); + HM10_Launchtask(TASK_HM10_READ_BF_FL,3,20); + HM10_Launchtask(TASK_HM10_CALL_TLMF_FL,4,30); + HM10_Launchtask(TASK_HM10_DISCONN,5,10); + } + +void HM10_Read_CGD1(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_HT_CGD1,2,20); + HM10_Launchtask(TASK_HM10_UN_HT_CGD1,3,10); + HM10_Launchtask(TASK_HM10_READ_B_CGD1,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Read_MJ_HT_V1(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_READ_B_MJ,2,20); + HM10_Launchtask(TASK_HM10_SUB_HT_MJ,3,10); + HM10_Launchtask(TASK_HM10_DISCONN,4,5); + } +# 444 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" +uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){ + + DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type); + bool _success = false; + for (uint32_t i=0;ibegin(HM10.serialSpeed)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); + if (HM10Serial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("%s: claim HW"),D_CMND_HM10); + } + HM10_Reset(); + HM10.mode.pending_task = 1; + HM10.mode.init = 1; + HM10.period = Settings.tele_period; + DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); + + + HM10.option.noRealTime = 1; + HM10.option.allwaysAggregate = 1; + HM10.option.showRSSI = 0; + HM10.option.ignoreBogusBattery = 1; + HM10.option.noSummary = 0; + HM10.option.minimalSummary = 0; + + HM10.rxBuffer = new char[HM10_MAX_RX_BUF]; + } + return; +} + + + + + +void HM10parseMiBeacon(char * _buf, uint32_t _slot){ + float _tempFloat; + mi_beacon_t _beacon; + if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1){ + memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); + memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); + } + else{ + memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon)); + } + HM10_ReverseMAC(_beacon.MAC); + if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){ + if (MIBLEsensors[_slot].showedUp>3) return; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: remove garbage sensor"),D_CMND_HM10); + DEBUG_SENSOR_LOG(PSTR("%s i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[_slot].MAC[5], MIBLEsensors[_slot].MAC[4],MIBLEsensors[_slot].MAC[3],MIBLEsensors[_slot].MAC[2],MIBLEsensors[_slot].MAC[1],MIBLEsensors[_slot].MAC[0]); + DEBUG_SENSOR_LOG(PSTR("%s n: %x %x %x %x %x %x"),D_CMND_HM10, _beacon.MAC[5], _beacon.MAC[4], _beacon.MAC[3],_beacon.MAC[2],_beacon.MAC[1],_beacon.MAC[0]); + MIBLEsensors.erase(MIBLEsensors.begin()+_slot); + return; + } + if (MIBLEsensors[_slot].showedUp<4) MIBLEsensors[_slot].showedUp++; + + DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); + DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); + + + if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){ + DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); + return; + } + DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot); + switch(_beacon.type){ + case 0x01: + MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6; + MIBLEsensors[_slot].eventType.Btn = 1; + + break; + case 0x04: + _tempFloat=(float)(_beacon.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); + MIBLEsensors[_slot].eventType.temp = 1; + } + DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); + break; + case 0x06: + _tempFloat=(float)(_beacon.hum)/10.0f; + if(_tempFloat<101){ + MIBLEsensors[_slot].hum=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); + MIBLEsensors[_slot].eventType.hum = 1; + } + DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum); + break; + case 0x07: + if(MIBLEsensors[_slot].type==MJYD2S){ + MIBLEsensors[_slot].eventType.noMotion = 1; + } + MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; + DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); + break; + case 0x08: + if(_beacon.moist<101){ + MIBLEsensors[_slot].moisture=_beacon.moist; + DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); + MIBLEsensors[_slot].eventType.moist = 1; + } + DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); + break; + case 0x09: + if(_beacon.fert<65535){ + MIBLEsensors[_slot].fertility=_beacon.fert; + DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); + MIBLEsensors[_slot].eventType.fert = 1; + } + DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); + break; + case 0x0a: + if(_beacon.bat<101){ + MIBLEsensors[_slot].bat = _beacon.bat; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + MIBLEsensors[_slot].eventType.bat = 1; + } + DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat); + break; + case 0x0d: + _tempFloat=(float)(_beacon.HT.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); + } + _tempFloat=(float)(_beacon.HT.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); + break; + } + if(MIBLEsensors[_slot].eventType.raw == 0) return; + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; +} + +void HM10parseATC(char * _buf, uint32_t _slot){ + ATCPacket_t *_packet = (ATCPacket_t*)_buf; + if(memcmp(_packet->MAC,MIBLEsensors.at(_slot).MAC,6)!=0) return; + MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; + MIBLEsensors.at(_slot).hum = (float)_packet->hum; + MIBLEsensors.at(_slot).bat = _packet->batPer; + MIBLEsensors[_slot].shallSendMQTT = 1; +} + +char* HM10ParseResponse(char *buf, uint16_t bufsize) { + if (!strncmp(buf,"HMSoft",6)) { + const char* _fw = "000"; + memcpy((void *)_fw,(void *)(buf+8),3); + HM10.firmware = atoi(_fw); + DEBUG_SENSOR_LOG(PSTR("%s: Firmware: %d"),D_CMND_HM10, HM10.firmware); + return buf; + } + char * _pos = nullptr; + uint32_t _idx = 0; + char _subStr[] = "SA:"; + while(_pos = (char*) memchr(buf+_idx, 'I', 60)){ + _idx=_pos-buf; + if(memcmp(&_pos+1,_subStr,3)){ + break; + } + } + if(_pos) { + uint8_t _newMacArray[6] = {0}; + memcpy((void *)_newMacArray,(void *)(_pos+4),6); + uint32_t _rssi = 255- (uint8_t)(_pos[11]); + HM10_ReverseMAC(_newMacArray); + DEBUG_SENSOR_LOG(PSTR("%s: MAC-array: %02x%02x%02x%02x%02x%02x"),D_CMND_HM10,_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); + uint16_t _type=0xffff; + + for (_idx =10;_idx<32;_idx++){ + if((uint8_t)_pos[_idx] == 0xfe){ + if((uint8_t)_pos[_idx-2] == 0x16 && (uint8_t)_pos[_idx-1] == 0x95){ + _pos = _pos+_idx+1; + _type = (uint8_t)_pos[3]*256 + (uint8_t)_pos[2]; + DEBUG_SENSOR_LOG(PSTR("%s: type %04x _ %02x %02x"),D_CMND_HM10,_type, _pos[3],_pos[2]); + break; + } + } + else if ((uint8_t)_pos[_idx] == 0x1a){ + if ((uint8_t)_pos[_idx+1] == 0x18){ + if((uint8_t)_pos[_idx+4] == 0x95 && (uint8_t)_pos[_idx+3] == 0x16) continue; + _type = 0xa1c; + _pos = _pos+_idx+2; + break; + } + } + } + uint16_t _slot = MIBLEgetSensorSlot(_newMacArray, _type, _rssi); + if(_slot!=0xff){ + if (_type==0xa1c) HM10parseATC(_pos,_slot); + else HM10parseMiBeacon(_pos,_slot); + } + if(bufsize>64) return _pos+12; + else return nullptr; + } + else if (strstr(buf, "LOST")){ + HM10.current_task_delay = 0; + HM10.mode.connected = false; + } + else if (strstr(buf, "CONNF")){ + HM10.mode.connected = false; + HM10.current_task_delay = 0; + } + else if (strstr(buf, "CONN")){ + HM10.current_task_delay = 0; + } + else { + DEBUG_SENSOR_LOG(PSTR("%s: empty response"),D_CMND_HM10); + return buf; + } + return _pos; +} + +void HM10readHT_LY(char *_buf){ + + if(_buf[0]==0x4f && _buf[1]==0x4b) return; + if(_buf[0] != 0 && _buf[1] != 0){ + LYWSD0x_HT_t *packet = (LYWSD0x_HT_t*)_buf; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u"),D_CMND_HM10,packet->temp,packet->hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(packet->temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + MIBLEsensors[_slot].showedUp=255; + } + _tempFloat=(float)packet->hum; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){ + MIBLEsensors[_slot].bat = ((float)packet->volt-2100.0f)/12.0f; + MIBLEsensors[_slot].eventType.bat = 1; + } + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; + } +} + +void HM10readHT_CGD1(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b) return; + if(_buf[0] == 0){ + if(_buf[1]==0 && _buf[2]==0 && _buf[3]==0 && _buf[4]==0) return; + CGD1_HT_t *_packet = (CGD1_HT_t*)_buf; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H * 100: %u"),D_CMND_HM10,_packet->temp,_packet->hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(_packet->temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + MIBLEsensors[_slot].showedUp=255; + } + _tempFloat=(float)_packet->hum/100.0f; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; + } +} + +void HM10readHT_MJ_HT_V1(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]!=0x54 && _buf[1]!=0x3d) return; + + + uint32_t _temp = (atoi(_buf+2) * 10) + atoi(_buf+5); + uint32_t _hum = (atoi(_buf+9) * 10) + atoi(_buf+12); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, H * 10: %u"),D_CMND_HM10,_temp,_hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)_temp/10.0f; + if(_tempFloat<60){ + MIBLEsensors[_slot].temp=_tempFloat; + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + MIBLEsensors[_slot].showedUp=255; + } + _tempFloat=(float)_hum/10.0f; + if(_tempFloat<100){ + MIBLEsensors[_slot].hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated")); + } + MIBLEsensors[_slot].eventType.tempHum = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; +} + +void HM10readTLMF(char *_buf){ + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)_buf,16); + Flora_TLMF_t *_packet = (Flora_TLMF_t*)_buf; + if(_packet->ID==0xFB003C02){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, L: %u, M: %u, F: %u"),D_CMND_HM10,_packet->temp,_packet->lux,_packet->moist,_packet->fert); + uint32_t _slot = HM10.state.sensor; + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + MIBLEsensors[_slot].showedUp=255; + + static float _tempFloat; + _tempFloat=(float)(_packet->temp)/10.0f; + MIBLEsensors[_slot].temp=_tempFloat; + + MIBLEsensors[_slot].lux = _packet->lux; + MIBLEsensors[_slot].moisture = _packet->moist; + MIBLEsensors[_slot].fertility = _packet->fert; + MIBLEsensors[_slot].eventType.temp = 1; + MIBLEsensors[_slot].eventType.lux = 1; + MIBLEsensors[_slot].eventType.moist = 1; + MIBLEsensors[_slot].eventType.fert = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; + + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + } +} + +bool HM10readBat(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b) return false; + uint32_t _slot = HM10.state.sensor; + + + + if(_buf[0] != 0){ + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_HM10,_buf[0]); + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + if(_buf[0]<101){ + MIBLEsensors[_slot].bat=_buf[0]; + MIBLEsensors[_slot].showedUp=255; + MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + HM10.mode.shallTriggerTele = 1; + return true; + } + } + return false; +} + + + + + +bool HM10SerialHandleFeedback(){ + bool success = false; + uint32_t i = 0; + + while(HM10Serial->available()) { + if(iread(); + } + i++; + success = true; + } + + if(i==0){ + if(HM10.mode.shallTriggerTele){ + HM10.mode.shallTriggerTele=0; + if(HM10.option.noRealTime){ + HM10.mode.triggeredTele=0; + return success; + } + HM10.mode.triggeredTele=1; + HM10triggerTele(); + } + return success; + } + + switch (HM10.mode.awaiting){ + case bat: + if (HM10.mode.connected) { + if (HM10readBat(HM10.rxBuffer)){ + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + } + } + break; + case tempHumLY: + if (HM10.mode.connected) HM10readHT_LY(HM10.rxBuffer); + break; + case tempHumCGD1: + if (HM10.mode.connected) HM10readHT_CGD1(HM10.rxBuffer); + break; + case TLMF: + if (HM10.mode.connected) HM10readTLMF(HM10.rxBuffer); + break; + case discScan: + if(success) { + char *_src = HM10ParseResponse(HM10.rxBuffer,i); + if(_src){ + HM10ParseResponse(_src,i-(_src-HM10.rxBuffer)); + } + } + break; + case tempHumMJ: + if (HM10.mode.connected) HM10readHT_MJ_HT_V1(HM10.rxBuffer); + break; + case none: + if(success) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: response: %s"),D_CMND_HM10, (char *)HM10.rxBuffer); + + + + HM10ParseResponse(HM10.rxBuffer,i); + } + break; + } + memset(HM10.rxBuffer,0,i); + return success; +} + + + + + +void HM10_TaskEvery100ms(){ + if (HM10.current_task_delay == 0) { + uint8_t i = 0; + bool runningTaskLoop = true; + while (runningTaskLoop) { + switch(HM10_TASK_LIST[i][0]) { + case TASK_HM10_ROLE1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set role to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+ROLE1"); + break; + case TASK_HM10_IMME1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set imme to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+IMME1"); + break; + case TASK_HM10_DISC: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: start discovery"),D_CMND_HM10); + HM10.current_task_delay = 90; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = discScan; + HM10Serial->write("AT+DISA?"); + break; + case TASK_HM10_VERSION: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read version"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+VERR?"); + break; + case TASK_HM10_NAME: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read name"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NAME?"); + break; + case TASK_HM10_CONN: + char _con[20]; + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors[HM10.state.sensor].MAC[0],MIBLEsensors[HM10.state.sensor].MAC[1],MIBLEsensors[HM10.state.sensor].MAC[2],MIBLEsensors[HM10.state.sensor].MAC[3],MIBLEsensors[HM10.state.sensor].MAC[4],MIBLEsensors[HM10.state.sensor].MAC[5]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: %s connect %s"),D_CMND_HM10,kHM10DeviceType[MIBLEsensors[HM10.state.sensor].type-1],_con); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write(_con); + HM10.mode.awaiting = none; + HM10.mode.connected = true; + break; + case TASK_HM10_DISCONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: disconnect"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT"); + break; + case TASK_HM10_RESET: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: Reset Device"),D_CMND_HM10); + HM10Serial->write("AT+RESET"); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + break; + case TASK_HM10_SUB_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); + HM10.current_task_delay = 25; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + HM10.mode.awaiting = tempHumLY; + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON0037"); + break; + case TASK_HM10_UN_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + HM10Serial->write("AT+NOTIFYOFF0037"); + break; + case TASK_HM10_SUB_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); + HM10.current_task_delay = 85; + HM10.mode.awaiting = tempHumLY; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_ON003C"); + else HM10Serial->write("AT+NOTIFY_ON004B"); + break; + case TASK_HM10_UN_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_OFF003C"); + else HM10Serial->write("AT+NOTIFY_OFF004B"); + break; + case TASK_HM10_TIME_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set time"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.time = Rtc.utc_time; + HM10Serial->write("AT+SEND_DATAWR002F"); + HM10Serial->write(HM10.timebuf,4); + HM10Serial->write(Rtc.time_timezone / 60); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); + break; +# 1079 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" + case TASK_HM10_READ_BT_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0043"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+READDATA0043?"); + else HM10Serial->write("AT+READDATA0052?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_READ_BF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0038"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0038?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_CALL_TLMF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: write to handle 0033"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_READ_TLMF_FL,i); + runningTaskLoop = false; + HM10Serial->write("AT+SEND_DATAWR0033"); + HM10Serial->write(0xa0); + HM10Serial->write(0x1f); + HM10.mode.awaiting = none; + break; + case TASK_HM10_READ_TLMF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0035"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0035?"); + HM10.mode.awaiting = TLMF; + break; + case TASK_HM10_READ_B_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0011"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0011?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_SUB_HT_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe 4b"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = tempHumCGD1; + HM10Serial->write("AT+NOTIFY_ON004b"); + break; + case TASK_HM10_UN_HT_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe 4b"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + HM10Serial->write("AT+NOTIFYOFF004b"); + break; + case TASK_HM10_SCAN9: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: scan time to 9"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+SCAN9"); + break; + case TASK_HM10_READ_B_MJ: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0x18"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0018?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_SUB_HT_MJ: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe to 0x0f"),D_CMND_HM10); + HM10.current_task_delay = 10; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON000F"); + HM10.mode.awaiting = tempHumMJ; + break; + case TASK_HM10_FEEDBACK: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: get response"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + runningTaskLoop = false; + break; + case TASK_HM10_STATUS_EVENT: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: show status"),D_CMND_HM10); + HM10StatusInfo(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + runningTaskLoop = false; + break; + case TASK_HM10_DONE: + + + if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { + DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); + for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); + HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; + HM10_TASK_LIST[j][1] = 0; + } + runningTaskLoop = false; + HM10.mode.pending_task = 0; + break; + } + } + i++; + } + } + else { + HM10.current_task_delay--; + } +} + +void HM10StatusInfo() { + + + + + + + Response_P(PSTR("{%s:{\"found\":%u}}"), D_CMND_HM10, MIBLEsensors.size()); + XdrvRulesProcess(); +} + + + + + + +void HM10EverySecond(bool restart){ + static uint32_t _counter = 0; + static uint32_t _nextSensorSlot = 0; + static uint32_t _lastDiscovery = 0; + + if(restart){ + _counter = 0; + _lastDiscovery = 0; + return; + } + + if(HM10.firmware == 0) return; + if(HM10.mode.pending_task == 1) return; + if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return; + + if((HM10.period-_counter)>15 && HM10.mode.autoScan) { + if(_counter-_lastDiscovery>HM10.autoScanInterval){ + HM10_Discovery_Scan(); + HM10.mode.pending_task = 1; + _counter+=12; + _lastDiscovery = _counter; + return; + } + } + + if(_counter==0) { + HM10.state.sensor = _nextSensorSlot; + _nextSensorSlot++; + HM10.mode.pending_task = 1; + switch(MIBLEsensors[HM10.state.sensor].type){ + case FLORA: + HM10_Read_Flora(); + break; + case MJ_HT_V1: case CGG1: + HM10_Read_MJ_HT_V1(); + break; + case LYWSD02: case MHOC303: + HM10_Read_LYWSD02(); + break; + case LYWSD03MMC: case MHOC401: + HM10_Read_LYWSD03(); + break; + case CGD1: + HM10_Read_CGD1(); + break; + default: + HM10.mode.pending_task = 0; + } + if (HM10.state.sensor==MIBLEsensors.size()-1) { + _nextSensorSlot= 0; + _counter++; + } + DEBUG_SENSOR_LOG(PSTR("%s: active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); + } + else _counter++; + if (_counter>HM10.period) { + _counter = 0; + _lastDiscovery = 0; + } +} + + + + + +bool HM10Cmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_HM10); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); + switch (command_code) { + case CMND_HM10_PERIOD: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload==1) { + HM10EverySecond(true); + XdrvMailbox.payload = HM10.period; + } + else { + HM10.period = XdrvMailbox.payload; + } + } + else { + XdrvMailbox.payload = HM10.period; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_AUTO: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload>0) { + HM10.mode.autoScan = 1; + HM10.autoScanInterval = XdrvMailbox.payload; + } + else { + HM10.mode.autoScan = 0; + HM10.autoScanInterval = 0; + } + } + else { + XdrvMailbox.payload = HM10.autoScanInterval; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_BAUD: + if (XdrvMailbox.data_len > 0) { + HM10.serialSpeed = XdrvMailbox.payload; + HM10Serial->begin(HM10.serialSpeed); + } + else { + XdrvMailbox.payload = HM10.serialSpeed; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_TIME: + if (XdrvMailbox.data_len > 0) { + if(MIBLEsensors.size()>XdrvMailbox.payload){ + if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02){ + HM10.state.sensor = XdrvMailbox.payload; + HM10_Time_LYWSD02(); + } + } + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_PAGE: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload == 0) XdrvMailbox.payload = HM10.perPage; + HM10.perPage = XdrvMailbox.payload; + } + else XdrvMailbox.payload = HM10.perPage; + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_AT: + HM10Serial->write("AT"); + if (strlen(XdrvMailbox.data)!=0) { + HM10Serial->write("+"); + HM10Serial->write(XdrvMailbox.data); + Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); + } + else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); + break; + case CMND_HM10_DISC_SCAN: + HM10_Discovery_Scan(); + Response_P(S_JSON_HM10_COMMAND, command, ""); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + +void HM10triggerTele(void){ + HM10.mode.triggeredTele = 1; + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + #ifdef USE_RULES + RulesTeleperiod(); + #endif + } +} + + + + + +const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}"; +const char HTTP_HM10_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; +const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; +const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; + +void HM10Show(bool json) +{ + if (json) { + if(!HM10.mode.triggeredTele){ + if(HM10.option.noSummary) return; + } + + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(HM10.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; + if(HM10.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; + + ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), + kHM10DeviceType[MIBLEsensors[i].type-1], + MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); + + uint32_t _positionCurlyBracket = strlen(mqtt_data); + + if((!HM10.mode.triggeredTele && !HM10.option.minimalSummary)||HM10.mode.triggeredTele){ + bool tempHumSended = false; + if(MIBLEsensors[i].feature.tempHum){ + if(MIBLEsensors[i].eventType.tempHum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ + if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)) { + ResponseAppend_P(PSTR(",")); + ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); + tempHumSended = true; + } + } + } + if(MIBLEsensors[i].feature.temp && !tempHumSended){ + if(MIBLEsensors[i].eventType.temp || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].temp)) { + char temperature[FLOATSZ]; + dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + } + } + if(MIBLEsensors[i].feature.hum && !tempHumSended){ + if(MIBLEsensors[i].eventType.hum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) { + if (!isnan(MIBLEsensors[i].hum)) { + char hum[FLOATSZ]; + dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); + } + } + } + if (MIBLEsensors[i].feature.lux){ + if(MIBLEsensors[i].eventType.lux || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ + if (MIBLEsensors[i].lux!=0x0ffffff) { + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); + } + } + } + if (MIBLEsensors[i].feature.moist){ + if(MIBLEsensors[i].eventType.moist || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ + if (MIBLEsensors[i].moisture!=0xff) { + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); + } + } + } + if (MIBLEsensors[i].feature.fert){ + if(MIBLEsensors[i].eventType.fert || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ + if (MIBLEsensors[i].fertility!=0xffff) { + ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); + } + } + } + if (MIBLEsensors[i].feature.Btn){ + if(MIBLEsensors[i].eventType.Btn){ + ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); + } + } + } + if (MIBLEsensors[i].feature.PIR){ + if(MIBLEsensors[i].eventType.motion || !HM10.mode.triggeredTele){ + if(HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); + ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); + } + else if(MIBLEsensors[i].eventType.noMotion && HM10.mode.triggeredTele){ + ResponseAppend_P(PSTR(",\"PIR\":0")); + } + } + + if (MIBLEsensors[i].type == FLORA && !HM10.mode.triggeredTele) { + if (MIBLEsensors[i].firmware[0] != '\0') { + ResponseAppend_P(PSTR(",\"Firmware\":\"%s\""), MIBLEsensors[i].firmware); + } + } + + if (MIBLEsensors[i].feature.NMT || !HM10.mode.triggeredTele){ + if(MIBLEsensors[i].eventType.NMT){ + ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); + } + } + if (MIBLEsensors[i].feature.bat){ + if(MIBLEsensors[i].eventType.bat || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ + if (MIBLEsensors[i].bat != 0x00) { + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); + } + } + } + if (HM10.option.showRSSI && HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi); + + + if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); + ResponseAppend_P(PSTR("}")); + mqtt_data[_positionCurlyBracket] = '{'; + MIBLEsensors[i].eventType.raw = 0; + if(MIBLEsensors[i].shallSendMQTT==1){ + MIBLEsensors[i].shallSendMQTT = 0; + continue; + } + } + HM10.mode.triggeredTele = 0; + +#ifdef USE_WEBSERVER + } else { + static uint16_t _page = 0; + static uint16_t _counter = 0; + int32_t i = _page * HM10.perPage; + uint32_t j = i + HM10.perPage; + if (j+1>MIBLEsensors.size()){ + j = MIBLEsensors.size(); + } + char stemp[5] ={0}; + if (MIBLEsensors.size()-(_page*HM10.perPage)>1 && HM10.perPage!=1) { + sprintf_P(stemp,"-%u",j); + } + if (MIBLEsensors.size()==0) i=-1; + + WSContentSend_PD(HTTP_HM10, HM10.firmware, i+1,stemp,MIBLEsensors.size()); + for (i; iFLORA){ + if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){ + WSContentSend_THD(kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); + } + } + if(MIBLEsensors[i].bat!=0x00){ + WSContentSend_PD(HTTP_BATTERY, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); + } + WSContentSend_PD(HTTP_RSSI, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].rssi); + } + _counter++; + if(_counter>3) { + _page++; + _counter=0; + } + if(MIBLEsensors.size()%HM10.perPage==0 && _page==MIBLEsensors.size()/HM10.perPage) _page=0; + if(_page>MIBLEsensors.size()/HM10.perPage) _page=0; +#endif + } +} + + + + + +bool Xsns62(uint8_t function) +{ + bool result = false; + + if (PinUsed(GPIO_HM10_RX) && PinUsed(GPIO_HM10_TX)) { + switch (function) { + case FUNC_INIT: + HM10SerialInit(); + break; + case FUNC_EVERY_50_MSECOND: + HM10SerialHandleFeedback(); + break; + case FUNC_EVERY_100_MSECOND: + if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { + HM10_TaskEvery100ms(); + } + break; + case FUNC_EVERY_SECOND: + HM10EverySecond(false); + break; + case FUNC_COMMAND: + result = HM10Cmd(); + break; + case FUNC_JSON_APPEND: + HM10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HM10Show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" +# 21 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" +#ifdef USE_I2C +#ifdef USE_AHT1x +# 45 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" +#define XSNS_63 63 +#define XI2C_43 43 + +#define AHT1X_ADDR1 0x38 +#define AHT1X_ADDR2 0x39 + +#define AHT1X_MAX_SENSORS 2 + +#define AHT_HUMIDITY_CONST 100 +#define AHT_TEMPERATURE_CONST 200 +#define AHT_TEMPERATURE_OFFSET 50 +#define KILOBYTE_CONST 1048576.0f + +#define AHT1X_CMD_DELAY 40 +#define AHT1X_RST_DELAY 30 +#define AHT1X_MEAS_DELAY 80 + +#ifdef USE_AHT2x + #define AHTX_CMD 0xB1 + const char ahtTypes[] PROGMEM = "AHT2X|AHT2X"; +#else + #define AHTX_CMD 0xE1 + const char ahtTypes[] PROGMEM = "AHT1X|AHT1X"; +#endif + +uint8_t AHTSetCalCmd[3] = { AHTX_CMD, 0x08, 0x00 }; +uint8_t AHTSetCycleCmd[3] = { AHTX_CMD, 0x28, 0x00 }; +uint8_t AHTMeasureCmd[3] = { 0xAC, 0x33, 0x00 }; +uint8_t AHTResetCmd = 0xBA; + +struct { + bool write_ok = false; + uint8_t addresses[2] = { AHT1X_ADDR1, AHT1X_ADDR2 }; + uint8_t count = 0; + uint8_t Pcount = 0; +} aht1x; + +struct { + float humidity = NAN; + float temperature = NAN; + uint8_t address; + char types[6]; +} aht1x_sensors[AHT1X_MAX_SENSORS]; + +bool AHT1XWrite(uint8_t aht1x_idx) { + Wire.beginTransmission(aht1x_sensors[aht1x_idx].address); + Wire.write(AHTMeasureCmd, 3); + if (Wire.endTransmission() != 0) + return false; + return true; +} + +bool AHT1XRead(uint8_t aht1x_idx) { + uint8_t data[6]; + Wire.requestFrom(aht1x_sensors[aht1x_idx].address, (uint8_t) 6); + + for(uint8_t i = 0; Wire.available() > 0; i++) { + data[i] = Wire.read(); + } + if (data[0] & 0x80) + return false; + + aht1x_sensors[aht1x_idx].humidity = (((data[1] << 12)| (data[2] << 4) | data[3] >> 4) * AHT_HUMIDITY_CONST / KILOBYTE_CONST); + aht1x_sensors[aht1x_idx].temperature = ((AHT_TEMPERATURE_CONST * (((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]) / KILOBYTE_CONST) - AHT_TEMPERATURE_OFFSET); + + return (!isnan(aht1x_sensors[aht1x_idx].temperature) && !isnan(aht1x_sensors[aht1x_idx].humidity) && (aht1x_sensors[aht1x_idx].humidity != 0)); +} + + + + + +void AHT1XPoll(void) { + aht1x.Pcount++; + switch (aht1x.Pcount) { + case 10: + aht1x.write_ok = AHT1XWrite(0); + break; + case 11: + if (aht1x.write_ok) AHT1XRead(0); + aht1x.Pcount = 0; + break; + } +} + +unsigned char AHT1XReadStatus(uint8_t aht1x_address) { + uint8_t result = 0; + + + + + Wire.requestFrom(aht1x_address, (uint8_t) 1); + result = Wire.read(); + return result; +} + +void AHT1XReset(uint8_t aht1x_address) { + Wire.beginTransmission(aht1x_address); + Wire.write(AHTResetCmd); + Wire.endTransmission(); + delay(AHT1X_RST_DELAY); +} + + +bool AHT1XInit(uint8_t aht1x_address) { + Wire.beginTransmission(aht1x_address); + Wire.write(AHTSetCalCmd, 3); + if (Wire.endTransmission() != 0) + return false; + delay(AHT1X_CMD_DELAY); + if(AHT1XReadStatus(aht1x_address) & 0x08) + return true; + return false; +} + +void AHT1XDetect(void) { + for (uint8_t i = 0; i < AHT1X_MAX_SENSORS; i++) { + if (!I2cSetDevice(aht1x.addresses[i])) {continue;} + if (AHT1XInit(aht1x.addresses[i])) { + aht1x_sensors[aht1x.count].address = aht1x.addresses[i]; + GetTextIndexed(aht1x_sensors[aht1x.count].types, sizeof(aht1x_sensors[aht1x.count].types), i, ahtTypes); + I2cSetActiveFound(aht1x_sensors[aht1x.count].address, aht1x_sensors[aht1x.count].types); + aht1x.count++; + break; + } + } +} + +void AHT1XShow(bool json) { + for (uint32_t i = 0; i < aht1x.count; i++) { + float tem = ConvertTemp(aht1x_sensors[i].temperature); + float hum = ConvertHumidity(aht1x_sensors[i].humidity); + char types[11]; + snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), aht1x_sensors[i].types, IndexSeparator(), aht1x_sensors[i].address); + TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, tem, hum); + } +} + + + + + +bool Xsns63(uint8_t function) +{ + if (!I2cEnabled(XI2C_43)) { return false; } + bool result = false; + + if (FUNC_INIT == function) { + AHT1XDetect(); + } + else if (aht1x.count) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + AHT1XPoll(); + break; + case FUNC_JSON_APPEND: + AHT1XShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AHT1XShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_64_hrxl.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_64_hrxl.ino" +#ifdef USE_HRXL + + + + + + + +#define XSNS_64 64 + +#include + +#define HRXL_READ_TIMEOUT 400 + +TasmotaSerial *HRXLSerial = nullptr; + +uint32_t hrxl_distance_mm = 0; +bool hrxl_found = false; + + + +void HRXLInit(void) +{ + hrxl_found = false; + if (PinUsed(GPIO_HRXL_RX)) + { + HRXLSerial = new TasmotaSerial(Pin(GPIO_HRXL_RX), -1, 1); + if (HRXLSerial->begin(9600)) + { + if (HRXLSerial->hardwareSerial()) + ClaimSerial(); + hrxl_found = true; + HRXLSerial->setTimeout(HRXL_READ_TIMEOUT); + } + } +} + +void HRXLEverySecond(void) +{ + if (!hrxl_found) + return; + + int num_read=0; + int sum=0; + while (HRXLSerial->available()>5) + { + if (HRXLSerial->read() != 'R') + continue; + + int d = HRXLSerial->parseInt(); + if (d >= 30 && d<=5000) + { + sum += d; + num_read++; + } + } + if (num_read>1) + hrxl_distance_mm = int(sum / num_read); + +} + + +void HRXLShow(bool json) +{ + char types[5] = "HRXL"; + if (json) + { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_DISTANCE "\":%d}"), types, hrxl_distance_mm); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_RANGE, types, hrxl_distance_mm); +#endif + } +} + + + + + +bool Xsns64(uint8_t function) +{ + if (!PinUsed(GPIO_HRXL_RX)) { return false; } + + switch (function) + { + case FUNC_INIT: + HRXLInit(); + break; + case FUNC_EVERY_SECOND: + HRXLEverySecond(); + break; + case FUNC_JSON_APPEND: + HRXLShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HRXLShow(0); + break; +#endif + } + return false; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +#ifdef USE_I2C +#ifdef USE_HDC1080 +# 31 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +#define XSNS_65 65 +#define XI2C_45 45 + +#define HDC1080_ADDR 0x40 + + + +#define HDC_REG_TEMP 0x00 +#define HDC_REG_RH 0x01 +#define HDC_REG_CONFIG 0x02 +#define HDC_REG_SERIAL1 0xFB +#define HDC_REG_SERIAL2 0xFC +#define HDC_REG_SERIAL3 0xFD +#define HDC_REG_MAN_ID 0xFE +#define HDC_REG_DEV_ID 0xFF + + + +#define HDC1080_MAN_ID 0x5449 +#define HDC1080_DEV_ID 0x1050 + + + +#define HDC1080_RST_ON 0x8000 +#define HDC1080_HEAT_ON 0x2000 +#define HDC1080_MODE_ON 0x1000 +#define HDC1080_TRES_11 0x400 +#define HDC1080_HRES_11 0x100 +#define HDC1080_HRES_8 0x80 + + + +#define HDC1080_CONV_TIME 15 +#define HDC1080_TEMP_MULT 0.0025177 +#define HDC1080_RH_MULT 0.0015258 +#define HDC1080_TEMP_OFFSET 40.0 + +const char* hdc_type_name = "HDC1080"; +uint16_t hdc_manufacturer_id = 0; +uint16_t hdc_device_id = 0; + +float hdc_temperature = 0.0; +float hdc_humidity = 0.0; + +uint8_t hdc_valid = 0; + +bool is_reading = false; +uint32_t hdc_next_read; + + + + + +uint16_t HdcReadDeviceId(void) { + return I2cRead16(HDC1080_ADDR, HDC_REG_DEV_ID); +} + + + + + +uint16_t HdcReadManufacturerId(void) { + return I2cRead16(HDC1080_ADDR, HDC_REG_MAN_ID); +} + + + + +void HdcConfig(uint16_t config) { + I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, config); +} + + + + + + + +void HdcReset(void) { + uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG); + + + + + current |= 0x8000; + + I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current); + + delay(HDC1080_CONV_TIME); +} +# 132 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +int8_t HdcTransactionOpen(uint8_t addr, uint8_t reg) { + Wire.beginTransmission((uint8_t) addr); + Wire.write((uint8_t) reg); + return Wire.endTransmission(); +} +# 147 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +int8_t HdcTransactionClose(uint8_t addr, uint8_t *reg_data, uint16_t len) { + if (len != Wire.requestFrom((uint8_t) addr, (uint8_t) len)) { + return 1; + } + + while (len--) { + *reg_data = (uint8_t)Wire.read(); + reg_data++; + } + + return 0; +} + + + + + +void HdcInit(void) { + HdcReset(); + HdcConfig(HDC1080_MODE_ON); +} + + + + + +bool HdcTriggerRead(void) { + int8_t status = HdcTransactionOpen(HDC1080_ADDR, HDC_REG_TEMP); + + hdc_next_read = millis() + HDC1080_CONV_TIME; + + if(status) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcTriggerRead: failed to open the transaction for HDC_REG_TEMP. Status = %d"), status); + + return false; + } + + is_reading = true; + + return true; +} +# 197 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" +bool HdcRead(void) { + int8_t status = 0; + uint8_t sensor_data[4]; + uint16_t temp_data = 0; + uint16_t rh_data = 0; + + is_reading = false; + + status = HdcTransactionClose(HDC1080_ADDR, sensor_data, 4); + + if(status) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: failed to read HDC_REG_TEMP. Status = %d"), status); + + return false; + } + + temp_data = (uint16_t) ((sensor_data[0] << 8) | sensor_data[1]); + rh_data = (uint16_t) ((sensor_data[2] << 8) | sensor_data[3]); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: temperature raw data: 0x%04x; humidity raw data: 0x%04x"), temp_data, rh_data); + + + + hdc_temperature = ConvertTemp(HDC1080_TEMP_MULT * (float) (temp_data) - HDC1080_TEMP_OFFSET); + + hdc_humidity = HDC1080_RH_MULT * (float) (rh_data); + + if (hdc_humidity > 100) { hdc_humidity = 100.0; } + if (hdc_humidity < 0) { hdc_humidity = 0.01; } + hdc_humidity = ConvertHumidity(hdc_humidity); + + hdc_valid = SENSOR_MAX_MISS; + + return true; +} + + + + + + +void HdcDetect(void) { + if (I2cActive(HDC1080_ADDR)) { + + + return; + } + + hdc_manufacturer_id = HdcReadManufacturerId(); + hdc_device_id = HdcReadDeviceId(); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: detected device with manufacturerId = 0x%04X and deviceId = 0x%04X"), hdc_manufacturer_id, hdc_device_id); + + if (hdc_device_id == HDC1080_DEV_ID) { + HdcInit(); + I2cSetActiveFound(HDC1080_ADDR, hdc_type_name); + } +} + + + + + + +void HdcEverySecond(void) { + if (uptime &1) { + if (!HdcTriggerRead()) { + AddLogMissed((char*) hdc_type_name, hdc_valid); + } + } +} + + + + + + +void HdcShow(bool json) { + if (hdc_valid) { + TempHumDewShow(json, (0 == tele_period), hdc_type_name, hdc_temperature, hdc_humidity); + } +} + + + + + +bool Xsns65(uint8_t function) +{ + if (!I2cEnabled(XI2C_45)) { + + + return false; + } + + bool result = false; + + if (FUNC_INIT == function) { + HdcDetect(); + } + else if (hdc_device_id) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if(is_reading && TimeReached(hdc_next_read)) { + if(!HdcRead()) { + AddLogMissed((char*) hdc_type_name, hdc_valid); + } + } + break; + case FUNC_EVERY_SECOND: + HdcEverySecond(); + break; + case FUNC_JSON_APPEND: + HdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HdcShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_66_iAQ.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_66_iAQ.ino" +#ifdef USE_I2C +#ifdef USE_IAQ + +#define XSNS_66 66 +#define XI2C_46 46 + +#define I2_ADR_IAQ 0x5a + +#define IAQ_STATUS_OK 0x00 +#define IAQ_STATUS_BUSY 0x01 +#define IAQ_STATUS_WARM 0x10 +#define IAQ_STATUS_ERR 0x80 +#define IAQ_STATUS_I2C_ERR 0xFF + +struct { + int32_t resistance; + uint16_t pred; + uint16_t Tvoc; + uint8_t status; + bool ready; +} iAQ; + +void IAQ_Init(void) +{ + if (!I2cSetDevice(I2_ADR_IAQ)) { return; } + I2cSetActiveFound(I2_ADR_IAQ, "IAQ"); + iAQ.ready = true; +} + +void IAQ_Read(void) +{ + uint8_t buf[9]; + buf[2] = IAQ_STATUS_I2C_ERR; + Wire.requestFrom((uint8_t)I2_ADR_IAQ,sizeof(buf)); + for( uint32_t i=0; i<9; i++ ) { + buf[i]= Wire.read(); + } + + iAQ.pred = (buf[0]<<8) + buf[1]; + iAQ.status = buf[2]; + iAQ.resistance = ((uint32_t)buf[3]<<24) + ((uint32_t)buf[4]<<16) + ((uint32_t)buf[5]<<8) + (uint32_t)buf[6]; + iAQ.Tvoc = (buf[7]<<8) + buf[8]; +} + + + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_IAQ[] PROGMEM = + "{s}iAQ-Core " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}iAQ-Core " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; + +const char HTTP_SNS_IAQ_ERROR[] PROGMEM = + "{s}iAQ-Core {m} %s {e}"; +#endif + +void IAQ_Show(uint8_t json) +{ + IAQ_Read(); + + if (json) { + if (iAQ.status!=IAQ_STATUS_OK){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("iAQ: " D_ERROR " %x" ),iAQ.status); + return; + } + else { + ResponseAppend_P(PSTR(",\"IAQ\":{\"" D_JSON_ECO2 "\":%u,\"" D_JSON_TVOC "\":%u,\"" D_JSON_RESISTANCE "\":%u}"), iAQ.pred, iAQ.Tvoc, iAQ.resistance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, iAQ.pred); +#endif + } +#ifdef USE_WEBSERVER + } else { + switch(iAQ.status){ + case IAQ_STATUS_OK: + WSContentSend_PD(HTTP_SNS_IAQ, iAQ.pred, iAQ.Tvoc); + break; + case IAQ_STATUS_WARM: + WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_START); + break; + default: + WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_ERROR); + } +#endif + } +} + + + + + +bool Xsns66(byte function) +{ + if (!I2cEnabled(XI2C_46)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + IAQ_Init(); + } + else if (iAQ.ready) { + switch (function) { + case FUNC_JSON_APPEND: + IAQ_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + IAQ_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_67_as3935.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_67_as3935.ino" +#ifdef USE_I2C +#ifdef USE_AS3935 + + + + + + +#define XSNS_67 67 +#define XI2C_48 48 + +#define D_NAME_AS3935 "AS3935" +#define AS3935_ADDR 0x03 + + +#define PWR_REG 0x00, 0x01, 0 +#define AFE_GB 0x00, 0x3E, 0 +#define WDTH 0x01, 0x0F, 0 +#define NF_LEVEL 0x01, 0x70, 4 +#define SPIKE_REJECT 0x02, 0x0F, 0 +#define MIN_NUM_LIGH 0x02, 0x30, 4 +#define DISTURBER 0x03, 0x20, 5 +#define LCO_FDIV 0x03, 0xC0, 6 +#define IRQ_TBL 0x03, 0x0F, 0 +#define ENERGY_RAW_1 0x04, 0xFF, 0 +#define ENERGY_RAW_2 0x05, 0xFF, 0 +#define ENERGY_RAW_3 0x06, 0x1F, 0 +#define LGHT_DIST 0x07, 0x3F, 0 +#define DISP_TRCO 0x08, 0x20, 5 +#define DISP_SRCO 0x08, 0x40, 6 +#define DISP_LCO 0x08, 0x80, 7 +#define TUNE_CAPS 0x08, 0x0F, 0 +#define CAL_TRCO_NOK 0x3A, 0x40, 6 +#define CAL_TRCO_DONE 0x3A, 0x80, 7 +#define CAL_SRCO_NOK 0x3B, 0x40, 6 +#define CAL_SRCO_DONE 0x3B, 0x80, 7 + + +#define RESET_DEFAULT 0x3C, 0x96 +#define CALIBATE_RCO 0x3D, 0x96 + + +#define INDOORS 0x24 +#define OUTDOORS 0x1C + + +#define SETREG00MASK 0x3E +#define SETREG03MASK 0xF0 + + +const char HTTP_SNS_AS3935_ENERGY[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_ENERGY " {m}%d{e}"; +const char HTTP_SNS_AS3935_DISTANZ[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_DISTANCE " {m}%u " D_UNIT_KILOMETER "{e}"; +const char HTTP_SNS_AS3935_VRMS[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_VRMS "{m}%#4u (%d){e}"; + +const char HTTP_SNS_AS3935_OUTDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_OUTDOORS " {e}"; +const char HTTP_SNS_AS3935_INDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_INDOORS " {e}"; +const char* const HTTP_SNS_AS3935_GAIN[] PROGMEM = {HTTP_SNS_AS3935_INDOORS, HTTP_SNS_AS3935_OUTDOORS}; + +const char HTTP_SNS_AS3935_DIST_ON[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_ON " {e}"; +const char HTTP_SNS_AS3935_DIST_OFF[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_OFF " {e}"; +const char* const HTTP_SNS_AS3935_DISTURBER[] PROGMEM = {HTTP_SNS_AS3935_DIST_OFF, HTTP_SNS_AS3935_DIST_ON}; + +const char HTTP_SNS_AS3935_EMPTY[] PROGMEM = "{s}%s " D_AS3935_NOMESS "{e}"; +const char HTTP_SNS_AS3935_OUT[] PROGMEM = "{s}%s " D_AS3935_OUT "{e}"; +const char HTTP_SNS_AS3935_NOT[] PROGMEM = "{s}%s " D_AS3935_NOT "{e}"; +const char HTTP_SNS_AS3935_ABOVE[] PROGMEM = "{s}%s " D_AS3935_ABOVE "{e}"; +const char HTTP_SNS_AS3935_NOISE[] PROGMEM = "{s}%s " D_AS3935_NOISE "{e}"; +const char HTTP_SNS_AS3935_DISTURB[] PROGMEM = "{s}%s " D_AS3935_DISTDET "{e}"; +const char HTTP_SNS_AS3935_INTNOEV[] PROGMEM = "{s}%s " D_AS3935_INTNOEV "{e}"; +const char HTTP_SNS_AS3935_FLICKER[] PROGMEM = "{s}%s " D_AS3935_FLICKER "{e}"; +const char HTTP_SNS_AS3935_POWEROFF[] PROGMEM = "{s}%s " D_AS3935_POWEROFF "{e}"; + +const char HTTP_SNS_AS3935_MSG[] PROGMEM = "{s}%s " D_AS3935_LIGHT " " D_AS3935_APRX " %d " D_UNIT_KILOMETER " " D_AS3935_AWAY "{e}"; +const char* const HTTP_SNS_AS3935_TABLE_1[] PROGMEM = { HTTP_SNS_AS3935_EMPTY, HTTP_SNS_AS3935_MSG, HTTP_SNS_AS3935_OUT, HTTP_SNS_AS3935_NOT, HTTP_SNS_AS3935_ABOVE, HTTP_SNS_AS3935_NOISE, HTTP_SNS_AS3935_DISTURB, HTTP_SNS_AS3935_INTNOEV, HTTP_SNS_AS3935_FLICKER, HTTP_SNS_AS3935_POWEROFF }; + +const char JSON_SNS_AS3935_EVENTS[] PROGMEM = ",\"%s\":{\"" D_JSON_EVENT "\":%d,\"" D_JSON_DISTANCE "\":%d,\"" D_JSON_ENERGY "\":%u,\"" D_JSON_STAGE "\":%d}"; + +const char* const S_JSON_AS3935_COMMAND_ONOFF[] PROGMEM = {"\"" D_AS3935_OFF "\"","\"" D_AS3935_ON"\""}; +const char* const S_JSON_AS3935_COMMAND_GAIN[] PROGMEM = {"\"" D_AS3935_INDOORS "\"", "\"" D_AS3935_OUTDOORS "\""}; +const char* const S_JSON_AS3935_COMMAND_CAL[] PROGMEM = {"" D_AS3935_CAL_FAIL "","" D_AS3935_CAL_OK ""}; + +const char S_JSON_AS3935_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%s}}"; +const char S_JSON_AS3935_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%d}}"; +const char S_JSON_AS3935_COMMAND_SETTINGS[] PROGMEM = "{\"AS3935_Settings\":{\"Gain\":%s,\"NFfloor\":%d,\"uVrms\":%d,\"Tunecaps\":%d,\"MinNumLight\":%d,\"Rejektion\":%d,\"Wdthreshold\":%d,\"MinNFstage\":%d,\"NFAutoTime\":%d,\"DisturberAutoTime\":%d,\"Disturber\":%s,\"NFauto\":%s,\"Disturberauto\":%s,\"NFautomax\":%s,\"Mqttlightevent\":%s,\"Mqttnoirqevent\":%s}}"; + +const char kAS3935_Commands[] PROGMEM = "power|setnf|setminstage|setml|default|setgain|settunecaps|setrej|setwdth|disttime|nftime|disturber|autonf|autodisturber|autonfmax|lightevent|noirqevent|settings|calibrate"; + +const uint8_t AS3935_VrmsIndoor[] PROGMEM = { 28, 45, 62, 78, 95, 112, 130, 146 }; +const uint16_t AS3935_VrmsOutdoor[] PROGMEM = { 390, 630, 860, 1100, 1140, 1570, 1800, 2000 }; + +enum AS3935_Commands { + CMND_AS3935_POWER, + CMND_AS3935_SET_NF, + CMND_AS3935_SET_MINNF, + CMND_AS3935_SET_MINLIGHT, + CMND_AS3935_SET_DEF, + CMND_AS3935_SET_GAIN, + CMND_AS3935_SET_TUNE, + CMND_AS3935_SET_REJ, + CMND_AS3935_SET_WDTH, + CMND_AS3935_DISTTIME, + CMND_AS3935_NFTIME, + CMND_AS3935_SET_DISTURBER, + CMND_AS3935_NF_AUTOTUNE, + CMND_AS3935_DIST_AUTOTUNE, + CMND_AS3935_NF_ATUNE_BOTH, + CMND_AS3935_MQTT_LIGHT_EVT, + CMND_AS3935_MQTT_NO_IRQ_EVT, + CMND_AS3935_SETTINGS, + CMND_AS3935_CALIBRATE +}; + +struct { + bool active = false; + bool http_count_start = false; + bool poweroff = false; + volatile bool detected = false; + volatile bool dispLCO = false; + volatile uint8_t icount = 0; + uint8_t irq = 0; + uint8_t mqtt_event = 0; + uint8_t http_event = 0; + uint8_t http_time = 0; + uint8_t http_count = 0; + int16_t http_distance = 0; + int16_t distance = 0; + uint16_t nftimer = 0; + uint16_t disttimer = 0; + uint32_t intensity = 0; + uint32_t http_intensity = 0; + volatile uint32_t pulse = 0; +} as3935_sensor; + +void ICACHE_RAM_ATTR AS3935Isr(void) { + as3935_sensor.detected = true; + as3935_sensor.icount++; +} + + +uint8_t AS3935ReadRegister(uint8_t reg, uint8_t mask, uint8_t shift) { + uint8_t data = I2cRead8(AS3935_ADDR, reg); + if (reg == 0x08) Settings.as3935_sensor_cfg[4] = data; + if (reg <= 0x03) Settings.as3935_sensor_cfg[reg] = data; + return ((data & mask) >> shift); +} + +void AS3935WriteRegister(uint8_t reg, uint8_t mask, uint8_t shift, uint8_t data) { + uint8_t currentReg = I2cRead8(AS3935_ADDR, reg); + currentReg &= (~mask); + data <<= shift; + data &= mask; + data |= currentReg; + I2cWrite8(AS3935_ADDR, reg, data); + if (reg == 0x08) Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, reg); + if (reg <= 0x03) Settings.as3935_sensor_cfg[reg] = I2cRead8(AS3935_ADDR, reg); +} + + + +void ICACHE_RAM_ATTR AS3935CountFreq(void) { + if (as3935_sensor.dispLCO) + as3935_sensor.pulse++; +} + +bool AS3935AutoTuneCaps(uint8_t irqpin) { + int32_t maxtune = 17500; + uint8_t besttune; + uint8_t oldvalue = AS3935GetTuneCaps(); + AS3935WriteRegister(LCO_FDIV, 0); + delay(2); + for (uint8_t tune = 0; tune < 16; tune++) { + AS3935WriteRegister(TUNE_CAPS, tune); + delay(2); + AS3935WriteRegister(DISP_LCO, 1); + delay(1); + as3935_sensor.dispLCO = true; + as3935_sensor.pulse = 0; + attachInterrupt(digitalPinToInterrupt(irqpin), AS3935CountFreq, RISING); + delay(50); + as3935_sensor.dispLCO = false; + detachInterrupt(irqpin); + AS3935WriteRegister(DISP_LCO, 0); + int32_t currentfreq = 500000 - ((as3935_sensor.pulse * 20) * 16); + if(currentfreq < 0) currentfreq = -currentfreq; + if(maxtune > currentfreq) { + maxtune = currentfreq; + besttune = tune; + } + } + if (maxtune >= 17500) { + AS3935SetTuneCaps(oldvalue); + return false; + } + AS3935SetTuneCaps(besttune); + return true; +} + + + +bool AS3935CalRCOResult(void) { + if(AS3935ReadRegister(CAL_SRCO_NOK) || AS3935ReadRegister(CAL_TRCO_NOK)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: AS3935 Fatal Failure of TRCO or SRCO calibration")); + return false; + } + return true; +} + +bool AS3935CalibrateRCO(void) { + detachInterrupt(Pin(GPIO_AS3935)); + I2cWrite8(AS3935_ADDR, CALIBATE_RCO); + AS3935WriteRegister(DISP_TRCO, 1); + delay(2); + AS3935WriteRegister(DISP_TRCO, 0); + if(!AS3935CalRCOResult()) + return false; + attachInterrupt(digitalPinToInterrupt(Pin(GPIO_AS3935)), AS3935Isr, RISING); + return true; +} + +void AS3935Reset(void) { + I2cWrite8(AS3935_ADDR, RESET_DEFAULT); + delay(2); +} + +void AS3935PwrDown(void) { + AS3935WriteRegister(PWR_REG ,1); + detachInterrupt(Pin(GPIO_AS3935)); + as3935_sensor.poweroff = true; + as3935_sensor.mqtt_event = 9; + as3935_sensor.http_event = 9; + as3935_sensor.intensity = 0; + as3935_sensor.distance = 0; +} + +void AS3935PwrUp(void) { + AS3935WriteRegister(PWR_REG ,0); + AS3935CalibrateRCO(); + as3935_sensor.poweroff = false; + as3935_sensor.mqtt_event = 0; + as3935_sensor.http_event = 0; +} + +uint8_t AS3935GetPwrStat(void) { + if (AS3935ReadRegister(PWR_REG)) + return 0; + return 1; +} + +uint8_t AS3935GetIRQ(void) { + delay(2); + return AS3935ReadRegister(IRQ_TBL); +} + +uint8_t AS3935TranslIrq(uint8_t irq, uint8_t distance) { + switch(irq) { + case 0: return 7; + case 1: return 5; + case 4: return 6; + case 8: + if (distance == -1) return 2; + else if (distance == 0) return 3; + else if (distance == 1) return 4; + else return 1; + } + return 0; +} + +uint8_t AS3935GetDistance(void) { + return AS3935ReadRegister(LGHT_DIST); +} + +int16_t AS3935CalcDistance(void) { + uint8_t dist = AS3935GetDistance(); + switch (dist) { + case 0x3F: return -1; + case 0x00: return 0; + case 0x01: return 1; + default: + if (40 < dist) return 40; + return dist; + } +} + +uint32_t AS3935GetIntensity(void) { + uint32_t energy_raw = (AS3935ReadRegister(ENERGY_RAW_3) << 8); + energy_raw |= AS3935ReadRegister(ENERGY_RAW_2); + energy_raw <<= 8; + energy_raw |= AS3935ReadRegister(ENERGY_RAW_1); + return energy_raw; +} + +uint8_t AS3935GetTuneCaps(void) { + return AS3935ReadRegister(TUNE_CAPS); +} + +void AS3935SetTuneCaps(uint8_t tune) { + AS3935WriteRegister(TUNE_CAPS, tune); + delay(2); + AS3935CalibrateRCO(); +} + +uint8_t AS3935GetDisturber(void) { + return AS3935ReadRegister(DISTURBER); +} + +void AS3935SetDisturber(uint8_t stat) { + AS3935WriteRegister(DISTURBER, stat); +} + +uint8_t AS3935GetMinLights(void) { + return AS3935ReadRegister(MIN_NUM_LIGH); +} + +void AS3935SetMinLights(uint8_t stat) { + AS3935WriteRegister(MIN_NUM_LIGH, stat); +} + +uint8_t AS3935TransMinLights(uint8_t min_lights) { + if (5 > min_lights) return 0; + else if (9 > min_lights) return 1; + else if (16 > min_lights) return 2; + else return 3; +} + +uint8_t AS3935TranslMinLightsInt(uint8_t min_lights) { + switch (min_lights) { + case 0: return 1; + case 1: return 5; + case 2: return 9; + case 3: return 16; + } + return 0; +} + +uint8_t AS3935GetNoiseFloor(void) { + return AS3935ReadRegister(NF_LEVEL); +} + +void AS3935SetNoiseFloor(uint8_t noise) { + AS3935WriteRegister(NF_LEVEL , noise); +} + +uint8_t AS3935GetGain(void) { + if (AS3935ReadRegister(AFE_GB) == OUTDOORS) + return OUTDOORS; + return INDOORS; +} + +void AS3935SetGain(uint8_t room) { + AS3935WriteRegister(AFE_GB, room); +} + +uint8_t AS3935GetGainInt(void) { + if (AS3935ReadRegister(AFE_GB) == OUTDOORS) + return 1; + return 0; +} + +void AS3935CalcVrmsLevel(uint16_t &vrms, uint8_t &stage) { + uint8_t room = AS3935GetGain(); + uint8_t nflev = AS3935GetNoiseFloor(); + if (room == INDOORS) { + vrms = pgm_read_byte(AS3935_VrmsIndoor + nflev); + stage = nflev; + } else { + vrms = pgm_read_word(AS3935_VrmsOutdoor + nflev); + stage = nflev + 8; + } +} + +uint8_t AS3935GetSpikeRejection(void) { + return AS3935ReadRegister(SPIKE_REJECT); +} + +void AS3935SetSpikeRejection(uint8_t rej) { + AS3935WriteRegister(SPIKE_REJECT, rej); +} + +uint8_t AS3935GetWdth(void) { + return AS3935ReadRegister(WDTH); +} + +void AS3935SetWdth(uint8_t wdth) { + AS3935WriteRegister(WDTH, wdth); +} + +bool AS3935AutoTune(void) { + detachInterrupt(Pin(GPIO_AS3935)); + bool result = AS3935AutoTuneCaps(Pin(GPIO_AS3935)); + return result; +} + + + +bool AS3935LowerNoiseFloor(void) { + uint16_t vrms; + uint8_t stage; + AS3935CalcVrmsLevel(vrms, stage); + if (Settings.as3935_functions.nf_autotune_both) { + if (stage == 8 && stage > Settings.as3935_parameter.nf_autotune_min) { + AS3935SetGain(INDOORS); + AS3935SetNoiseFloor(7); + return true; + } + } + uint8_t noise = AS3935GetNoiseFloor(); + if (0 < noise && stage > Settings.as3935_parameter.nf_autotune_min) { + noise--; + AS3935SetNoiseFloor(noise); + return true; + } + return false; +} + +bool AS3935RaiseNoiseFloor(void) { + uint8_t noise = AS3935GetNoiseFloor(); + uint8_t room = AS3935GetGain(); + if (Settings.as3935_functions.nf_autotune_both) { + if (7 == noise && room == INDOORS) { + AS3935SetGain(OUTDOORS); + AS3935SetNoiseFloor(0); + return true; + } + } + if (7 > noise) { + noise++; + AS3935SetNoiseFloor(noise); + return true; + } + return false; +} + + + +bool AS3935SetDefault(void) { + AS3935Reset(); + AS3935SetDisturber(1); + AS3935SetNoiseFloor(7); + Settings.as3935_sensor_cfg[0] = I2cRead8(AS3935_ADDR, 0x00); + Settings.as3935_sensor_cfg[1] = I2cRead8(AS3935_ADDR, 0x01); + Settings.as3935_sensor_cfg[2] = I2cRead8(AS3935_ADDR, 0x02); + Settings.as3935_sensor_cfg[3] = I2cRead8(AS3935_ADDR, 0x03); + Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, 0x08); + + Settings.as3935_functions.data = 0x00; + Settings.as3935_parameter.nf_autotune_min = 0x00; + Settings.as3935_parameter.nf_autotune_time = 4; + Settings.as3935_parameter.dist_autotune_time = 1; + return true; +} + +void AS3935InitSettings(void) { + if(Settings.as3935_functions.nf_autotune) { + if(Settings.as3935_parameter.nf_autotune_min) { + if (Settings.as3935_parameter.nf_autotune_min > 7) { + AS3935SetGain(OUTDOORS); + AS3935SetNoiseFloor(Settings.as3935_parameter.nf_autotune_min - 8); + } else { + AS3935SetGain(INDOORS); + AS3935SetNoiseFloor(Settings.as3935_parameter.nf_autotune_min); + } + } + } + I2cWrite8(AS3935_ADDR, 0x00, Settings.as3935_sensor_cfg[0] & SETREG00MASK); + I2cWrite8(AS3935_ADDR, 0x01, Settings.as3935_sensor_cfg[1]); + I2cWrite8(AS3935_ADDR, 0x02, Settings.as3935_sensor_cfg[2]); + I2cWrite8(AS3935_ADDR, 0x03, Settings.as3935_sensor_cfg[3] & SETREG03MASK); + I2cWrite8(AS3935_ADDR, 0x08, Settings.as3935_sensor_cfg[4]); + delay(2); +} + +bool AS3935Setup(void) { + if (Settings.as3935_sensor_cfg[0] == 0x00) { + AS3935SetDefault(); + } else { + AS3935InitSettings(); + } + return AS3935CalibrateRCO(); +} + +bool AS3935init(void) { + AS3935Reset(); + uint8_t afe_gb = I2cRead8(AS3935_ADDR, 0x00) & SETREG00MASK; + if(INDOORS == afe_gb) + return true; + return false; +} + +void AS3935Detect(void) { + if (!I2cSetDevice(AS3935_ADDR)) return; + if (AS3935init()) { + I2cSetActiveFound(AS3935_ADDR, D_NAME_AS3935); + if (PinUsed(GPIO_AS3935)) { + pinMode(Pin(GPIO_AS3935), INPUT); + if (!AS3935Setup()) return; + as3935_sensor.active = true; + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: AS3935 GPIO Pin not defined!")); + } + } +} + +void AS3935EverySecond(void) { + if (!as3935_sensor.poweroff) { + if (as3935_sensor.detected) { + as3935_sensor.detected = false; + as3935_sensor.irq = AS3935GetIRQ(); + + if (10 > as3935_sensor.icount) { + switch (as3935_sensor.irq) { + case 1: + if (Settings.as3935_functions.nf_autotune) { + if (AS3935RaiseNoiseFloor()) + as3935_sensor.nftimer = 0; + } + break; + case 4: + if (Settings.as3935_functions.dist_autotune) { + AS3935SetDisturber(1); + } + break; + case 8: + as3935_sensor.intensity = AS3935GetIntensity(); + as3935_sensor.distance = AS3935CalcDistance(); + as3935_sensor.http_intensity = as3935_sensor.intensity; + as3935_sensor.http_distance = as3935_sensor.distance; + break; + } + + as3935_sensor.http_event = AS3935TranslIrq(as3935_sensor.irq, as3935_sensor.distance); + } else { + as3935_sensor.http_event = 8; + } + + + as3935_sensor.mqtt_event = as3935_sensor.http_event; + + switch (as3935_sensor.mqtt_event) { + case 5: + case 6: + if (!Settings.as3935_functions.mqtt_only_Light_Event) { + MqttPublishSensor(); + as3935_sensor.http_time = 10; + } + break; + case 7: + if (!Settings.as3935_functions.suppress_irq_no_Event) { + MqttPublishSensor(); + as3935_sensor.http_time = 10; + } + break; + default: + as3935_sensor.http_time = 30; + MqttPublishSensor(); + } + + as3935_sensor.irq = 0; + + as3935_sensor.intensity = 0; + as3935_sensor.distance = 0; + as3935_sensor.mqtt_event = 0; + + as3935_sensor.http_count_start = true; + as3935_sensor.http_count = 0; + } + as3935_sensor.icount = 0; + + + if (as3935_sensor.http_count_start) + as3935_sensor.http_count++; + + if (as3935_sensor.http_count > as3935_sensor.http_time) { + as3935_sensor.http_count_start = false; + as3935_sensor.http_intensity = 0; + as3935_sensor.http_distance = 0; + as3935_sensor.http_event = 0; + } + + if (Settings.as3935_functions.nf_autotune) { + as3935_sensor.nftimer++; + if (as3935_sensor.nftimer > Settings.as3935_parameter.nf_autotune_time * 60) { + AS3935LowerNoiseFloor(); + as3935_sensor.nftimer = 0; + } + } + + if (Settings.as3935_functions.dist_autotune) { + if (AS3935GetDisturber()) { + as3935_sensor.disttimer++; + } + if (as3935_sensor.disttimer >= Settings.as3935_parameter.dist_autotune_time * 60) { + AS3935SetDisturber(0); + as3935_sensor.disttimer = 0; + } + } + } +} + +bool AS3935Cmd(void) { + char command[CMDSZ]; + uint8_t name_len = strlen(D_NAME_AS3935); + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_AS3935), name_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kAS3935_Commands); + switch (command_code) { + case CMND_AS3935_POWER: + if (XdrvMailbox.data_len) { + if (!XdrvMailbox.payload) { + AS3935PwrDown(); + } else { + AS3935PwrUp(); + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[AS3935GetPwrStat()]); + break; + case CMND_AS3935_SET_NF: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + AS3935SetNoiseFloor(XdrvMailbox.payload); + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetNoiseFloor()); + break; + case CMND_AS3935_SET_MINNF: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + Settings.as3935_parameter.nf_autotune_min = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_min); + break; + case CMND_AS3935_SET_MINLIGHT: + if (XdrvMailbox.data_len) { + AS3935SetMinLights(AS3935TransMinLights(XdrvMailbox.payload)); + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935TranslMinLightsInt(AS3935GetMinLights())); + break; + case CMND_AS3935_SET_DEF: + if (!XdrvMailbox.data_len) { + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935SetDefault()); + } + break; + case CMND_AS3935_SET_GAIN: + if (XdrvMailbox.data_len > 6) { + uint8_t data_len = strlen(D_AS3935_OUTDOORS); + if (!strncasecmp_P(XdrvMailbox.data, PSTR(D_AS3935_OUTDOORS), data_len)) { + AS3935SetGain(OUTDOORS); + } else { + AS3935SetGain(INDOORS); + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_GAIN[AS3935GetGainInt()]); + break; + case CMND_AS3935_SET_TUNE: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + AS3935SetTuneCaps(XdrvMailbox.payload); + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetTuneCaps()); + break; + case CMND_AS3935_SET_REJ: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + AS3935SetSpikeRejection(XdrvMailbox.payload); + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetSpikeRejection()); + break; + case CMND_AS3935_SET_WDTH: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + AS3935SetWdth(XdrvMailbox.payload); + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetWdth()); + break; + case CMND_AS3935_DISTTIME: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + Settings.as3935_parameter.dist_autotune_time = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.dist_autotune_time); + break; + case CMND_AS3935_NFTIME: + if (XdrvMailbox.data_len) { + if (15 >= XdrvMailbox.payload) { + Settings.as3935_parameter.nf_autotune_time = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_time); + break; + case CMND_AS3935_SET_DISTURBER: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + AS3935SetDisturber(XdrvMailbox.payload); + if (!XdrvMailbox.payload) Settings.as3935_functions.dist_autotune = 0; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[AS3935GetDisturber()]); + break; + case CMND_AS3935_NF_AUTOTUNE: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + Settings.as3935_functions.nf_autotune = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune]); + break; + case CMND_AS3935_DIST_AUTOTUNE: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + Settings.as3935_functions.dist_autotune = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.dist_autotune]); + break; + case CMND_AS3935_NF_ATUNE_BOTH: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + Settings.as3935_functions.nf_autotune_both = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune_both]); + break; + case CMND_AS3935_MQTT_LIGHT_EVT: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + Settings.as3935_functions.mqtt_only_Light_Event = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.mqtt_only_Light_Event]); + break; + case CMND_AS3935_MQTT_NO_IRQ_EVT: + if (XdrvMailbox.data_len) { + if (2 > XdrvMailbox.payload) { + Settings.as3935_functions.suppress_irq_no_Event = XdrvMailbox.payload; + } + } + Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.suppress_irq_no_Event]); + break; + case CMND_AS3935_SETTINGS: { + if (!XdrvMailbox.data_len) { + uint8_t gain = AS3935GetGainInt(); + uint16_t vrms; + uint8_t stage; + AS3935CalcVrmsLevel(vrms, stage); + uint8_t nf_floor = AS3935GetNoiseFloor(); + uint8_t tunecaps = AS3935GetTuneCaps(); + uint8_t minnumlight = AS3935TranslMinLightsInt(AS3935GetMinLights()); + uint8_t disturber = AS3935GetDisturber(); + uint8_t reinj = AS3935GetSpikeRejection(); + uint8_t wdth = AS3935GetWdth(); + uint8_t min_nf = Settings.as3935_parameter.nf_autotune_min; + uint8_t nf_time = Settings.as3935_parameter.nf_autotune_time; + uint8_t nfauto = Settings.as3935_functions.nf_autotune; + uint8_t nfautomax = Settings.as3935_functions.nf_autotune_both; + uint8_t distauto = Settings.as3935_functions.dist_autotune; + uint8_t jsonlight = Settings.as3935_functions.mqtt_only_Light_Event; + uint8_t jsonirq = Settings.as3935_functions.suppress_irq_no_Event; + uint8_t dist_time = Settings.as3935_parameter.dist_autotune_time; + Response_P(S_JSON_AS3935_COMMAND_SETTINGS, S_JSON_AS3935_COMMAND_GAIN[gain], nf_floor, vrms, tunecaps, minnumlight, reinj, wdth, min_nf, nf_time, dist_time, S_JSON_AS3935_COMMAND_ONOFF[disturber], S_JSON_AS3935_COMMAND_ONOFF[nfauto], S_JSON_AS3935_COMMAND_ONOFF[distauto], S_JSON_AS3935_COMMAND_ONOFF[nfautomax], S_JSON_AS3935_COMMAND_ONOFF[jsonlight], S_JSON_AS3935_COMMAND_ONOFF[jsonirq]); + } + } + break; + case CMND_AS3935_CALIBRATE: { + bool calreslt; + if (!XdrvMailbox.data_len) calreslt = AS3935AutoTune(); + Response_P(S_JSON_AS3935_COMMAND_NVALUE, S_JSON_AS3935_COMMAND_CAL[calreslt], AS3935GetTuneCaps()); + } + break; + default: + return false; + } + return true; + } else { + return false; + } +} + +void AH3935Show(bool json) { + if (json) { + uint16_t vrms; + uint8_t stage; + AS3935CalcVrmsLevel(vrms, stage); + ResponseAppend_P(JSON_SNS_AS3935_EVENTS, D_SENSOR_AS3935, as3935_sensor.mqtt_event, as3935_sensor.distance, as3935_sensor.intensity, stage); +#ifdef USE_WEBSERVER + } else { + uint8_t gain = AS3935GetGainInt(); + uint8_t disturber = AS3935GetDisturber(); + uint16_t vrms; + uint8_t stage; + AS3935CalcVrmsLevel(vrms, stage); + + WSContentSend_PD(HTTP_SNS_AS3935_TABLE_1[as3935_sensor.http_event], D_NAME_AS3935, as3935_sensor.http_distance); + WSContentSend_PD(HTTP_SNS_AS3935_DISTANZ, as3935_sensor.http_distance); + WSContentSend_PD(HTTP_SNS_AS3935_ENERGY, as3935_sensor.http_intensity); + WSContentSend_PD(HTTP_SNS_AS3935_GAIN[gain], D_NAME_AS3935); + WSContentSend_PD(HTTP_SNS_AS3935_DISTURBER[disturber], D_NAME_AS3935); + WSContentSend_PD(HTTP_SNS_AS3935_VRMS, vrms, stage); + +#endif + } +} + + + + + +bool Xsns67(uint8_t function) { + if (!I2cEnabled(XI2C_48)) { return false; } + bool result = false; + if (FUNC_INIT == function) { + AS3935Detect(); + } + else if (as3935_sensor.active) { + switch (function) { + case FUNC_EVERY_SECOND: + AS3935EverySecond(); + break; + case FUNC_COMMAND: + result = AS3935Cmd(); + break; + case FUNC_JSON_APPEND: + AH3935Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AH3935Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" +# 21 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" +#ifdef USE_WINDMETER + + + + +#define XSNS_68 68 + +#define D_WINDMETER_NAME "WindMeter" + +#define WINDMETER_DEF_RADIUS 61 +#define WINDMETER_DEF_PULSES_X_ROT 1 +#define WINDMETER_DEF_PULSE_DEBOUNCE 10 +#define WINDMETER_DEF_COMP_FACTOR 1.18 +#define WINDMETER_DEF_TELE_PCHANGE 255 +#define WINDMETER_WEIGHT_AVG_SAMPLE 150 + +#ifdef USE_WEBSERVER +#define D_WINDMETER_WIND_AVG "∅" +#define D_WINDMETER_WIND_ANGLE "∠" +#define D_WINDMETER_WIND_DEGREE "°" +const char HTTP_SNS_WINDMETER[] PROGMEM = + "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}" +#ifndef USE_WINDMETER_NOSTATISTICS + "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED " " D_WINDMETER_WIND_AVG "{m}%s %s{e}" + "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}" + "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}" +#endif + + + + + + ; +#endif + + +float const windmeter_pi = 3.1415926535897932384626433; +float const windmeter_2pi = windmeter_pi * 2; + +struct WINDMETER { + volatile uint32_t counter_time; + volatile unsigned long counter = 0; + + float speed = 0; + float last_tele_speed = 0; +#ifndef USE_WINDMETER_NOSTATISTICS + float speed_min = 0; + float speed_max = 0; + float speed_avg = 0; + uint32_t samples_count = 0; + uint32_t avg_samples_no; +#endif +} WindMeter; + +void ICACHE_RAM_ATTR WindMeterUpdateSpeed(void) +{ + uint32_t time = micros(); + uint32_t time_diff = time - WindMeter.counter_time; + if (time_diff > Settings.windmeter_pulse_debounce * 1000) { + WindMeter.counter_time = time; + WindMeter.counter++; + + } +} + + + +void WindMeterInit(void) +{ + if (!Settings.flag2.speed_conversion) { + Settings.flag2.speed_conversion = 2; + } + if (!Settings.windmeter_radius) { + Settings.windmeter_radius = WINDMETER_DEF_RADIUS; + } + if (!Settings.windmeter_pulses_x_rot) { + Settings.windmeter_pulses_x_rot = WINDMETER_DEF_PULSES_X_ROT; + } + if (!Settings.windmeter_pulse_debounce) { + Settings.windmeter_pulse_debounce = WINDMETER_DEF_PULSE_DEBOUNCE; + } + if (!Settings.windmeter_speed_factor) { + Settings.windmeter_speed_factor = (int16_t)(WINDMETER_DEF_COMP_FACTOR * 1000); + } + if (!Settings.windmeter_tele_pchange) { + Settings.windmeter_tele_pchange = WINDMETER_DEF_TELE_PCHANGE; + } + +#ifndef USE_WINDMETER_NOSTATISTICS + WindMeterResetStatData(); + WindMeterCheckSampleCount(); +#endif + + pinMode(Pin(GPIO_WINDMETER_SPEED), INPUT_PULLUP); + attachInterrupt(Pin(GPIO_WINDMETER_SPEED), WindMeterUpdateSpeed, FALLING); +} + +void WindMeterEverySecond(void) +{ + + + + + + WindMeter.speed = ((WindMeter.counter / Settings.windmeter_pulses_x_rot) * (windmeter_2pi * ((float)Settings.windmeter_radius / 1000))) * ((float)Settings.windmeter_speed_factor / 1000); + + WindMeter.counter = 0; +# 136 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" +#ifndef USE_WINDMETER_NOSTATISTICS + if (WindMeter.speed < WindMeter.speed_min) { + WindMeter.speed_min = WindMeter.speed; + } + if (WindMeter.speed > WindMeter.speed_max) { + WindMeter.speed_max = WindMeter.speed; + } + + + + + if (WindMeter.samples_count <= WindMeter.avg_samples_no) { + WindMeter.samples_count++; + } + WindMeter.speed_avg -= WindMeter.speed_avg / WindMeter.samples_count; + WindMeter.speed_avg += float(WindMeter.speed) / WindMeter.samples_count; + + WindMeterCheckSampleCount(); + if (0==Settings.tele_period) { + WindMeterResetStatData(); + } +#endif + + if (WindMeterShouldTriggerTele()) { + WindMeterTriggerTele(); + } +} + +bool WindMeterShouldTriggerTele() +{ + if (Settings.windmeter_tele_pchange > 100) { + return false; + } else if (WindMeter.last_tele_speed == 0) { + return WindMeter.speed > 0; + } else { + float perc_change = (WindMeter.speed / WindMeter.last_tele_speed) -1; + return (perc_change * ((perc_change < 0) ? -100 : 100)) >= Settings.windmeter_tele_pchange; + } +} + +void WindMeterResetStatData(void) +{ + WindMeter.speed_min = WindMeter.speed; + WindMeter.speed_max = WindMeter.speed; + + +} + +void WindMeterCheckSampleCount(void) +{ + uint32_t prev_avg_samples_no = WindMeter.avg_samples_no; + if (Settings.tele_period) { + + WindMeter.avg_samples_no = Settings.tele_period; + } else { + + WindMeter.avg_samples_no = WINDMETER_WEIGHT_AVG_SAMPLE; + } + if (prev_avg_samples_no != WindMeter.avg_samples_no) { + WindMeter.speed_avg = WindMeter.speed; + WindMeter.samples_count = 0; + } +} + +void WindMeterShow(bool json) +{ + char speed_string[FLOATSZ]; + dtostrfd(ConvertSpeed(WindMeter.speed), 2, speed_string); +#ifndef USE_WINDMETER_NOSTATISTICS + char speed_min_string[FLOATSZ]; + dtostrfd(ConvertSpeed(WindMeter.speed_min), 2, speed_min_string); + char speed_max_string[FLOATSZ]; + dtostrfd(ConvertSpeed(WindMeter.speed_max), 2, speed_max_string); + char speed_avg_string[FLOATSZ]; + dtostrfd(ConvertSpeed(WindMeter.speed_avg), 2, speed_avg_string); +# 221 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" +#endif + + if (json) { + WindMeter.last_tele_speed = WindMeter.speed; +#ifndef USE_WINDMETER_NOSTATISTICS + + ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s}}"), + speed_string, + speed_avg_string, + speed_min_string, + speed_max_string + + + + + + + + ); +#else + + ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s}}"), + speed_string + + + ); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_WINDMETER, + speed_string, + SpeedUnit().c_str(), +#ifndef USE_WINDMETER_NOSTATISTICS + speed_avg_string, + SpeedUnit().c_str(), + speed_min_string, + SpeedUnit().c_str(), + speed_max_string, + SpeedUnit().c_str(), +#endif + "n/a", + "n/a" +#ifndef USE_WINDMETER_NOSTATISTICS + ,"n/a", + "n/a", + "n/a", + "n/a", + "n/a" +#endif + ); +#endif + } +} + +void WindMeterTriggerTele(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } +} + + + + + +bool Xsns68Cmnd(void) +{ + bool serviced = true; + bool show_parms = true; + char sub_string[XdrvMailbox.data_len +1]; + switch (XdrvMailbox.payload) { + case 1: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.windmeter_radius = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + break; + case 2: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.windmeter_pulses_x_rot = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + break; + case 3: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.windmeter_pulse_debounce = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + break; + case 4: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.windmeter_speed_factor = (int16_t)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 1000); + } + break; + case 5: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.windmeter_tele_pchange = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + break; + } + + if (show_parms) { + char speed_factor_string[FLOATSZ]; + dtostrfd((float)Settings.windmeter_speed_factor / 1000, 3, speed_factor_string); + char tele_pchange_string[4] = "off"; + if (Settings.windmeter_tele_pchange <= 100) { + itoa(Settings.windmeter_tele_pchange, tele_pchange_string, 10); + } + Response_P(PSTR("{\"" D_WINDMETER_NAME "\":{\"Radius\":%d,\"PulsesPerRot\":%d,\"PulseDebounce\":%d,\"SpeedFactor\":%s,\"TeleTriggerMin%Change\":%s}}"), + Settings.windmeter_radius, Settings.windmeter_pulses_x_rot, Settings.windmeter_pulse_debounce, speed_factor_string, tele_pchange_string); + } + return serviced; +} + + + + + +bool Xsns68(uint8_t function) +{ + bool result = false; + if (PinUsed(GPIO_WINDMETER_SPEED)) { + switch (function) { + case FUNC_INIT: + WindMeterInit(); + break; + case FUNC_EVERY_SECOND: + WindMeterEverySecond(); + break; +#ifndef USE_WINDMETER_NOSTATISTICS + case FUNC_AFTER_TELEPERIOD: + WindMeterResetStatData(); + break; +#endif + case FUNC_JSON_APPEND: + WindMeterShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + WindMeterShow(false); + break; +#endif + case FUNC_COMMAND_SENSOR: + if (XSNS_68 == XdrvMailbox.index) { + result = Xsns68Cmnd(); + } + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" +#ifdef USE_OPENTHERM + +#define XSNS_69 69 + +#include + + +#define OT_HOT_WATER_MIN 23 +#define OT_HOT_WATER_MAX 55 +#define OT_BOILER_MIN 40 +#define OT_BOILER_MAX 85 + +#define OT_HOT_WATER_DEFAULT 36; +#define OT_BOILER_DEFAULT 85; + + +#define SNS_OT_DISCONNECT_COOLDOWN_SECONDS 10 + + +#define OT_FLAGS_COUNT 6 +enum OpenThermSettingsFlags +{ + + + EnableCentralHeatingOnDiagnostics = 0x01, + + EnableHotWater = 0x02, + + EnableCentralHeating = 0x04, + EnableCooling = 0x08, + EnableTemperatureCompensation = 0x10, + EnableCentralHeating2 = 0x20, +}; + +enum OpenThermConnectionStatus +{ + OTC_NONE, + OTC_DISCONNECTED, + OTC_CONNECTING, + OTC_HANDSHAKE, + OTC_READY, + OTC_INFLIGHT +}; + +OpenThermConnectionStatus sns_ot_connection_status = OpenThermConnectionStatus::OTC_NONE; +uint8_t sns_ot_disconnect_cooldown = 0; + +OpenTherm *sns_ot_master = NULL; + + +typedef struct OT_BOILER_STATUS_T +{ + + uint8_t m_fault_code; + + uint8_t m_oem_fault_code; + + uint16_t m_oem_diag_code; + + uint8_t m_slave_flags; + + unsigned long m_slave_raw_status; + + bool m_enableCentralHeating; + bool m_enableHotWater; + bool m_enableCooling; + bool m_enableOutsideTemperatureCompensation; + bool m_enableCentralHeating2; + + + + + + + + bool m_useDiagnosticIndicationAsHeatRequest; + + + float m_hotWaterSetpoint_read; + + float m_flame_modulation_read; + + float m_boiler_temperature_read; + + + float m_boilerSetpoint; + float m_hotWaterSetpoint; + +} OT_BOILER_STATUS; + +OT_BOILER_STATUS sns_ot_boiler_status; + +const char *sns_opentherm_connection_stat_to_str(int status) +{ + switch (status) + { + case OpenThermConnectionStatus::OTC_NONE: + return "NONE"; + case OpenThermConnectionStatus::OTC_DISCONNECTED: + return "FAULT"; + case OpenThermConnectionStatus::OTC_CONNECTING: + return "CONNECTING"; + case OpenThermConnectionStatus::OTC_HANDSHAKE: + return "HANDSHAKE"; + case OpenThermConnectionStatus::OTC_READY: + return "READY"; + case OpenThermConnectionStatus::OTC_INFLIGHT: + return "BUSY"; + default: + return "UNKNOWN"; + } +} + +void sns_opentherm_init_boiler_status() +{ + memset(&sns_ot_boiler_status, 0, sizeof(OT_BOILER_STATUS)); + + + sns_ot_boiler_status.m_useDiagnosticIndicationAsHeatRequest = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics; + sns_ot_boiler_status.m_enableHotWater = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableHotWater; + sns_ot_boiler_status.m_enableCentralHeating = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeating; + sns_ot_boiler_status.m_enableCooling = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCooling; + sns_ot_boiler_status.m_enableOutsideTemperatureCompensation = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableTemperatureCompensation; + sns_ot_boiler_status.m_enableCentralHeating2 = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeating2; + + sns_ot_boiler_status.m_boilerSetpoint = (float)Settings.ot_boiler_setpoint; + sns_ot_boiler_status.m_hotWaterSetpoint = (float)Settings.ot_hot_water_setpoint; + + sns_ot_boiler_status.m_fault_code = 0; + sns_ot_boiler_status.m_oem_fault_code = 0; + sns_ot_boiler_status.m_oem_diag_code = 0; + sns_ot_boiler_status.m_hotWaterSetpoint_read = 0; + sns_ot_boiler_status.m_flame_modulation_read = 0; + sns_ot_boiler_status.m_boiler_temperature_read = 0; +} + +void ICACHE_RAM_ATTR sns_opentherm_handleInterrupt() +{ + sns_ot_master->handleInterrupt(); +} + +void sns_opentherm_processResponseCallback(unsigned long response, int st) +{ + OpenThermResponseStatus status = (OpenThermResponseStatus)st; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, + PSTR("[OTH]: Processing response. Status=%s, Response=0x%lX"), + sns_ot_master->statusToString(status), response); + + if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_HANDSHAKE) + { + return sns_ot_process_handshake(response, st); + } + + switch (status) + { + case OpenThermResponseStatus::SUCCESS: + if (sns_ot_master->isValidResponse(response)) + { + sns_opentherm_process_success_response(&sns_ot_boiler_status, response); + } + sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; + break; + + case OpenThermResponseStatus::INVALID: + sns_opentherm_check_retry_request(); + sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; + break; + + + + + + case OpenThermResponseStatus::TIMEOUT: + sns_opentherm_check_retry_request(); + sns_ot_connection_status = OpenThermConnectionStatus::OTC_DISCONNECTED; + break; + } +} + +bool sns_opentherm_Init() +{ + if (PinUsed(GPIO_BOILER_OT_RX) && PinUsed(GPIO_BOILER_OT_TX)) + { + sns_ot_master = new OpenTherm(Pin(GPIO_BOILER_OT_RX), Pin(GPIO_BOILER_OT_TX)); + sns_ot_master->begin(sns_opentherm_handleInterrupt, sns_opentherm_processResponseCallback); + sns_ot_connection_status = OpenThermConnectionStatus::OTC_CONNECTING; + + sns_opentherm_init_boiler_status(); + return true; + } + return false; + +} + +void sns_opentherm_stat(bool json) +{ + if (!sns_ot_master) + { + return; + } + const char *statusStr = sns_opentherm_connection_stat_to_str(sns_ot_connection_status); + + if (json) + { + ResponseAppend_P(PSTR(",\"OPENTHERM\":{")); + ResponseAppend_P(PSTR("\"conn\":\"%s\","), statusStr); + ResponseAppend_P(PSTR("\"settings\":%d,"), Settings.ot_flags); + sns_opentherm_dump_telemetry(); + ResponseJsonEnd(); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_P(PSTR("{s}OpenTherm status{m}%s (0x%X){e}"), statusStr, (int)sns_ot_boiler_status.m_slave_flags); + if (sns_ot_connection_status < OpenThermConnectionStatus::OTC_READY) + { + return; + } + WSContentSend_P(PSTR("{s}Std/OEM Fault Codes{m}%d / %d{e}"), + (int)sns_ot_boiler_status.m_fault_code, + (int)sns_ot_boiler_status.m_oem_fault_code); + + WSContentSend_P(PSTR("{s}OEM Diagnostic Code{m}%d{e}"), + (int)sns_ot_boiler_status.m_oem_diag_code); + + WSContentSend_P(PSTR("{s}Hot Water Setpoint{m}%d{e}"), + (int)sns_ot_boiler_status.m_hotWaterSetpoint_read); + + WSContentSend_P(PSTR("{s}Flame Modulation{m}%d{e}"), + (int)sns_ot_boiler_status.m_flame_modulation_read); + + WSContentSend_P(PSTR("{s}Boiler Temp/Setpnt{m}%d / %d{e}"), + (int)sns_ot_boiler_status.m_boiler_temperature_read, + (int)sns_ot_boiler_status.m_boilerSetpoint); + + if (OpenTherm::isCentralHeatingActive(sns_ot_boiler_status.m_slave_raw_status)) + { + WSContentSend_P(PSTR("{s}Central Heating is ACTIVE{m}{e}")); + } + + if (sns_ot_boiler_status.m_enableHotWater) + { + WSContentSend_P(PSTR("{s}Hot Water is Enabled{m}{e}")); + } + + if (OpenTherm::isHotWaterActive(sns_ot_boiler_status.m_slave_raw_status)) + { + WSContentSend_P(PSTR("{s}Hot Water is ACTIVE{m}{e}")); + } + + if (OpenTherm::isFlameOn(sns_ot_boiler_status.m_slave_raw_status)) + { + WSContentSend_P(PSTR("{s}Flame is ACTIVE{m}{e}")); + } + + if (sns_ot_boiler_status.m_enableCooling) + { + WSContentSend_P(PSTR("{s}Cooling is Enabled{m}{e}")); + } + + if (OpenTherm::isCoolingActive(sns_ot_boiler_status.m_slave_raw_status)) + { + WSContentSend_P(PSTR("{s}Cooling is ACTIVE{m}{e}")); + } + + if (OpenTherm::isDiagnostic(sns_ot_boiler_status.m_slave_raw_status)) + { + WSContentSend_P(PSTR("{s}Diagnostic Indication{m}{e}")); + } + +#endif + } +} + +void sns_ot_start_handshake() +{ + if (!sns_ot_master) + { + return; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("[OTH]: perform handshake")); + + sns_ot_master->sendRequestAync( + OpenTherm::buildRequest(OpenThermMessageType::READ_DATA, OpenThermMessageID::SConfigSMemberIDcode, 0)); + + sns_ot_connection_status = OpenThermConnectionStatus::OTC_HANDSHAKE; +} + +void sns_ot_process_handshake(unsigned long response, int st) +{ + OpenThermResponseStatus status = (OpenThermResponseStatus)st; + + if (status != OpenThermResponseStatus::SUCCESS || !sns_ot_master->isValidResponse(response)) + { + AddLog_P2(LOG_LEVEL_ERROR, + PSTR("[OTH]: getSlaveConfiguration failed. Status=%s"), + sns_ot_master->statusToString(status)); + sns_ot_connection_status = OpenThermConnectionStatus::OTC_DISCONNECTED; + return; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("[OTH]: getLastResponseStatus SUCCESS. Slave Cfg: %lX"), response); + + sns_ot_boiler_status.m_slave_flags = (response & 0xFF00) >> 8; + + sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; +} + +void sns_opentherm_CheckSettings(void) +{ + bool settingsValid = true; + + settingsValid &= Settings.ot_hot_water_setpoint >= OT_HOT_WATER_MIN; + settingsValid &= Settings.ot_hot_water_setpoint <= OT_HOT_WATER_MAX; + settingsValid &= Settings.ot_boiler_setpoint >= OT_BOILER_MIN; + settingsValid &= Settings.ot_boiler_setpoint <= OT_BOILER_MAX; + + if (!settingsValid) + { + Settings.ot_hot_water_setpoint = OT_HOT_WATER_DEFAULT; + Settings.ot_boiler_setpoint = OT_BOILER_DEFAULT; + Settings.ot_flags = + OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics | + OpenThermSettingsFlags::EnableHotWater; + } +} + + + +const char *sns_opentherm_flag_text(uint8_t mode) +{ + switch ((OpenThermSettingsFlags)mode) + { + case OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics: + return "CHOD"; + case OpenThermSettingsFlags::EnableHotWater: + return "DHW"; + case OpenThermSettingsFlags::EnableCentralHeating: + return "CH"; + case OpenThermSettingsFlags::EnableCooling: + return "COOL"; + case OpenThermSettingsFlags::EnableTemperatureCompensation: + return "OTC"; + case OpenThermSettingsFlags::EnableCentralHeating2: + return "CH2"; + default: + return "?"; + } +} + +uint8_t sns_opentherm_parse_flag(char *flag) +{ + if (!strncmp(flag, "CHOD", 4)) + { + return OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics; + } + else if (!strncmp(flag, "COOL", 4)) + { + return OpenThermSettingsFlags::EnableCooling; + } + else if (!strncmp(flag, "DHW", 3)) + { + return OpenThermSettingsFlags::EnableHotWater; + } + else if (!strncmp(flag, "OTC", 3)) + { + return OpenThermSettingsFlags::EnableTemperatureCompensation; + } + else if (!strncmp(flag, "CH2", 3)) + { + return OpenThermSettingsFlags::EnableCentralHeating2; + } + else if (!strncmp(flag, "CH", 2)) + { + return OpenThermSettingsFlags::EnableCentralHeating; + } + return 0; +} + +uint8_t sns_opentherm_read_flags(char *data, uint32_t len) +{ + uint8_t tokens = 1; + for (int i = 0; i < len; ++i) + { + if (data[i] == ',') + { + ++tokens; + } + } + uint8_t result = 0; + char sub_string[XdrvMailbox.data_len + 1]; + for (int i = 1; i <= tokens; ++i) + { + char *flag = subStr(sub_string, data, ",", i); + if (!flag) + { + break; + } + result |= sns_opentherm_parse_flag(flag); + } + return result; +} +#define D_PRFX_OTHERM "ot_" + + +#define D_CMND_OTHERM_BOILER_SETPOINT "tboiler" + + +#define D_CMND_OTHERM_DHW_SETPOINT "twater" + + + +#define D_CMND_OTHERM_SAVE_SETTINGS "save_setpoints" +# 442 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" +#define D_CMND_OTHERM_FLAGS "flags" + + + + + + + +#define D_CMND_SET_CENTRAL_HEATING_ENABLED "ch" + +const char kOpenThermCommands[] PROGMEM = D_PRFX_OTHERM "|" D_CMND_OTHERM_BOILER_SETPOINT "|" D_CMND_OTHERM_DHW_SETPOINT + "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED; + +void (*const OpenThermCommands[])(void) PROGMEM = { + &sns_opentherm_boiler_setpoint_cmd, + &sns_opentherm_hot_water_setpoint_cmd, + &sns_opentherm_save_settings_cmd, + &sns_opentherm_flags_cmd, + &sns_opentherm_set_central_heating_cmd}; + +void sns_opentherm_cmd(void) { } +void sns_opentherm_boiler_setpoint_cmd(void) +{ + bool query = strlen(XdrvMailbox.data) == 0; + if (!query) + { + sns_ot_boiler_status.m_boilerSetpoint = atof(XdrvMailbox.data); + } + ResponseCmndFloat(sns_ot_boiler_status.m_boilerSetpoint, Settings.flag2.temperature_resolution); +} + +void sns_opentherm_hot_water_setpoint_cmd(void) +{ + bool query = strlen(XdrvMailbox.data) == 0; + if (!query) + { + sns_ot_boiler_status.m_hotWaterSetpoint = atof(XdrvMailbox.data); + } + ResponseCmndFloat(sns_ot_boiler_status.m_hotWaterSetpoint, Settings.flag2.temperature_resolution); +} + +void sns_opentherm_save_settings_cmd(void) +{ + Settings.ot_hot_water_setpoint = (uint8_t)sns_ot_boiler_status.m_hotWaterSetpoint; + Settings.ot_boiler_setpoint = (uint8_t)sns_ot_boiler_status.m_boilerSetpoint; + ResponseCmndDone(); +} + +void sns_opentherm_flags_cmd(void) +{ + bool query = strlen(XdrvMailbox.data) == 0; + if (!query) + { + + Settings.ot_flags = sns_opentherm_read_flags(XdrvMailbox.data, XdrvMailbox.data_len); + + sns_opentherm_init_boiler_status(); + } + bool addComma = false; + mqtt_data[0] = 0; + for (int pos = 0; pos < OT_FLAGS_COUNT; ++pos) + { + int mask = 1 << pos; + int mode = Settings.ot_flags & (uint8_t)mask; + if (mode > 0) + { + if (addComma) + { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, sns_opentherm_flag_text(mode)); + addComma = true; + } + } +} + +void sns_opentherm_set_central_heating_cmd(void) +{ + bool query = strlen(XdrvMailbox.data) == 0; + if (!query) + { + sns_ot_boiler_status.m_enableCentralHeating = atoi(XdrvMailbox.data); + } + ResponseCmndNumber(sns_ot_boiler_status.m_enableCentralHeating ? 1 : 0); +} + + + + + +bool Xsns69(uint8_t function) +{ + bool result = false; + if (FUNC_INIT == function) + { + if (sns_opentherm_Init()) + { + sns_opentherm_CheckSettings(); + } + } + + if (!sns_ot_master) + { + return result; + } + + switch (function) + { + case FUNC_LOOP: + sns_ot_master->process(); + break; + case FUNC_EVERY_100_MSECOND: + if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_READY && sns_ot_master->isReady()) + { + unsigned long request = sns_opentherm_get_next_request(&sns_ot_boiler_status); + if (-1 != request) + { + sns_ot_master->sendRequestAync(request); + sns_ot_connection_status = OpenThermConnectionStatus::OTC_INFLIGHT; + } + } + break; + case FUNC_EVERY_SECOND: + if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_DISCONNECTED) + { + + if (sns_ot_disconnect_cooldown == 0) + { + sns_ot_disconnect_cooldown = SNS_OT_DISCONNECT_COOLDOWN_SECONDS; + } + else if (--sns_ot_disconnect_cooldown == 0) + { + sns_ot_connection_status = OpenThermConnectionStatus::OTC_CONNECTING; + } + } + else if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_CONNECTING) + { + sns_ot_start_handshake(); + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kOpenThermCommands, OpenThermCommands); + break; + case FUNC_JSON_APPEND: + sns_opentherm_stat(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + sns_opentherm_stat(0); + break; +#endif + } + + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_69_opentherm_protocol.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_69_opentherm_protocol.ino" +#ifdef USE_OPENTHERM + +#include "OpenTherm.h" + + + +#define OPENTHERM_BOILER_SETPOINT_TOLERANCE 1.0 + +typedef union { + uint8_t m_flags; + struct + { + uint8_t notSupported : 1; + uint8_t supported : 1; + uint8_t retryCount : 2; + }; +} OpenThermParamFlags; + +typedef union { + float m_float; + uint8_t m_u8; + uint16_t m_u16; + unsigned long m_ul; + bool m_bool; +} ResponseStorage; + +typedef struct OpenThermCommandT +{ + const char *m_command_name; + uint8_t m_command_code; + OpenThermParamFlags m_flags; + ResponseStorage m_results[2]; + unsigned long (*m_ot_make_request)(OpenThermCommandT *self, OT_BOILER_STATUS_T *boilerStatus); + void (*m_ot_parse_response)(OpenThermCommandT *self, OT_BOILER_STATUS_T *boilerStatus, unsigned long response); + void (*m_ot_appent_telemetry)(OpenThermCommandT *self); +} OpenThermCommand; + +OpenThermCommand sns_opentherm_commands[] = { + { + .m_command_name = "SLAVE", + .m_command_code = 0, + + + .m_flags = {.supported = 1}, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_set_slave_flags, + .m_ot_parse_response = sns_opentherm_parse_slave_flags, + .m_ot_appent_telemetry = sns_opentherm_tele_slave_flags}, + { + .m_command_name = "BTMP", + .m_command_code = 0, + + .m_flags = {.supported = 1}, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_set_boiler_temperature, + .m_ot_parse_response = sns_opentherm_parse_set_boiler_temperature, + .m_ot_appent_telemetry = sns_opentherm_tele_boiler_temperature}, + { + .m_command_name = "HWTMP", + .m_command_code = 0, + + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_set_boiler_dhw_temperature, + .m_ot_parse_response = sns_opentherm_parse_boiler_dhw_temperature, + .m_ot_appent_telemetry = sns_opentherm_tele_boiler_dhw_temperature}, + { + .m_command_name = "ASFF", + .m_command_code = 0, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_flags, + .m_ot_parse_response = sns_opentherm_parse_flags, + .m_ot_appent_telemetry = sns_opentherm_tele_flags}, + { + .m_command_name = "OEMD", + .m_command_code = 0, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_oem_diag, + .m_ot_parse_response = sns_opentherm_parse_oem_diag, + .m_ot_appent_telemetry = sns_opentherm_tele_oem_diag}, + { + .m_command_name = "FLM", + .m_command_code = (uint8_t)OpenThermMessageID::RelModLevel, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_flame_modulation, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "TB", + .m_command_code = (uint8_t)OpenThermMessageID::Tboiler, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_boiler_temperature, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "TDHW", + .m_command_code = (uint8_t)OpenThermMessageID::Tdhw, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_generic_float, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "TOUT", + .m_command_code = (uint8_t)OpenThermMessageID::Toutside, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_generic_float, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "TRET", + .m_command_code = (uint8_t)OpenThermMessageID::Tret, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_generic_float, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "DHWS", + .m_command_code = (uint8_t)OpenThermMessageID::TdhwSet, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_dhw_setpoint, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + { + .m_command_name = "TMAX", + .m_command_code = (uint8_t)OpenThermMessageID::MaxTSet, + .m_flags = 0, + .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, + .m_ot_make_request = sns_opentherm_get_generic_float, + .m_ot_parse_response = sns_opentherm_parse_generic_float, + .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, + +}; + + +unsigned long sns_opentherm_set_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) +{ + bool centralHeatingIsOn = status->m_enableCentralHeating; + + if (status->m_useDiagnosticIndicationAsHeatRequest) { + centralHeatingIsOn |= OpenTherm::isDiagnostic(status->m_slave_raw_status); + } + + if (self->m_results[1].m_bool != centralHeatingIsOn) { + AddLog_P2(LOG_LEVEL_INFO, + PSTR("[OTH]: Central Heating transitioning from %s to %s"), + self->m_results[1].m_bool ? "on" : "off", + status->m_enableCentralHeating ? "on" : "off"); + } + self->m_results[1].m_bool = centralHeatingIsOn; + + unsigned int data = centralHeatingIsOn | + (status->m_enableHotWater << 1) | + (status->m_enableCooling << 2) | + (status->m_enableOutsideTemperatureCompensation << 3) | + (status->m_enableCentralHeating2 << 4); + + data <<= 8; + + return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Status, data); +} + +void sns_opentherm_parse_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + boilerStatus->m_slave_raw_status = response; + self->m_results[0].m_ul = response; +} + +#define OT_FLAG_TO_ON_OFF(status,flag) ((((status) & (flag)) != 0) ? 1 : 0) +void sns_opentherm_tele_slave_flags(struct OpenThermCommandT *self) +{ + unsigned long st = self->m_results[0].m_ul; + ResponseAppend_P(PSTR("{\"FAULT\":%d,\"CH\":%d,\"DHW\":%d,\"FL\":%d,\"COOL\":%d,\"CH2\":%d,\"DIAG\":%d,\"RAW\":%lu}"), + OT_FLAG_TO_ON_OFF(st, 0x01), + OT_FLAG_TO_ON_OFF(st, 0x02), + OT_FLAG_TO_ON_OFF(st, 0x04), + OT_FLAG_TO_ON_OFF(st, 0x08), + OT_FLAG_TO_ON_OFF(st, 0x10), + OT_FLAG_TO_ON_OFF(st, 0x20), + OT_FLAG_TO_ON_OFF(st, 0x40), + st); +} + + +unsigned long sns_opentherm_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) +{ + + + + float diff = abs(status->m_boilerSetpoint - self->m_results[0].m_float); + + if (diff < OPENTHERM_BOILER_SETPOINT_TOLERANCE) + { + return -1; + } + AddLog_P2(LOG_LEVEL_INFO, + PSTR("[OTH]: Setting Boiler Temp. Old: %d, New: %d"), + (int)self->m_results[0].m_float, + (int)status->m_boilerSetpoint); + self->m_results[0].m_float = status->m_boilerSetpoint; + + unsigned int data = OpenTherm::temperatureToData(status->m_boilerSetpoint); + return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::TSet, data); +} +void sns_opentherm_parse_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[1].m_float = OpenTherm::getFloat(response); +} +void sns_opentherm_tele_boiler_temperature(struct OpenThermCommandT *self) +{ + char requested[FLOATSZ]; + dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, requested); + char actual[FLOATSZ]; + dtostrfd(self->m_results[1].m_float, Settings.flag2.temperature_resolution, actual); + + + bool isFault = abs(self->m_results[1].m_float - self->m_results[0].m_float) > OPENTHERM_BOILER_SETPOINT_TOLERANCE; + + ResponseAppend_P(PSTR("{\"FAULT\":%d,\"REQ\":%s,\"ACT\": %s}"), + (int)isFault, + requested, + actual); +} + + +unsigned long sns_opentherm_set_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) +{ + + float diff = abs(status->m_hotWaterSetpoint - self->m_results[0].m_float); + + if (diff < OPENTHERM_BOILER_SETPOINT_TOLERANCE) + { + return -1; + } + AddLog_P2(LOG_LEVEL_INFO, + PSTR("[OTH]: Setting Hot Water Temp. Old: %d, New: %d"), + (int)self->m_results[0].m_float, + (int)status->m_hotWaterSetpoint); + + self->m_results[0].m_float = status->m_hotWaterSetpoint; + + unsigned int data = OpenTherm::temperatureToData(status->m_hotWaterSetpoint); + return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::TdhwSet, data); +} +void sns_opentherm_parse_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[1].m_float = OpenTherm::getFloat(response); +} +void sns_opentherm_tele_boiler_dhw_temperature(struct OpenThermCommandT *self) +{ + char requested[FLOATSZ]; + dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, requested); + char actual[FLOATSZ]; + dtostrfd(self->m_results[1].m_float, Settings.flag2.temperature_resolution, actual); + + ResponseAppend_P(PSTR("{\"REQ\":%s,\"ACT\": %s}"), + requested, + actual); +} + + +unsigned long sns_opentherm_get_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) +{ + return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::ASFflags, 0); +} + +void sns_opentherm_parse_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + uint8_t fault_code = (response >> 8) & 0xFF; + uint8_t oem_fault_code = response & 0xFF; + boilerStatus->m_fault_code = fault_code; + boilerStatus->m_oem_fault_code = fault_code; + self->m_results[0].m_u8 = fault_code; + self->m_results[1].m_u8 = oem_fault_code; +} + +void sns_opentherm_tele_flags(struct OpenThermCommandT *self) +{ + ResponseAppend_P(PSTR("{\"FC\":%d,\"OFC\":%d}"), + (int)self->m_results[0].m_u8, + (int)self->m_results[1].m_u8); +} + + +unsigned long sns_opentherm_get_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) +{ + return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::OEMDiagnosticCode, 0); +} + +void sns_opentherm_parse_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + uint16_t diag_code = (uint16_t)response & 0xFFFF; + boilerStatus->m_oem_diag_code = diag_code; + self->m_results[0].m_u16 = diag_code; +} + +void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self) +{ + ResponseAppend_P(PSTR("%d"), (int)self->m_results[0].m_u16); +} + + +unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) +{ + return OpenTherm::buildRequest(OpenThermRequestType::READ, (OpenThermMessageID)self->m_command_code, 0); +} + +void sns_opentherm_parse_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[0].m_float = OpenTherm::getFloat(response); +} + +void sns_opentherm_tele_generic_float(struct OpenThermCommandT *self) +{ + char str[FLOATSZ]; + dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, str); + ResponseAppend_P(PSTR("%s"), str); +} + + +void sns_opentherm_parse_dhw_setpoint(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[0].m_float = OpenTherm::getFloat(response); + boilerStatus->m_hotWaterSetpoint_read = self->m_results[0].m_float; +} + +void sns_opentherm_parse_flame_modulation(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[0].m_float = OpenTherm::getFloat(response); + boilerStatus->m_flame_modulation_read = self->m_results[0].m_float; +} + +void sns_opentherm_parse_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + self->m_results[0].m_float = OpenTherm::getFloat(response); + boilerStatus->m_boiler_temperature_read = self->m_results[0].m_float; +} + + + + + +#define SNS_OT_COMMANDS_COUNT (sizeof(sns_opentherm_commands) / sizeof(OpenThermCommand)) +int sns_opentherm_current_command = SNS_OT_COMMANDS_COUNT; + +unsigned long sns_opentherm_get_next_request(struct OT_BOILER_STATUS_T *boilerStatus) +{ + + if (++sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) + { + sns_opentherm_current_command = 0; + } + + struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; + + if (cmd->m_flags.notSupported) + { + return -1; + } + + return cmd->m_ot_make_request(cmd, boilerStatus); +} + +void sns_opentherm_check_retry_request() +{ + if (sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) + { + return; + } + struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; + + bool canRetry = ++cmd->m_flags.retryCount < 3; + + if (!canRetry && !cmd->m_flags.supported) + { + cmd->m_flags.notSupported = true; + AddLog_P2(LOG_LEVEL_ERROR, + PSTR("[OTH]: command %s is not supported by the boiler. Last status: %s"), + cmd->m_command_name, + sns_ot_master->statusToString(sns_ot_master->getLastResponseStatus())); + } +} + +void sns_opentherm_process_success_response(struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) +{ + if (sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) + { + return; + } + struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; + + cmd->m_flags.supported = true; + + cmd->m_ot_parse_response(cmd, boilerStatus, response); +} + +void sns_opentherm_dump_telemetry() +{ + bool add_coma = false; + for (int i = 0; i < SNS_OT_COMMANDS_COUNT; ++i) + { + struct OpenThermCommandT *cmd = &sns_opentherm_commands[i]; + if (!cmd->m_flags.supported) + { + continue; + } + + ResponseAppend_P(PSTR("%s\"%s\":"), add_coma ? "," : "", cmd->m_command_name); + + cmd->m_ot_appent_telemetry(cmd); + + add_coma = true; + } +} +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_70_veml6075.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_70_veml6075.ino" +#ifdef USE_I2C +#ifdef USE_VEML6075 + + + + + + +#define XSNS_70 70 +#define XI2C_49 49 + + +#define VEML6075_ADDR 0x10 +#define VEML6075_CHIP_ID 0x26 + + +#define VEML6075_REG_CONF 0x00 +#define VEML6075_REG_UVA 0x07 +#define VEML6075_REG_DARK 0x08 +#define VEML6075_REG_UVB 0x09 +#define VEML6075_REG_UVCOMP1 0x0A +#define VEML6075_REG_UVCOMP2 0x0B +#define VEML6075_REG_ID 0x0C + + +#define VEML6075_DEFAULT_UVA_A_COEFF 2.22 +#define VEML6075_DEFAULT_UVA_B_COEFF 1.33 +#define VEML6075_DEFAULT_UVB_C_COEFF 2.95 +#define VEML6075_DEFAULT_UVB_D_COEFF 1.74 +#define UVA_RESPONSIVITY_100MS_UNCOVERED 0.001461 +#define UVB_RESPONSIVITY_100MS_UNCOVERED 0.002591 + +const float UVA_RESPONSIVITY[] PROGMEM = +{ + UVA_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, + UVA_RESPONSIVITY_100MS_UNCOVERED, + UVA_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, + UVA_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, + UVA_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 +}; + +const float UVB_RESPONSIVITY[] PROGMEM = +{ + UVB_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, + UVB_RESPONSIVITY_100MS_UNCOVERED, + UVB_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, + UVB_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, + UVB_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 +}; + + +#define D_NAME_VEML6075 "VEML6075" +#define D_UVA_INTENSITY "UVA intensity" +#define D_UVB_INTENSITY "UVB intensity" + +const char HTTP_SNS_UVA[] PROGMEM = "{s}%s " D_UVA_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}"; +const char HTTP_SNS_UVB[] PROGMEM = "{s}%s " D_UVB_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}"; +const char HTTP_SNS_UVINDEX[] PROGMEM = "{s}%s " D_UV_INDEX "{m}%s {e}"; +const char JSON_SNS_VEML6075[] PROGMEM = ",\"%s\":{\"" D_JSON_UVA_INTENSITY "\":%d,\"" D_JSON_UVB_INTENSITY "\":%d,\"" D_JSON_UV_INDEX "\":%s}"; +const char S_JSON_VEML6075_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_VEML6075 "\":{\"%s\":%d}}"; + +const char kVEML6075_Commands[] PROGMEM = D_CMND_VEML6075_POWER "|" D_CMND_VEML6075_DYNAMIC "|" D_CMND_VEML6075_INTTIME; + +enum VEML6075_Commands { + CMND_VEML6075_PWR, + CMND_VEML6075_SET_HD, + CMND_VEML6075_SET_UVIT, + }; + + +struct VEML6075STRUCT +{ + char types[9] = D_NAME_VEML6075; + uint8_t address = VEML6075_ADDR; + uint8_t inttime = 0; + uint16_t uva = 0; + uint16_t uvb = 0; + uint16_t uva_raw = 0; + uint16_t uvb_raw = 0; + uint16_t comp1 = 0; + uint16_t comp2 = 0; + uint16_t conf = 0; + float uvi = 0.0f; +} veml6075_sensor; + +uint8_t veml6075_active = 0; + + +typedef union { + struct { + uint8_t pwr:1; + uint8_t forded_auto:1; + uint8_t forced_trigger:1; + uint8_t hd:1; + uint8_t inttime:3; + uint8_t spare7:1; + }; + uint16_t config; +} veml6075configRegister; + +veml6075configRegister veml6075Config; + + + +uint16_t VEML6075read16 (uint8_t reg) { + uint16_t swap = I2cRead16(VEML6075_ADDR, reg); + uint16_t ret = ((swap & 0xFF) << 8) | (swap >> 8); + return ret; +} + +void VEML6075write16 (uint8_t reg, uint16_t val) { + uint16_t swap = ((val & 0xFF) << 8) | (val >> 8); + I2cWrite16(VEML6075_ADDR, reg, swap); +} + +float VEML6075calcUVA (void) { + float uva_calc = veml6075_sensor.uva_raw - (VEML6075_DEFAULT_UVA_A_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVA_B_COEFF * veml6075_sensor.comp2); + return uva_calc; +} + +float VEML6075calcUVB (void) { + float uvb_calc = veml6075_sensor.uvb_raw - (VEML6075_DEFAULT_UVB_C_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVB_D_COEFF * veml6075_sensor.comp2); + return uvb_calc; +} + +float VEML6075calcUVI (void) { + float uvi_calc = ((veml6075_sensor.uva * UVA_RESPONSIVITY[veml6075_sensor.inttime]) + (veml6075_sensor.uvb * UVB_RESPONSIVITY[veml6075_sensor.inttime])) / 2; + return uvi_calc; +} + +void VEML6075SetHD(uint8_t val){ + veml6075Config.hd = val; + VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); +} + +uint8_t VEML6075ReadHD(void){ + veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); + return veml6075Config.hd; +} + +void VEML6075SetUvIt(uint8_t val){ + veml6075Config.inttime = val; + VEML6075Pwr(1); + VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); + VEML6075Pwr(0); +} + +uint8_t VEML6075GetUvIt(void){ + veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); + return veml6075Config.inttime; +} + +void VEML6075Pwr(uint8_t val){ + veml6075Config.pwr = val; + VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); +} + +uint8_t VEML6075GetPwr(void){ + veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); + return veml6075Config.pwr; +} + +void VEML6075ReadData(void) +{ + veml6075_sensor.uva_raw = VEML6075read16 (VEML6075_REG_UVA); + veml6075_sensor.uvb_raw = VEML6075read16 (VEML6075_REG_UVB); + veml6075_sensor.comp1 = VEML6075read16 (VEML6075_REG_UVCOMP1); + veml6075_sensor.comp2 = VEML6075read16 (VEML6075_REG_UVCOMP2); + veml6075_sensor.inttime = VEML6075GetUvIt(); + veml6075_sensor.uva = VEML6075calcUVA(); + veml6075_sensor.uvb = VEML6075calcUVB(); + veml6075_sensor.uvi = VEML6075calcUVI(); +} + +bool VEML6075init(void) +{ + uint8_t id = VEML6075read16 (VEML6075_REG_ID); + if(id == VEML6075_CHIP_ID) + return true; + return false; +} + +void VEML6075Detect(void) { + if (I2cActive(veml6075_sensor.address)) return; + + if (VEML6075init()) { + I2cSetActiveFound(veml6075_sensor.address, veml6075_sensor.types); + VEML6075write16 (VEML6075_REG_CONF, 0x10); + veml6075_active = 1; + } +} + +void VEML6075EverySecond(void) { + VEML6075ReadData(); +} + +bool VEML6075Cmd(void) { + char command[CMDSZ]; + uint8_t name_len = strlen(D_NAME_VEML6075); + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_VEML6075), name_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kVEML6075_Commands); + switch (command_code) { + case CMND_VEML6075_PWR: + if (XdrvMailbox.data_len) { + if (2 >= XdrvMailbox.payload) { + VEML6075Pwr(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetPwr()); + break; + case CMND_VEML6075_SET_HD: + if (XdrvMailbox.data_len) { + if (2 >= XdrvMailbox.payload) { + VEML6075SetHD(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075ReadHD()); + break; + case CMND_VEML6075_SET_UVIT: + if (XdrvMailbox.data_len) { + if (4 >= XdrvMailbox.payload) { + VEML6075SetUvIt(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetUvIt()); + break; + default: + return false; + } + return true; + } else { + return false; + } +} + +void VEML6075Show(bool json) +{ + char s_uvindex[FLOATSZ]; + dtostrfd(veml6075_sensor.uvi,1, s_uvindex); + + if (json) { + ResponseAppend_P(JSON_SNS_VEML6075, D_NAME_VEML6075, veml6075_sensor.uva, veml6075_sensor.uvb, s_uvindex); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_UVA, D_NAME_VEML6075, veml6075_sensor.uva); + WSContentSend_PD(HTTP_SNS_UVB, D_NAME_VEML6075, veml6075_sensor.uvb); + WSContentSend_PD(HTTP_SNS_UVINDEX, D_NAME_VEML6075 ,s_uvindex); +#endif + } +} + + + + + +bool Xsns70(uint8_t function) +{ + if (!I2cEnabled(XI2C_49)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + VEML6075Detect(); + } + else if (veml6075_active) { + switch (function) { + case FUNC_EVERY_SECOND: + VEML6075EverySecond(); + break; + case FUNC_COMMAND: + result = VEML6075Cmd(); + break; + case FUNC_JSON_APPEND: + VEML6075Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + VEML6075Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_71_veml7700.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_71_veml7700.ino" +#ifdef USE_I2C +#ifdef USE_VEML7700 + + + + + + +#define XSNS_71 71 +#define XI2C_50 50 + +#include "Adafruit_VEML7700.h" +Adafruit_VEML7700 veml7700 = Adafruit_VEML7700(); + +#define D_NAME_VEML7700 "VEML7700" +#define D_WHITE_CONTENT "White content" + +const char HTTP_SNS_WHITE[] PROGMEM = "{s}%s " D_WHITE_CONTENT "{m}%d {e}"; +const char JSON_SNS_VEML7700[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_WHITE_CONTENT "\":%d}"; + +#define D_CMND_VEML7700_PWR "power" +#define D_CMND_VEML7700_GAIN "gain" +#define D_CMND_VEML7700_INTTIME "inttime" +#define D_CMND_VEML7700_PERSIST "persist" + +const char S_JSON_VEML7700_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_VEML7700 "\":{\"%s\":%d}}"; +const char kVEML7700_Commands[] PROGMEM = D_CMND_VEML7700_PWR "|" D_CMND_VEML7700_GAIN "|" D_CMND_VEML7700_INTTIME "|" D_CMND_VEML7700_PERSIST; + +enum VEML7700_Commands { + CMND_VEML7700_PWR, + CMND_VEML7700_GAIN, + CMND_VEML7700_SET_IT, + CMND_VEML7700_PERSIST, +}; + +struct VEML7700STRUCT +{ + bool active = 0; + char types[9] = D_NAME_VEML7700; + uint8_t address = VEML7700_I2CADDR_DEFAULT; + uint32_t lux_normalized = 0; + uint32_t white_normalized = 0; +} veml7700_sensor; + + + + +void VEML7700Detect(void) { + if (!I2cSetDevice(veml7700_sensor.address)) return; + if (veml7700.begin()) { + I2cSetActiveFound(veml7700_sensor.address, veml7700_sensor.types); + veml7700_sensor.active = 1; + } +} + +uint16_t VEML7700TranslateItMs (uint8_t ittime){ + switch (ittime) { + case 0: return 100; + case 1: return 200; + case 2: return 400; + case 3: return 800; + case 8: return 50; + case 12: return 25; + default: return 0xFFFF; + } +} + +uint8_t VEML7700TranslateItInt (uint16_t ittimems){ + switch (ittimems) { + case 100: return 0; + case 200: return 1; + case 400: return 2; + case 800: return 3; + case 50: return 8; + case 25: return 12; + default: return 0xFF; + } +} + +void VEML7700EverySecond(void) { + veml7700_sensor.lux_normalized = (uint32_t) veml7700.readLuxNormalized(); + veml7700_sensor.white_normalized = (uint32_t) veml7700.readWhiteNormalized(); +} + +void VEML7700Show(bool json) +{ + if (json) { + ResponseAppend_P(JSON_SNS_VEML7700, D_NAME_VEML7700, veml7700_sensor.lux_normalized, veml7700_sensor.white_normalized); + +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, veml7700_sensor.lux_normalized); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, D_NAME_VEML7700, veml7700_sensor.lux_normalized); + WSContentSend_PD(HTTP_SNS_WHITE, D_NAME_VEML7700, veml7700_sensor.white_normalized); +#endif + } +} + +bool VEML7700Cmd(void) { + char command[CMDSZ]; + uint8_t name_len = strlen(D_NAME_VEML7700); + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_VEML7700), name_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kVEML7700_Commands); + switch (command_code) { + case CMND_VEML7700_PWR: + if (XdrvMailbox.data_len) { + if (2 >= XdrvMailbox.payload) { + veml7700.enable(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.enabled()); + break; + case CMND_VEML7700_GAIN: + if (XdrvMailbox.data_len) { + if (4 >= XdrvMailbox.payload) { + veml7700.setGain(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.getGain()); + break; + case CMND_VEML7700_SET_IT: { + if (XdrvMailbox.data_len) { + uint8_t data = VEML7700TranslateItInt(XdrvMailbox.payload); + if (0xFF != data) { + veml7700.setIntegrationTime(data); + } + } + uint16_t dataret = VEML7700TranslateItMs(veml7700.getIntegrationTime()); + Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, dataret); + } + break; + case CMND_VEML7700_PERSIST: + if (XdrvMailbox.data_len) { + if (4 >= XdrvMailbox.payload) { + veml7700.setPersistence(XdrvMailbox.payload); + } + } + Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.getPersistence()); + break; + default: + return false; + } + return true; + } + else { + return false; + } +} + + + + +bool Xsns71(uint8_t function) +{ + if (!I2cEnabled(XI2C_50)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + VEML7700Detect(); + } + else if (veml7700_sensor.active) { + switch (function) { + case FUNC_EVERY_SECOND: + VEML7700EverySecond(); + break; + case FUNC_COMMAND: + result = VEML7700Cmd(); + break; + case FUNC_JSON_APPEND: + VEML7700Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + VEML7700Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_72_mcp9808.ino" +# 21 "/workspace/Tasmota/tasmota/xsns_72_mcp9808.ino" +#ifdef USE_I2C +#ifdef USE_MCP9808 + + + + + + + +#define XSNS_72 72 +#define XI2C_51 51 + +#include "Adafruit_MCP9808.h" +Adafruit_MCP9808 mcp9808 = Adafruit_MCP9808(); + +#define MCP9808_MAX_SENSORS 8 +#define MCP9808_START_ADDRESS 0x18 + +struct { +char types[9] = "MCP9808"; +uint8_t count = 0; +} mcp9808_cfg; + +struct { + float temperature = NAN; + uint8_t address; +} mcp9808_sensors[MCP9808_MAX_SENSORS]; + + + +float MCP9808Read(uint8_t addr) { + float t = mcp9808.readTempC(addr); + return t; +} + +void MCP9808Detect(void) { + for (uint8_t i = 0; i < MCP9808_MAX_SENSORS; i++) { + if (!I2cSetDevice(MCP9808_START_ADDRESS + i)) { continue; } + + if (mcp9808.begin(MCP9808_START_ADDRESS + i)) { + mcp9808_sensors[mcp9808_cfg.count].address = MCP9808_START_ADDRESS + i; + I2cSetActiveFound(mcp9808_sensors[mcp9808_cfg.count].address, mcp9808_cfg.types); + mcp9808.setResolution (mcp9808_sensors[mcp9808_cfg.count].address, 2); + mcp9808_cfg.count++; + } + } +} + +void MCP9808EverySecond(void) { + for (uint32_t i = 0; i < mcp9808_cfg.count; i++) { + float t = MCP9808Read(mcp9808_sensors[i].address); + mcp9808_sensors[i].temperature = ConvertTemp(t); + } +} + +void MCP9808Show(bool json) { + for (uint32_t i = 0; i < mcp9808_cfg.count; i++) { + char temperature[33]; + dtostrfd(mcp9808_sensors[i].temperature, Settings.flag2.temperature_resolution, temperature); + + char sensor_name[11]; + strlcpy(sensor_name, mcp9808_cfg.types, sizeof(sensor_name)); + if (mcp9808_cfg.count > 1) { + snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), mcp9808_sensors[i].address); + } + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, sensor_name, temperature); + if ((0 == tele_period) && (0 == i)) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, mcp9808_sensors[i].temperature); +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns72(uint8_t function) +{ + if (!I2cEnabled(XI2C_51)) { return false; } + bool result = false; + + if (FUNC_INIT == function) { + MCP9808Detect(); + } + else if (mcp9808_cfg.count){ + switch (function) { + case FUNC_EVERY_SECOND: + MCP9808EverySecond(); + break; + case FUNC_JSON_APPEND: + MCP9808Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MCP9808Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" +#ifdef USE_I2C +#ifdef USE_HP303B +# 30 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" +#define XSNS_73 73 +#define XI2C_52 52 + +#define HP303B_MAX_SENSORS 2 +#define HP303B_START_ADDRESS 0x76 + +#include + +LOLIN_HP303B HP303BSensor = LOLIN_HP303B(); + +struct { + int16_t oversampling = 7; + char types[7] = "HP303B"; + uint8_t count = 0; +} hp303b_cfg; + +struct BHP303B { + float temperature = NAN; + float pressure = NAN; + uint8_t address; + uint8_t valid = 0; +} hp303b_sensor[HP303B_MAX_SENSORS]; + + + +bool HP303B_Read(uint32_t hp303b_idx) { + if (hp303b_sensor[hp303b_idx].valid) { hp303b_sensor[hp303b_idx].valid--; } + + float t; + if (HP303BSensor.measureTempOnce(t, hp303b_sensor[hp303b_idx].address, hp303b_cfg.oversampling) != 0) { + return false; + } + + float p; + if (HP303BSensor.measurePressureOnce(p, hp303b_sensor[hp303b_idx].address, hp303b_cfg.oversampling) != 0) { + return false; + } + + hp303b_sensor[hp303b_idx].temperature = (float)ConvertTemp(t); + hp303b_sensor[hp303b_idx].pressure = (float)ConvertPressure(p / 100); + + hp303b_sensor[hp303b_idx].valid = SENSOR_MAX_MISS; + return true; +} + + + +void HP303B_Detect(void) { + for (uint32_t i = 0; i < HP303B_MAX_SENSORS; i++) { + if (!I2cSetDevice(HP303B_START_ADDRESS + i)) { continue; } + + if (HP303BSensor.begin(HP303B_START_ADDRESS + i)) { + hp303b_sensor[hp303b_cfg.count].address = HP303B_START_ADDRESS + i; + I2cSetActiveFound(hp303b_sensor[hp303b_cfg.count].address, hp303b_cfg.types); + hp303b_cfg.count++; + } + } +} + +void HP303B_EverySecond(void) { + for (uint32_t i = 0; i < hp303b_cfg.count; i++) { + if (uptime &1) { + if (!HP303B_Read(i)) { + AddLogMissed(hp303b_cfg.types, hp303b_sensor[i].valid); + } + } + } +} + +void HP303B_Show(bool json) { + for (uint32_t i = 0; i < hp303b_cfg.count; i++) { + if (hp303b_sensor[i].valid) { + char sensor_name[12]; + strlcpy(sensor_name, hp303b_cfg.types, sizeof(sensor_name)); + if (hp303b_cfg.count > 1) { + snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), hp303b_sensor[i].address); + } + + float sealevel = 0.0; + if (hp303b_sensor[i].pressure != 0.0) { + sealevel = (hp303b_sensor[i].pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + sealevel = ConvertPressure(sealevel); + } + + char str_temperature[33]; + dtostrfd(hp303b_sensor[i].temperature, Settings.flag2.temperature_resolution, str_temperature); + char str_pressure[33]; + dtostrfd(hp303b_sensor[i].pressure, Settings.flag2.pressure_resolution, str_pressure); + char sea_pressure[33]; + dtostrfd(sealevel, Settings.flag2.pressure_resolution, sea_pressure); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_PRESSURE "\":%s"), sensor_name, str_temperature, str_pressure); + if (Settings.altitude != 0) { + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_TEMP, hp303b_sensor[i].temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, str_temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_PRESSURE, sensor_name, str_pressure, PressureUnit().c_str()); + if (Settings.altitude != 0) { + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, sensor_name, sea_pressure, PressureUnit().c_str()); + } +#endif + } + } + } +} + + + + + +bool Xsns73(uint8_t function) +{ + if (!I2cEnabled(XI2C_52)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + HP303B_Detect(); + } + else if (hp303b_cfg.count) { + switch (function) { + case FUNC_EVERY_SECOND: + HP303B_EverySecond(); + break; + case FUNC_JSON_APPEND: + HP303B_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HP303B_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_74_lmt01.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_74_lmt01.ino" +#ifdef USE_LMT01 + + + + + + + +#define XSNS_74 74 + +#define LMT01_TIMEOUT 200 + +bool lmt01_initialized = false; +float lmt01_temperature = NAN; + +void LMT01_Init(void) { + if (PinUsed(GPIO_LMT01)) { + pinMode(Pin(GPIO_LMT01), INPUT); + attachInterrupt(Pin(GPIO_LMT01), LMT01_countPulse, FALLING); + lmt01_initialized = true; + } +} + +volatile int lmt01_pulseCount = 0; + +void ICACHE_RAM_ATTR LMT01_countPulse(void) { + lmt01_pulseCount++; +} + +void LMT01_GetTemperature(void) { + int pulses = 0; + pulses = LMT01_getPulses(); + if (pulses >= 0) { + + + lmt01_temperature = ConvertTemp(0.0625 * pulses - 50); + } else { + lmt01_temperature = NAN; + } +} + +int LMT01_getPulses(void) { + int timeout = LMT01_TIMEOUT; + int hold = -1; + + while(lmt01_pulseCount != hold && --timeout > 0) { + hold = lmt01_pulseCount; + delay(1); + } + lmt01_pulseCount = 0; + + while(lmt01_pulseCount == 0 && --timeout > 0) { + delay(1); + } + hold = -1; + + while(lmt01_pulseCount != hold && --timeout > 0) { + hold = lmt01_pulseCount; + delay(1); + } + + if (timeout > 0 && hold >= 10) { + return hold; + } + return -1; +} + +void LMT01_Show(bool Json) { + char temp[33]; + dtostrfd(lmt01_temperature, Settings.flag2.temperature_resolution, temp); + + if (Json) { + ResponseAppend_P(JSON_SNS_TEMP, "LMT01", temp); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temp); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, lmt01_temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "LMT01", temp, TempUnit()); +#endif + } +} + + + + + +bool Xsns74(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + LMT01_Init(); + } + else if (lmt01_initialized) { + switch (function) { + case FUNC_EVERY_SECOND: + LMT01_GetTemperature(); + break; + case FUNC_JSON_APPEND: + LMT01_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LMT01_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" +#ifdef USE_PROMETHEUS + + + + +#define XSNS_75 75 + +void HandleMetrics(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); + + WSContentBegin(200, CT_PLAIN); + + + char parameter[FLOATSZ]; + + + WSContentSend_P(PSTR("# TYPE tasmota_info gauge\ntasmota_info{version=\"%s\",image=\"%s\",build_timestamp=\"%s\"} 1\n"), + my_version, my_image, GetBuildDateAndTime().c_str()); + WSContentSend_P(PSTR("# TYPE tasmota_uptime_seconds gauge\ntasmota_uptime_seconds %d\n"), uptime); + WSContentSend_P(PSTR("# TYPE tasmota_boot_count counter\ntasmota_boot_count %d\n"), Settings.bootcount); + WSContentSend_P(PSTR("# TYPE tasmota_flash_writes_total counter\ntasmota_flash_writes_total %d\n"), Settings.save_flag); + + + + WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_info gauge\ntasmota_wifi_station_info{bssid=\"%s\",ssid=\"%s\"} 1\n"), WiFi.BSSIDstr().c_str(), WiFi.SSID().c_str()); + + + WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_signal_dbm gauge\ntasmota_wifi_station_signal_dbm{mac_address=\"%s\"} %d\n"), WiFi.BSSIDstr().c_str(), WiFi.RSSI()); + + if (!isnan(global_temperature_celsius)) { + dtostrfd(global_temperature_celsius, Settings.flag2.temperature_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_temperature_celsius gauge\nglobal_temperature_celsius %s\n"), parameter); + } + if (global_humidity != 0) { + dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); + } + if (global_pressure_hpa != 0) { + dtostrfd(global_pressure_hpa, Settings.flag2.pressure_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_pressure_hpa gauge\nglobal_pressure_hpa %s\n"), parameter); + } + +#ifdef USE_ENERGY_SENSOR + dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_voltage_volts gauge\nenergy_voltage_volts %s\n"), parameter); + dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_current_amperes gauge\nenergy_current_amperes %s\n"), parameter); + dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_power_active_watts gauge\nenergy_power_active_watts %s\n"), parameter); + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_daily counter\nenergy_power_kilowatts_daily %s\n"), parameter); + dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter); +#endif +# 92 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" + WSContentEnd(); +} + + + + + +bool Xsns75(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer_on(PSTR("/metrics"), HandleMetrics); + break; + } + return result; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" +#ifdef USE_DYP +# 34 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" +#define XSNS_76 76 + +#include + +TasmotaSerial *DYPSerial = nullptr; + +#define DYP_CRCERROR -1 +#define DYP_BELOWMIN 0 +#define DYP_MIN 300 +#define DYP_MAX 4000 +#define DYP_ABOVEMAX 4999 +#define DYP_NOSENSOR 5999 + +uint16_t DYPDistance = 0; +bool DYPSensor = false; + + + +void DYPInit(void) { + DYPSensor = false; + if (PinUsed(GPIO_DYP_RX)) { + DYPSerial = new TasmotaSerial(Pin(GPIO_DYP_RX), -1, 1); + if (DYPSerial->begin(9600)) { + if (DYPSerial->hardwareSerial()) { + ClaimSerial(); + } + DYPSensor = true; + } + } +} + +void DYPEverySecond(void) { + if (!DYPSensor) { return; } + + + if (DYPSerial->available() < 6) { + DYPDistance = DYP_NOSENSOR; + return; + } + + + while (DYPSerial->available() > 7) { + DYPSerial->read(); + } + + + while (DYPSerial->available() > 3) { + + if (DYPSerial->read() != 0xFF) { + continue; + } + + + if (DYPSerial->available() > 2) { + uint8_t msb = DYPSerial->read(); + uint8_t lsb = DYPSerial->read(); + if (((uint16_t)(0xFF + msb + lsb) & 0xFF) == DYPSerial->read()) { + uint16_t data = (msb << 8) | lsb; + if (data < DYP_MIN) { + data = DYP_BELOWMIN; + } + if (data > DYP_MAX) { + data = DYP_ABOVEMAX; + } + DYPDistance = data; + } else { + DYPDistance = DYP_CRCERROR; + } + } + } +} + +void DYPShow(bool json) { + char types[5] = "DYP"; + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_DISTANCE "\":%d}"), types, DYPDistance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_RANGE, types, DYPDistance); +#endif + } +} + + + + + +bool Xsns76(uint8_t function) { + if (!PinUsed(GPIO_DYP_RX)) { return false; } + + switch (function) { + case FUNC_INIT: + DYPInit(); + break; + case FUNC_EVERY_SECOND: + DYPEverySecond(); + break; + case FUNC_JSON_APPEND: + DYPShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DYPShow(0); + break; +#endif + } + return false; +} + +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" +#ifdef USE_I2C +#ifdef USE_VL53L1X +# 30 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" +#define XSNS_77 77 +#define XI2C_54 54 + +#include "VL53L1X.h" +VL53L1X vl53l1x = VL53L1X(); + +#define VL53L1X_ADDRESS 0x29 + +struct { + bool ready = false; + uint16_t distance = 0; +} vl53l1x_sensors; + + + +void Vl53l1Detect(void) { + if (!I2cSetDevice(VL53L1X_ADDRESS)) { return; } + if (!vl53l1x.init()) { return; } + + I2cSetActiveFound(vl53l1x.getAddress(), "VL53L1X"); + vl53l1x.setTimeout(500); + vl53l1x.setDistanceMode(VL53L1X::Long); + vl53l1x.setMeasurementTimingBudget(140000); + vl53l1x.startContinuous(50); + vl53l1x_sensors.ready = true; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_VL53L1X[] PROGMEM = + "{s}VL53L1X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; +#endif + +void Vl53l1Every_250MSecond(void) { + + uint16_t dist = vl53l1x.read(); + if (!dist || dist > 4000) { + dist = 9999; + } + vl53l1x_sensors.distance = dist; +} + +#ifdef USE_DOMOTICZ +void Vl53l1Every_Second(void) { + char distance[FLOATSZ]; + dtostrfd((float)vl53l1x_sensors.distance / 10, 1, distance); + DomoticzSensor(DZ_ILLUMINANCE, distance); +} +#endif + +void Vl53l1Show(bool json) { + if (json) { +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + Vl53l1Every_Second(); + } +#endif + ResponseAppend_P(PSTR(",\"VL53L1X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l1x_sensors.distance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L1X, vl53l1x_sensors.distance); +#endif + } +} + + + + + +bool Xsns77(uint8_t function) +{ + if (!I2cEnabled(XI2C_54)) { return false; } + bool result = false; + + if (FUNC_INIT == function) { + Vl53l1Detect(); + } + else if (vl53l1x_sensors.ready) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + Vl53l1Every_250MSecond(); + break; +#ifdef USE_DOMOTICZ + case FUNC_EVERY_SECOND: + Vl53l1Every_Second(); + break; +#endif + case FUNC_JSON_APPEND: + Vl53l1Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l1Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezo.ino" +# 19 "/workspace/Tasmota/tasmota/xsns_78_ezo.ino" +#ifdef USE_I2C + +#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) + #define USE_EZO +#endif +#if defined(USE_EZO) + +#define D_EZO_DELAY 300 +#define D_EZO_MAX_BUF 40 + +const char D_EZO_NAME[] PROGMEM = "EZO"; + + + + +struct EZOStruct { + EZOStruct(uint32_t addr) : valid(0), addr(addr), lastRead(-2000) {} + + void MeasureRequest(void) + { + const uint8_t EZOMeasureCmd[2] = {'R', 0}; + + if (valid) { + valid--; + } + + Wire.beginTransmission(addr); + Wire.write(EZOMeasureCmd, sizeof(EZOMeasureCmd)); + Wire.endTransmission(); + + lastRead = millis(); + } + + void HandleCommand(char *cmd, uint32_t len) const + { + + Wire.beginTransmission(addr); + Wire.write(cmd, len); + if (Wire.endTransmission() != 0) { + return; + } + + + char data[D_EZO_MAX_BUF]; + for (uint32_t code = 254; code == 254; code = Wire.read()) { + delay(D_EZO_DELAY); + Wire.requestFrom(addr, sizeof(data)); + } + + for (uint32_t i = 0; Wire.available() > 0; i++) { + data[i] = Wire.read(); + } + + ResponseCmndChar((char *)data); + } + + bool isValid(void) + { + return valid; + } + + virtual void ProcessMeasurement(void); + virtual void Show(bool json, const char *name); + + static const char id[] PROGMEM; + +protected: + void ProcessMeasurement(char *const data, const uint32_t len, const uint32_t latency) + { + + const int32_t dur = lastRead + latency - millis(); + + + if (dur > 0) { + delay(dur); + } + + Wire.requestFrom(addr, len); + const char code = Wire.read(); + + if (code == 1) { + for (uint32_t i = 0; (Wire.available() > 0) && (i < len); i++) { + data[i] = Wire.read(); + } + + valid = SENSOR_MAX_MISS; + } + } + + uint8_t valid; + uint8_t addr; + uint32_t lastRead; +}; + +const char EZOStruct::id[] PROGMEM = ""; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoco2.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoco2.ino" +#ifdef USE_I2C +#ifdef USE_EZOCO2 + +#define EZO_CO2_READ_LATENCY 900 + +struct EZOCO2 : public EZOStruct { + EZOCO2(uint32_t addr) : EZOStruct(addr), CO2(0) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_CO2_READ_LATENCY); + + + if (uptime >= 10) { + CO2 = atoi(data); + } + } + + virtual void Show(bool json, const char *name) + { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d}" ), name, CO2); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_CO2, name, CO2); +#endif + } + } + + static const char id[] PROGMEM; + +private: + uint16_t CO2; +}; + +const char EZOCO2::id[] PROGMEM = "CO2"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoec.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoec.ino" +#ifdef USE_I2C +#ifdef USE_EZOEC + +#define EZO_EC_READ_LATENCY 600 + +struct EZOEC : public EZOStruct { + EZOEC(uint32_t addr) : EZOStruct(addr), EC(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_EC_READ_LATENCY); + EC = CharToFloat(data); + } + + virtual void Show(bool json, const char *name) + { + char str[10]; + dtostrfd(EC, 3, str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_EC "\":%s}" ), name, str); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_EC, name, str); +#endif + } + } + + static const char id[] PROGMEM; + +private: + float EC; +}; + +const char EZOEC::id[] PROGMEM = "EC"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezohum.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezohum.ino" +#ifdef USE_I2C +#ifdef USE_EZOHUM + +#define EZO_HUM_READ_LATENCY 300 + +struct EZOHUM : public EZOStruct { + EZOHUM(uint32_t addr) : EZOStruct(addr), humidity(NAN), temperature(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_HUM_READ_LATENCY); + + humidity = CharToFloat(data); + + char *next = strchr(data, ','); + if (next) { + temperature = CharToFloat(next + 1); + } + } + + virtual void Show(bool json, const char *name) + { + if (isnan(temperature)) { + char parameter[FLOATSZ]; + + dtostrfd(humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_PD(HTTP_SNS_HUM, name, parameter); + } else { + TempHumDewShow(json, (0 == tele_period), name, temperature, humidity); + } + } + + static const char id[] PROGMEM; + +private: + float humidity; + float temperature; +}; + +const char EZOHUM::id[] PROGMEM = "HUM"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoorp.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoorp.ino" +#ifdef USE_I2C +#ifdef USE_EZOORP + +#define EZO_ORP_READ_LATENCY 900 + +struct EZOORP : public EZOStruct { + EZOORP(uint32_t addr) : EZOStruct(addr), ORP(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_ORP_READ_LATENCY); + ORP = CharToFloat(data); + } + + virtual void Show(bool json, const char *name) + { + char str[8]; + dtostrfd(ORP, 2, str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ORP "\":%s}" ), name, str); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_ORP, name, str); +#endif + } + } + + static const char id[] PROGMEM; + +private: + float ORP; +}; + +const char EZOORP::id[] PROGMEM = "ORP"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoph.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoph.ino" +#ifdef USE_I2C +#ifdef USE_EZOPH + +#define EZO_PH_READ_LATENCY 900 + +struct EZOPH : public EZOStruct { + EZOPH(uint32_t addr) : EZOStruct(addr), pH(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_PH_READ_LATENCY); + pH = CharToFloat(data); + } + + virtual void Show(bool json, const char *name) + { + char str[6]; + dtostrfd(pH, 2, str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PH "\":%s}" ), name, str); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_PH, name, str); +#endif + } + } + + static const char id[] PROGMEM; + +private: + float pH; +}; + +const char EZOPH::id[] PROGMEM = "pH"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_ezortd.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_ezortd.ino" +#ifdef USE_I2C +#ifdef USE_EZORTD + +#define EZO_RTD_READ_LATENCY 600 + +struct EZORTD : public EZOStruct { + EZORTD(uint32_t addr) : EZOStruct(addr), temperature(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_RTD_READ_LATENCY); + temperature = CharToFloat(data); + } + + virtual void Show(bool json, const char *name) + { + char str[10]; + dtostrfd(ConvertTemp(temperature), Settings.flag2.temperature_resolution, str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), name, str); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_TEMP, name, str, TempUnit()); +#endif + } + } + + static const char id[] PROGMEM; + +private: + float temperature; +}; + +const char EZORTD::id[] PROGMEM = "RTD"; + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_78_xezo.ino" +# 20 "/workspace/Tasmota/tasmota/xsns_78_xezo.ino" +#ifdef USE_I2C +#if defined(USE_EZO) + +#define XSNS_78 78 +#define XI2C_55 55 + +#define EZO_ADDR_0 0x61 +#define EZO_ADDR_n 16 + + + +enum { + EZO_DO = 0x61, + EZO_ORP = 0x62, + EZO_PH = 0x63, + EZO_EC = 0x64, + + EZO_RTD = 0x66, + EZO_PMP = 0x67, + EZO_FLO = 0x68, + EZO_CO2 = 0x69, + EZO_PRS = 0x6A, + + EZO_O2 = 0x6C, + + + EZO_HUM = 0x6F, + EZO_RGB = 0x70, +}; + + + + +template struct IsComplete : std::false_type {}; +template struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type {}; + +#define GET_EZO_CLASS(CLASS) std::conditional::value, CLASS, EZOStruct>::type + + +const char *const EZOSupport[EZO_ADDR_n] PROGMEM = { + EZOStruct::id, + GET_EZO_CLASS(EZOORP)::id, + GET_EZO_CLASS(EZOPH)::id, + GET_EZO_CLASS(EZOEC)::id, + EZOStruct::id, + GET_EZO_CLASS(EZORTD)::id, + EZOStruct::id, + EZOStruct::id, + GET_EZO_CLASS(EZOCO2)::id, + EZOStruct::id, + EZOStruct::id, + EZOStruct::id, + EZOStruct::id, + EZOStruct::id, + GET_EZO_CLASS(EZOHUM)::id, + EZOStruct::id, +}; + +#define CREATE_EZO_CLASS(CLASS) \ + case EZO_ ## CLASS: \ + sensor[count] = new EZO ## CLASS(addr); \ + break; + + +struct EZOManager { + void Command() + { + char *at = XdrvMailbox.data; + uint32_t len = XdrvMailbox.data_len; + + + + if (at[0] == '-') { + int32_t idx = atoi(&at[1]) - 1; + at = strchr(at, ' '); + + if (!at++) { + return; + } + + len -= (at - XdrvMailbox.data); + + if ((idx >= 0) && (idx < count)) { + sensor[idx]->ProcessMeasurement(); + sensor[idx]->HandleCommand(at, len); + } + } else { + for (uint32_t i = 0; i < count; i++) { + sensor[i]->ProcessMeasurement(); + sensor[i]->HandleCommand(at, len); + } + } + } + + void EverySecond() + { + + if (count < 0) { + + if (uptime >= next) { + count++; + + if (count == -1) { + DetectRequest(); + next = uptime + 1; + } else if (count == 0) { + ProcessDetection(); + } + } + } + + for (int32_t i = 0; i < count; i++) { + sensor[i]->ProcessMeasurement(); + sensor[i]->MeasureRequest(); + } + } + + void Show(bool json) + { + for (int32_t i = 0; i < count; i++) { + if (sensor[i]->isValid()) { + char name[7]; + snprintf_P(name, sizeof(name), PSTR("%s%c%X"), D_EZO_NAME, IndexSeparator(), i + 1); + + if (count == 1) { + name[sizeof(D_EZO_NAME) - 1] = 0; + } + + sensor[i]->Show(json, name); + } + } + } + +private: + void DetectRequest(void) + { + const uint8_t EZOInfoCmd[2] = {'i', 0}; + alive = 0; + + + uint16_t shift = 1; + for (uint8_t i = EZO_ADDR_0; shift; i++) { + if (!I2cActive(i)) { + + Wire.beginTransmission(i); + Wire.write(EZOInfoCmd, sizeof(EZOInfoCmd)); + + int c = Wire.endTransmission(); + + if (c == 0) { + alive |= shift; + } + } + shift <<= 1; + } + } + + void ProcessDetection(void) + { + + for (uint8_t addr = EZO_ADDR_0; addr < EZO_ADDR_0 + EZO_ADDR_n; addr++) { + if (alive & 1) { + char data[D_EZO_MAX_BUF]; + Wire.requestFrom(addr, sizeof(data)); + char code = Wire.read(); + + if (code == 1) { + uint32_t i; + + for (i = 0; Wire.available() > 0; i++) { + char c = Wire.read(); + + + data[i] = (c == ',') ? 0 : c; + } + + + if (i >= 3) { + for (uint32_t j = 0; j < EZO_ADDR_n; j++) { + if (strcasecmp_P(&data[3], EZOSupport[j]) == 0) { + data[0] = 'E'; + data[1] = 'Z'; + data[2] = 'O'; + I2cSetActiveFound(addr, data); + + + switch (j + EZO_ADDR_0) { +#ifdef USE_EZOORP + CREATE_EZO_CLASS(ORP) +#endif +#ifdef USE_EZOPH + CREATE_EZO_CLASS(PH) +#endif +#ifdef USE_EZOEC + CREATE_EZO_CLASS(EC) +#endif +#ifdef USE_EZORTD + CREATE_EZO_CLASS(RTD) +#endif +#ifdef USE_EZOCO2 + CREATE_EZO_CLASS(CO2) +#endif +#ifdef USE_EZOHUM + CREATE_EZO_CLASS(HUM) +#endif + } + + count++; + } + } + } + } + } + + alive >>= 1; + } + } + + uint32_t next = 2; + int8_t count = -2; + + + uint16_t alive; + EZOStruct *sensor[EZO_ADDR_n]; +} EZOManager; + + + + + +bool Xsns78(uint8_t function) +{ + if (!I2cEnabled(XI2C_55)) { + return false; + } + + switch (function) { + case FUNC_COMMAND_SENSOR: + EZOManager.Command(); + break; + + case FUNC_EVERY_SECOND: + EZOManager.EverySecond(); + break; + + case FUNC_JSON_APPEND: + EZOManager.Show(1); + break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + EZOManager.Show(0); + break; +#endif + } + + return false; +} + +#endif +#endif +# 1 "/workspace/Tasmota/tasmota/xsns_interface.ino" +# 20 "/workspace/Tasmota/tasmota/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) +{ + if (0 == xsns_present) { + xsns_index = 0; + return false; + } + + 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; + + DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); + +#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; +} +# 1 "/workspace/Tasmota/tasmota/xx2c_interface.ino" +# 20 "/workspace/Tasmota/tasmota/xx2c_interface.ino" +#ifdef USE_I2C + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kI2cList[] PROGMEM = { +#else +const uint8_t kI2cList[] = { +#endif + +#ifdef XI2C_01 + XI2C_01, +#endif + +#ifdef XI2C_02 + XI2C_02, +#endif + +#ifdef XI2C_03 + XI2C_03, +#endif + +#ifdef XI2C_04 + XI2C_04, +#endif + +#ifdef XI2C_05 + XI2C_05, +#endif + +#ifdef XI2C_06 + XI2C_06, +#endif + +#ifdef XI2C_07 + XI2C_07, +#endif + +#ifdef XI2C_08 + XI2C_08, +#endif + +#ifdef XI2C_09 + XI2C_09, +#endif + +#ifdef XI2C_10 + XI2C_10, +#endif + +#ifdef XI2C_11 + XI2C_11, +#endif + +#ifdef XI2C_12 + XI2C_12, +#endif + +#ifdef XI2C_13 + XI2C_13, +#endif + +#ifdef XI2C_14 + XI2C_14, +#endif + +#ifdef XI2C_15 + XI2C_15, +#endif + +#ifdef XI2C_16 + XI2C_16, +#endif + +#ifdef XI2C_17 + XI2C_17, +#endif + +#ifdef XI2C_18 + XI2C_18, +#endif + +#ifdef XI2C_19 + XI2C_19, +#endif + +#ifdef XI2C_20 + XI2C_20, +#endif + +#ifdef XI2C_21 + XI2C_21, +#endif + +#ifdef XI2C_22 + XI2C_22, +#endif + +#ifdef XI2C_23 + XI2C_23, +#endif + +#ifdef XI2C_24 + XI2C_24, +#endif + +#ifdef XI2C_25 + XI2C_25, +#endif + +#ifdef XI2C_26 + XI2C_26, +#endif + +#ifdef XI2C_27 + XI2C_27, +#endif + +#ifdef XI2C_28 + XI2C_28, +#endif + +#ifdef XI2C_29 + XI2C_29, +#endif + +#ifdef XI2C_30 + XI2C_30, +#endif + +#ifdef XI2C_31 + XI2C_31, +#endif + +#ifdef XI2C_32 + XI2C_32, +#endif + +#ifdef XI2C_33 + XI2C_33, +#endif + +#ifdef XI2C_34 + XI2C_34, +#endif + +#ifdef XI2C_35 + XI2C_35, +#endif + +#ifdef XI2C_36 + XI2C_36, +#endif + +#ifdef XI2C_37 + XI2C_37, +#endif + +#ifdef XI2C_38 + XI2C_38, +#endif + +#ifdef XI2C_39 + XI2C_39, +#endif + +#ifdef XI2C_40 + XI2C_40, +#endif + +#ifdef XI2C_41 + XI2C_41, +#endif + +#ifdef XI2C_42 + XI2C_42, +#endif + +#ifdef XI2C_43 + XI2C_43, +#endif + +#ifdef XI2C_44 + XI2C_44, +#endif + +#ifdef XI2C_45 + XI2C_45, +#endif + +#ifdef XI2C_46 + XI2C_46, +#endif + +#ifdef XI2C_47 + XI2C_47, +#endif + +#ifdef XI2C_48 + XI2C_48, +#endif + +#ifdef XI2C_49 + XI2C_49, +#endif + +#ifdef XI2C_50 + XI2C_50, +#endif + +#ifdef XI2C_51 + XI2C_51, +#endif + +#ifdef XI2C_52 + XI2C_52, +#endif + +#ifdef XI2C_53 + XI2C_53, +#endif + +#ifdef XI2C_54 + XI2C_54, +#endif + +#ifdef XI2C_55 + XI2C_55, +#endif + +#ifdef XI2C_56 + XI2C_56, +#endif + +#ifdef XI2C_57 + XI2C_57, +#endif + +#ifdef XI2C_58 + XI2C_58, +#endif + +#ifdef XI2C_59 + XI2C_59, +#endif + +#ifdef XI2C_60 + XI2C_60, +#endif + +#ifdef XI2C_61 + XI2C_61, +#endif + +#ifdef XI2C_62 + XI2C_62, +#endif + +#ifdef XI2C_63 + XI2C_63, +#endif + +#ifdef XI2C_64 + XI2C_64, +#endif + +#ifdef XI2C_65 + XI2C_65, +#endif + +#ifdef XI2C_66 + XI2C_66, +#endif + +#ifdef XI2C_67 + XI2C_67, +#endif + +#ifdef XI2C_68 + XI2C_68, +#endif + +#ifdef XI2C_69 + XI2C_69, +#endif + +#ifdef XI2C_70 + XI2C_70, +#endif + +#ifdef XI2C_71 + XI2C_71, +#endif + +#ifdef XI2C_72 + XI2C_72, +#endif + +#ifdef XI2C_73 + XI2C_73, +#endif + +#ifdef XI2C_74 + XI2C_74, +#endif + +#ifdef XI2C_75 + XI2C_75, +#endif + +#ifdef XI2C_76 + XI2C_76, +#endif + +#ifdef XI2C_77 + XI2C_77, +#endif + +#ifdef XI2C_78 + XI2C_78, +#endif + +#ifdef XI2C_79 + XI2C_79, +#endif + +#ifdef XI2C_80 + XI2C_80, +#endif + +#ifdef XI2C_81 + XI2C_81, +#endif + +#ifdef XI2C_82 + XI2C_82, +#endif + +#ifdef XI2C_83 + XI2C_83, +#endif + +#ifdef XI2C_84 + XI2C_84, +#endif + +#ifdef XI2C_85 + XI2C_85, +#endif + +#ifdef XI2C_86 + XI2C_86, +#endif + +#ifdef XI2C_87 + XI2C_87, +#endif + +#ifdef XI2C_88 + XI2C_88, +#endif + +#ifdef XI2C_89 + XI2C_89, +#endif + +#ifdef XI2C_90 + XI2C_90, +#endif + +#ifdef XI2C_91 + XI2C_91, +#endif + +#ifdef XI2C_92 + XI2C_92, +#endif + +#ifdef XI2C_93 + XI2C_93, +#endif + +#ifdef XI2C_94 + XI2C_94, +#endif + +#ifdef XI2C_95 + XI2C_95, +#endif + +#ifdef XI2C_96 + XI2C_96 +#endif +}; + + + +bool I2cEnabled(uint32_t i2c_index) +{ + return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); +} + +void I2cDriverState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kI2cList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); +#else + uint32_t i2c_driver_id = kI2cList[i]; +#endif + bool disabled = false; + if (i2c_driver_id < MAX_I2C_DRIVERS) { + disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); + } + ResponseAppend_P(PSTR("\"")); +} + +#endif \ No newline at end of file From db0fb54bc5d3c2ae01329ec7df53c561bb526779 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 26 Oct 2020 14:07:08 +0100 Subject: [PATCH 34/38] Expose the devicetype on mDNS Add txt field to tell the network this is a tasmota device. --- tasmota/support_network.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/support_network.ino b/tasmota/support_network.ino index da6512acb..ed4df6705 100644 --- a/tasmota/support_network.ino +++ b/tasmota/support_network.ino @@ -72,6 +72,7 @@ void MdnsAddServiceHttp(void) { if (1 == Mdns.begun) { Mdns.begun = 2; MDNS.addService("http", "tcp", WEB_PORT); + MDNS.addServiceTxt("http", "tcp", "devicetype", "tasmota"); } } From 4af598fa3323bed05cd8d0747659b642503336c6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 26 Oct 2020 14:36:38 +0100 Subject: [PATCH 35/38] missing lib/ --- platformio.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index 728bcafaf..84970115a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -84,13 +84,13 @@ extra_scripts = ${scripts_defaults.extra_scripts} lib_ldf_mode = chain+ shared_libdeps_dir = lib lib_extra_dirs = - lib_basic - lib_i2c - lib_display - lib_ssl - lib_audio - lib_rf - lib_div + lib/lib_basic + lib/lib_i2c + lib/lib_display + lib/lib_ssl + lib/lib_audio + lib/lib_rf + lib/lib_div [scripts_defaults] extra_scripts = pio/strip-floats.py From 3e784f2bcc2ba5aa8bb8373024d3843a04fce4a4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 26 Oct 2020 15:10:56 +0100 Subject: [PATCH 36/38] Delete tasmota.ino.cpp --- tasmota/tasmota.ino.cpp | 115375 ------------------------------------- 1 file changed, 115375 deletions(-) delete mode 100644 tasmota/tasmota.ino.cpp diff --git a/tasmota/tasmota.ino.cpp b/tasmota/tasmota.ino.cpp deleted file mode 100644 index b3dc46cc3..000000000 --- a/tasmota/tasmota.ino.cpp +++ /dev/null @@ -1,115375 +0,0 @@ -# 1 "/tmp/tmpjvshbmyn" -#include -# 1 "/workspace/Tasmota/tasmota/tasmota.ino" -# 37 "/workspace/Tasmota/tasmota/tasmota.ino" -#include -#include "tasmota_compat.h" -#include "tasmota_version.h" -#include "tasmota.h" -#include "my_user_config.h" -#ifdef USE_TLS - #include -#endif -#include "tasmota_globals.h" -#include "i18n.h" -#include "tasmota_template.h" - - -#include -#include -#include -#include -#include -#ifdef USE_ARDUINO_OTA - #include - #ifndef USE_DISCOVERY - #define USE_DISCOVERY - #endif -#endif -#ifdef USE_DISCOVERY - #include -#endif - - #include - -#ifdef USE_SPI - #include -#endif - - -#include "settings.h" - - - - - -WiFiUDP PortUdp; - -unsigned long feature_drv1; -unsigned long feature_drv2; -unsigned long feature_sns1; -unsigned long feature_sns2; -unsigned long feature5; -unsigned long feature6; -unsigned long feature7; -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 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 blinks = 201; -uint32_t uptime = 0; -uint32_t loop_load_avg = 0; -uint32_t global_update = 0; -uint32_t web_log_index = 1; -uint32_t baudrate = APP_BAUDRATE; -float global_temperature_celsius = NAN; -float global_humidity = 0.0f; -float global_pressure_hpa = 0.0f; -uint16_t tele_period = 9999; -uint16_t blink_counter = 0; -uint16_t seriallog_timer = 0; -uint16_t syslog_timer = 0; -uint16_t gpio_pin[MAX_GPIO_PIN] = { 0 }; -int16_t save_data_counter; -RulesBitfield rules_flag; -uint8_t mqtt_cmnd_blocked = 0; -uint8_t mqtt_cmnd_blocked_reset = 0; -uint8_t state_250mS = 0; -uint8_t latching_relay_pulse = 0; -uint8_t ssleep; -uint8_t blinkspeed = 1; -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_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 masterlog_level = 0; -uint8_t seriallog_level; -uint8_t syslog_level; -uint8_t my_module_type; -uint8_t last_source = 0; -uint8_t shutters_present = 0; -uint8_t prepped_loglevel = 0; - -bool serial_local = false; -bool serial_buffer_overrun = 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 is_8285 = false; -bool skip_light_fade; -bool restart_halt = false; -myio my_module; -StateBitfield global_state; -char my_version[33]; -char my_image[33]; -char my_hostname[33]; -char mqtt_client[TOPSZ]; -char mqtt_topic[TOPSZ]; -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 -void setup(void); -void BacklogLoop(void); -void SleepDelay(uint32_t mseconds); -void loop(void); -uint16_t SendMail(char *buffer); -void xsend_message_txt(char *msg); -void attach_File(char *path); -void attach_Array(char *aname); -uint16_t SendMail(char *buffer); -void attach_Array(char *aname); -void send_message_txt(char *txt); -uint32_t GetRtcSettingsCrc(void); -void RtcSettingsSave(void); -void RtcSettingsLoad(void); -bool RtcSettingsValid(void); -uint32_t GetRtcRebootCrc(void); -void RtcRebootSave(void); -void RtcRebootReset(void); -void RtcRebootLoad(void); -bool RtcRebootValid(void); -void SetFlashModeDout(void); -bool VersionCompatible(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); -void UpdateQuickPowerCycle(bool update); -uint32_t GetSettingsTextLen(void); -bool SettingsUpdateFinished(void); -bool SettingsUpdateText(uint32_t index, const char* replace_me); -char* SettingsText(uint32_t index); -void UpdateBackwardCompatibility(void); -uint32_t GetSettingsAddress(void); -void SettingsSave(uint8_t rotate); -void SettingsLoad(void); -void EspErase(uint32_t start_sector, uint32_t end_sector); -void SettingsErase(uint8_t type); -void SettingsSdkErase(void); -void SettingsDefault(void); -void SettingsDefaultSet1(void); -void SettingsDefaultSet2(void); -void SettingsResetStd(void); -void SettingsResetDst(void); -void SettingsDefaultWebColor(void); -void SettingsEnableAllI2cDrivers(void); -void SettingsDelta(void); -void OsWatchTicker(void); -void OsWatchInit(void); -void OsWatchLoop(void); -bool OsWatchBlockedLoop(void); -uint32_t ResetReason(void); -String GetResetReason(void); -String GetBinary8(uint8_t value, size_t count); -size_t strchrspn(const char *str1, int character); -uint32_t ChrCount(const char *str, const char *delim); -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* RemoveControlCharacter(char* p); -char* ReplaceCommaWithDot(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); -void SetShortcutDefault(void); -uint8_t Shortcut(void); -bool ValidIpAddress(const char* str); -bool ParseIp(uint32_t* addr, const char* str); -uint32_t ParseParameters(uint32_t count, uint32_t *params); -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); -void GetEspHardwareType(void); -String GetDeviceHardware(void); -float ConvertTemp(float c); -float ConvertTempToCelsius(float c); -char TempUnit(void); -float ConvertHumidity(float h); -float CalcTempHumToDew(float t, float h); -float ConvertPressure(float p); -String PressureUnit(void); -float ConvertSpeed(float s); -String SpeedUnit(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); -String GetSerialConfig(void); -void SetSerialBegin(void); -void SetSerialConfig(uint32_t serial_config); -void SetSerialBaudrate(uint32_t ubaudrate); -void SetSerial(uint32_t ubaudrate, uint32_t serial_config); -void ClaimSerial(void); -void SerialSendRaw(char *codes); -void SerialSendDecimal(char *values); -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 ResponseAppendTHD(float f_temperature, float f_humidity); -int ResponseJsonEnd(void); -int ResponseJsonEndEnd(void); -uint16_t GpioConvert(uint8_t gpio); -uint16_t Adc0Convert(uint8_t adc0); -void TemplateConvert(uint8_t template8[], uint16_t template16[]); -void ConvertGpios(void); -uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index); -bool PinUsed(uint32_t gpio, uint32_t index); -uint32_t GetPin(uint32_t lpin); -void SetPin(uint32_t lpin, uint32_t gpio); -void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state); -uint8_t ModuleNr(void); -bool ValidTemplateModule(uint32_t index); -bool ValidModule(uint32_t index); -bool ValidTemplate(const char *search); -String AnyModuleName(uint32_t index); -String ModuleName(void); -void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option); -void ModuleGpios(myio *gp); -gpio_flag ModuleFlag(void); -void ModuleDefault(uint32_t module); -void SetModuleType(void); -bool FlashPin(uint32_t pin); -uint32_t ValidPin(uint32_t pin, uint32_t gpio); -bool ValidGPIO(uint32_t pin, uint32_t gpio); -bool GetUsedInModule(uint32_t val, uint16_t *arr); -bool JsonTemplate(char* dataBuf); -void TemplateJson(void); -inline int32_t TimeDifference(uint32_t prev, uint32_t next); -int32_t TimePassedSince(uint32_t timestamp); -bool TimeReached(uint32_t timer); -void SetNextTimeInterval(unsigned long& timer, const unsigned long step); -int32_t TimePassedSinceUsec(uint32_t timestamp); -bool TimeReachedUsec(uint32_t timer); -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); -void I2cSetActiveFound(uint32_t addr, const char *types); -bool I2cActive(uint32_t addr); -bool I2cSetDevice(uint32_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 PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...); -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(const char *sensor, uint32_t misses); -void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size); -String Decompress(const char * compressed, size_t uncompressed_size); -uint32_t HwRandom(void); -void ButtonPullupFlag(uint8 button_bit); -void ButtonInvertFlag(uint8 button_bit); -void ButtonTouchFlag(uint8 button_bit); -void ButtonInit(void); -uint8_t ButtonSerial(uint8_t serial_in_byte); -void ButtonHandler(void); -void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold); -void ButtonLoop(void); -void ResponseCmndNumber(int value); -void ResponseCmndFloat(float value, uint32_t decimals); -void ResponseCmndIdxNumber(int value); -void ResponseCmndChar_P(const char* value); -void ResponseCmndChar(const char* value); -void ResponseCmndStateText(uint32_t value); -void ResponseCmndDone(void); -void ResponseCmndIdxChar(const char* value); -void ResponseCmndAll(uint32_t text_index, uint32_t count); -void ExecuteCommand(const char *cmnd, uint32_t source); -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len); -void CmndBacklog(void); -void CmndDelay(void); -void CmndPower(void); -void CmndStatus(void); -void CmndState(void); -void CmndTempOffset(void); -void CmndHumOffset(void); -void CmndGlobalTemp(void); -void CmndGlobalHum(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 CmndSpeedUnit(void); -void CmndModule(void); -void CmndModules(void); -void CmndGpio(void); -void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines); -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 CmndSerialConfig(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 CmndWifi(void); -void CmndDevicename(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 CmndLedPwmOff(void); -void CmndLedPwmOn(void); -void CmndLedPwmMode(void); -void CmndWifiPower(void); -void CmndI2cScan(void); -void CmndI2cDriver(void); -void CmndDevGroupName(void); -void CmndDevGroupSend(void); -void CmndDevGroupShare(void); -void CmndDevGroupStatus(void); -void CmndSensor(void); -void CmndDriver(void); -void CmndCpuFrequency(void); -void CmndTouchCal(void); -void CmndTouchThres(void); -void CmndTouchNum(void); -void resetPins(); -void HwWdtDisable(void); -void HwWdtEnable(void); -void WdtDisable(void); -void WdtEnable(void); -void CmndCrash(void); -void CmndWDT(void); -void CmndBlockedLoop(void); -void CrashDumpClear(void); -bool CrashFlag(void); -void CrashDump(void); -bool DeviceGroupItemShared(bool incoming, uint8_t item); -void DeviceGroupsInit(void); -void DeviceGroupsStart(); -void DeviceGroupsStop(); -void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received); -bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...); -void ProcessDeviceGroupMessage(uint8_t * message, int message_length); -void DeviceGroupStatus(uint8_t device_group_index); -void DeviceGroupsLoop(void); -void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff); -void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff); -uint32_t eeprom_init(uint32_t size); -uint32_t eeprom_init(uint32_t size); -void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff); -void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff); -uint32_t eeprom_init(uint32_t size); -void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf); -void eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf); -uint32_t ESP_ResetInfoReason(void); -String ESP_getResetReason(void); -uint32_t ESP_getChipId(void); -uint32_t ESP_getSketchSize(void); -uint32_t ESP_getFreeHeap(void); -uint32_t ESP_getMaxAllocHeap(void); -void ESP_Restart(void); -void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen); -void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen); -void NvmErase(const char *sNvsName); -void SettingsErase(uint8_t type); -void SettingsRead(void *data, size_t size); -void SettingsWrite(const void *pSettings, unsigned nSettingsLen); -void QPCRead(void *pSettings, unsigned nSettingsLen); -void QPCWrite(const void *pSettings, unsigned nSettingsLen); -void ZigbeeErase(void); -void ZigbeeRead(void *pSettings, unsigned nSettingsLen); -void ZigbeeWrite(const void *pSettings, unsigned nSettingsLen); -void SntpInit(); -uint32_t SntpGetCurrentTimestamp(void); -void CrashDump(void); -bool CrashFlag(void); -void CrashDumpClear(void); -void CmndCrash(void); -void CmndWDT(void); -void CmndBlockedLoop(void); -void DisableBrownout(void); -String ESP32GetResetReason(uint32_t cpu_no); -String ESP_getResetReason(void); -uint32_t ESP_ResetInfoReason(void); -uint32_t ESP_getChipId(void); -uint32_t ESP_getSketchSize(void); -uint32_t ESP_getFreeHeap(void); -uint32_t ESP_getMaxAllocHeap(void); -void ESP_Restart(void); -static bool spiflash_is_ready(void); -static void spi_write_enable(void); -bool EsptoolEraseSector(uint32_t sector); -void EsptoolErase(uint32_t start_sector, uint32_t end_sector); -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); -float ModulusRangef(float f, float a, float b); -float Polynomialf(const float *factors, uint32_t degree, float x); -static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len); -static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); -void createBitmapFileHeader(uint32_t height, uint32_t width, uint8_t *fileHeader); -void createBitmapInfoHeader(uint32_t height, uint32_t width, uint8_t *infoHeader ); -void StartMdns(void); -void MqttDiscoverServer(void); -void MdnsAddServiceHttp(void); -void MdnsUpdate(void); -char* NetworkHostname(void); -IPAddress NetworkAddress(void); -String NetworkMacAddress(void); -bool RotaryButtonPressed(uint32_t button_index); -void ICACHE_RAM_ATTR RotaryIsrArgMiDesk(void *arg); -void ICACHE_RAM_ATTR RotaryIsrArg(void *arg); -void RotaryInit(void); -void RotaryHandler(void); -uint32_t UtcTime(void); -uint32_t LocalTime(void); -uint32_t Midnight(void); -bool MidnightNow(void); -bool IsDst(void); -String GetBuildDateAndTime(void); -String GetMinuteTime(uint32_t minutes); -String GetTimeZone(void); -String GetDuration(uint32_t time); -String GetDT(uint32_t time); -String GetDateAndTime(uint8_t time_type); -uint32_t UpTime(void); -uint32_t MinutesUptime(void); -String GetUptime(void); -uint32_t MinutesPastMidnight(void); -uint32_t RtcMillis(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); -bool equalsSBuffer(const class SBuffer * buf1, const class SBuffer * buf2); -String GetStatistics(void); -String GetStatistics(void); -void SwitchPullupFlag(uint16 switch_bit); -void SwitchSetVirtual(uint32_t index, uint8_t state); -uint8_t SwitchGetVirtual(uint32_t index); -uint8_t SwitchLastState(uint32_t index); -bool SwitchState(uint32_t index); -void SwitchProbe(void); -void SwitchInit(void); -void SwitchHandler(uint8_t mode); -void SwitchLoop(void); -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* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic); -char* GetFallbackTopic_P(char *stopic, 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 SetPowerOnState(void); -void UpdateLedPowerAll(); -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); -void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperature, float f_humidity); -bool MqttShowSensor(void); -void MqttPublishSensor(void); -void PerformEverySecond(void); -void Every100mSeconds(void); -void Every250mSeconds(void); -void ArduinoOTAInit(void); -void ArduinoOtaLoop(void); -void SerialInput(void); -void ResetPwm(void); -void GpioInit(void); -bool UdpDisconnect(void); -bool UdpConnect(void); -void PollUdp(void); -int WifiGetRssiAsQuality(int rssi); -bool WifiConfigCounter(void); -void WifiConfig(uint8_t type); -void WifiSetMode(WiFiMode_t wifi_mode); -void WiFiSetSleepMode(void); -void WifiBegin(uint8_t flag, uint8_t channel); -void WifiBeginAfterScan(void); -uint16_t WifiLinkCount(void); -String WifiDowntime(void); -void WifiSetState(uint8_t state); -bool WifiCheckIPv6(void); -String WifiGetIPv6(void); -bool WifiCheckIPAddrStatus(void); -void WifiCheckIp(void); -void WifiCheck(uint8_t param); -int WifiState(void); -String WifiGetOutputPower(void); -void WifiSetOutputPower(void); -void WifiConnect(void); -void EspRestart(void); -void stationKeepAliveNow(void); -void wifiKeepAlive(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 HttpHeaderCors(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); -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 WSContentSend_THD(const char *types, float f_temperature, float f_humidity); -void WSContentEnd(void); -void WSContentStop(void); -void WebRestart(uint32_t type); -void HandleWifiLogin(void); -void WebSliderColdWarm(void); -void HandleRoot(void); -bool HandleRootStatusRefresh(void); -int32_t IsShutterWebButton(uint32_t idx); -void HandleConfiguration(void); -void WSContentSendNiceLists(uint32_t option); -void WSContentSendAdcNiceList(uint32_t option); -void HandleTemplateConfiguration(void); -uint16_t WebGetGpioArg(uint32_t i); -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); -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); -void CmndWebButton(void); -void CmndCors(void); -bool Xdrv01(uint8_t function); -bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); -void MakeValidMqtt(uint32_t option, char* str); -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 MqttDumpData(char* topic, char* data, uint32_t data_len); -void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len); -void MqttRetryCounter(uint8_t value); -void MqttSubscribe(const char *topic); -void MqttUnsubscribe(const char *topic); -void MqttPublishLogging(const char *mxtime); -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 MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained); -void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic); -void MqttPublishTeleSensor(void); -void MqttPublishPowerState(uint32_t device); -void MqttPublishAllPowerState(void); -void MqttPublishPowerBlinkState(uint32_t device); -uint16_t MqttConnectCount(void); -void MqttDisconnected(int state); -void MqttConnected(void); -void MqttReconnect(void); -void MqttCheck(void); -bool KeyTopicActive(uint32_t key); -void CmndMqttFingerprint(void); -void CmndMqttUser(void); -void CmndMqttPassword(void); -void CmndMqttlog(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); -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); -void EnergyCommandCalResponse(uint32_t nvalue); -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 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 mat3x3(const float *mat33, const float *vec3, float *res3); -uint16_t change8to10(uint8_t v); -uint8_t change10to8(uint16_t v); -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr); -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr); -uint16_t ledGamma10_10(uint16_t v); -uint16_t ledGamma10(uint8_t v); -uint8_t ledGamma(uint8_t v); -void LightPwmOffset(uint32_t offset); -bool LightModuleInit(void); -void LightCalcPWMRange(void); -void LightInit(void); -void LightUpdateColorMapping(void); -uint8_t LightGetDimmer(uint8_t dimmer); -void LightSetDimmer(uint8_t dimmer); -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri); -void LightGetXY(float *X, float *Y); -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); -uint8_t LightGetBri(uint8_t device); -void LightSetBri(uint8_t device, uint8_t bri); -void LightColorOffset(int32_t offset); -bool LightColorTempOffset(int32_t offset); -void LightSetColorTemp(uint16_t ct); -uint16_t LightGetColorTemp(void); -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); -void LightPowerOn(void); -void ResponseLightState(uint8_t append); -void LightSetPaletteEntry(void); -void LightCycleColor(int8_t direction); -void LightSetPower(void); -void LightAnimate(void); -bool isChannelGammaCorrected(uint32_t channel); -bool isChannelCT(uint32_t channel); -uint16_t fadeGamma(uint32_t channel, uint16_t v); -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg); -bool LightApplyFade(void); -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power); -void LightSetOutputs(const uint16_t *cur_col_10); -void calcGammaMultiChannels(uint16_t cur_col_10[5]); -void calcGammaBulbs(uint16_t cur_col_10[5]); -void LightSendDeviceGroupStatus(bool status); -void LightHandleDevGroupItem(void); -bool LightColorEntry(char *buffer, uint32_t buffer_length); -void CmndSupportColor(void); -void CmndColor(void); -void CmndWhite(void); -void CmndChannel(void); -void CmndHsbColor(void); -void CmndScheme(void); -void CmndWakeup(void); -void CmndColorTemperature(void); -void LightDimmerOffset(uint32_t index, int32_t offset); -void CmndDimmer(void); -void CmndDimmerRange(void); -void CmndLedTable(void); -void CmndRgbwwTable(void); -void CmndFade(void); -void CmndSpeed(void); -void CmndWakeupDuration(void); -void CmndPalette(void); -void CmndSequenceOffset(void); -void CmndUndocA(void); -bool Xdrv04(uint8_t function); -void IrSendInit(void); -void IrReceiveUpdateThreshold(void); -void IrReceiveInit(void); -void IrReceiveCheck(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); -void IrReceiveInit(void); -String sendIRJsonState(const struct decode_results &results); -void IrReceiveCheck(void); -String listSupportedProtocols(bool hvac); -bool strToBool(class JsonParserToken token, bool def); -uint32_t IrRemoteCmndIrHvacJson(void); -void CmndIrHvac(void); -uint32_t IrRemoteCmndIrSendJson(void); -uint32_t IrRemoteSendGC(char ** pp, uint32_t count, uint32_t repeat); -uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat); -uint32_t IrRemoteParseRawCompact(char * str, uint16_t * arr, size_t arr_len); -uint32_t IrRemoteSendRawStandard(char ** pp, uint32_t count, uint32_t repeat); -uint16_t parsqeFreq(char * str); -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); -void DomoticzUpdateFanState(void); -void MqttPublishDomoticzPowerState(uint8_t device); -void DomoticzUpdatePowerState(uint8_t device); -void DomoticzMqttUpdate(void); -void DomoticzMqttSubscribe(void); -bool DomoticzMqttData(void); -void DomoticzSendSwitch(uint32_t type, uint32_t index, uint32_t state); -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); -void DomoticzSendData(uint32_t sensor_idx, uint32_t idx, char *data); -void DomoticzSensor(uint8_t idx, char *data); -uint8_t DomoticzHumidityState(float h); -void DomoticzSensor(uint8_t idx, uint32_t value); -void DomoticzTempHumPressureSensor(float temp, float hum, float 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 CmndDomoticzSend(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); -uint32_t JulianDate(const struct TIME_T &now); -float InPi(float x); -float TimeFormula(float *DK, uint32_t Tdays); -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); -inline bool IsRuleUncompressed(uint32_t idx); -inline bool IsRuleEmpty(uint32_t idx); -size_t GetRuleLen(uint32_t idx); -size_t GetRuleLenStorage(uint32_t idx); -void GetRule_decompress(String &rule, const char *rule_head); -String GetRule(uint32_t idx); -int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, size_t out_len); -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all_rules); -int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); -void RulesVarReplace(String &commands, const String &sfind, const String &replace); -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(void); -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 Script_ticker1_end(void); -void Script_ticker2_end(void); -void Script_ticker3_end(void); -void Script_ticker4_end(void); -void SaveFile(const char *name, const uint8_t *buf, uint32_t len); -void LoadFile(const char *name, uint8_t *buf, uint32_t len); -void f2char(float num, uint32_t dprec, uint32_t lzeros, char *nbuff); -void ScriptEverySecond(void); -void RulesTeleperiod(void); -int16_t Init_Scripter(void); -uint32_t get_fsinfo(uint32_t sel); -void form1000(uint32_t number, char *dp, char sc); -void Restart_globvars(void); -void Script_Stop_UDP(void); -void Script_Init_UDP(); -void Script_PollUdp(void); -void script_udp_sendvar(char *vname,float *fp,char *sp); -void ws2812_set_array(float *array ,uint32_t len, uint32_t offset); -float median_array(float *array, uint16_t len); -float Get_MFVal(uint8_t index, int16_t bind); -void Set_MFVal(uint8_t index, uint16_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); -void ICACHE_RAM_ATTR MP_Timer(void); -uint32_t MeasurePulseTime(int32_t in); -uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind); -uint16_t GetStack(void); -uint16_t GetStack(void); -void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_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); -void esp32_beep(int32_t freq ,uint32_t len); -int16_t Run_Scripter(const char *type, int8_t tlen, char *js); -int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo); -void ScripterEvery100ms(void); -void Scripter_save_pvars(void); -void script_upload_start(void); -void ScriptExecuteUploadSuccess(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 SaveScript(void); -void ScriptSaveSettings(void); -void SaveScriptEnd(void); -void Script_HueStatus(String *response, uint16_t hue_devs); -void Script_Check_Hue(String *response); -void Script_Handle_Hue(String *path); -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 ScriptGetSDCard(void); -void SendFile(char *fname); -void ScriptFullWebpage(void); -void Script_Check_HTML_Setvars(void); -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); -void ScriptWebShow(char mc); -void ScriptJsonAppend(void); -bool RulesProcessEvent(char *json_event); -void script_task1(void *arg); -void script_task2(void *arg); -uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio); -void script_task1(void *arg); -void script_task2(void *arg); -uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio); -uint32_t call2https(const char *host, const char *path); -void cpy2lf(char *dst, uint32_t dstlen, char *src); -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(void); -void KnxSensor(uint8_t sensor_type, float value); -void HandleKNXConfiguration(void); -void KNX_Save_Settings(void); -void CmndKnxTxCmnd(void); -void CmndKnxTxVal(void); -void CmndKnxTxScene(void); -void CmndKnxEnabled(void); -void CmndKnxEnhanced(void); -void CmndKnxPa(void); -void CmndKnxGa(void); -void CmndKnxCb(void); -bool Xdrv11(uint8_t function); -void HassDiscoveryRelays(struct HASS &Hass); -void NewHAssDiscovery(void); -void TryResponseAppend_P(const char *format, ...); -void HAssAnnounceRelayLight(void); -void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold, uint8_t single, uint8_t trg_start, uint8_t trg_end); -void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint8_t toggle, uint8_t pir); -void HAssAnnounceSwitches(void); -void HAssAnnounceButtons(void); -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, bool nested, const char* SubKey); -void HAssAnnounceSensors(void); -void HAssAnnounceShutters(void); -void HAssAnnounceDeviceInfoAndStatusSensor(void); -void HAssPublishStatus(void); -void HAssDiscovery(void); -void HAssDiscover(void); -void HAssAnyKey(void); -bool HAssMqttLWT(void); -void HassLwtSubscribe(bool hasslwt); -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); -uint32_t 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 Touch_Init(TwoWire &i2c); -uint32_t Touch_Status(uint32_t sel); -void Touch_MQTT(uint8_t index, const char *cp); -void Touch_RDW_BUTT(uint32_t count, uint32_t pwr); -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); -bool IsModuleTuya(void); -bool AsModuleTuyaMS(void); -bool IsTuyaFanCtrl(void); -bool TuyaModeSet(void); -uint8_t TuyaFanSpeeds(void); -uint8_t TuyaFanState(void); -void CmndTuyaSend(void); -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); -void TuyaSendEnum(uint8_t id, uint32_t value); -void TuyaSendString(uint8_t id, char data[]); -bool TuyaSetPower(void); -bool TuyaSetChannels(void); -void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx); -void TuyaRequestState(uint8_t state_type); -void TuyaResetWifi(void); -void TuyaProcessStatePacket(void); -void TuyaLowPowerModePacketProcess(void); -void TuyaHandleProductInfoPacket(void); -void TuyaSendLowPowerSuccessIfNeeded(void); -void TuyaNormalPowerModePacketProcess(void); -bool TuyaModuleSelected(void); -void TuyaInit(void); -void TuyaSerialInput(void); -bool TuyaButtonPressed(void); -uint8_t TuyaGetTuyaWifiState(void); -void TuyaSetWifiLed(void); -void TuyaSetTime(void); -bool Xnrg32(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 PS16DZSerialSend(const char *tx_buffer); -void PS16DZSerialSendOk(void); -void PS16DZSerialSendUpdateCommand(void); -void PS16DZSerialInput(void); -bool PS16DZSerialSendUpdateCommandIfRequired(void); -void PS16DZInit(void); -bool PS16DZModuleSelected(void); -bool Xdrv19(uint8_t function); -String HueBridgeId(void); -String HueSerialnumber(void); -String HueUuid(void); -void HueRespondToMSearch(void); -String GetHueDeviceId(uint16_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); -bool HueActive(uint8_t device); -void HueLightStatus2(uint8_t device, String *response); -inline uint32_t findEchoGeneration(void); -void HueGlobalConfig(String *path); -void HueAuthentication(String *path); -void CheckHue(String * response, bool &appending); -void HueLightsCommand(uint8_t device, uint32_t device_id, String &response); -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 LogUpnpWithClient(const char *msg); -void HandleUpnpEvent(void); -void HandleUpnpService(void); -void HandleUpnpMetaService(void); -void HandleUpnpSetupWemo(void); -bool Xdrv21(uint8_t function); -bool IsModuleIfan(void); -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); -String getZDPStatusMessage(uint8_t status); -String getEmberStatus(uint8_t status); -String getZigbeeStatusMessage(uint8_t status); -int strcmp_PP(const char *p1, const char *p2); -uint16_t Z_GetLastDevice(void); -uint16_t Z_GetLastGroup(void); -uint16_t Z_GetLastCluster(void); -uint8_t Z_GetLastEndpoint(void); -void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response); -void HueLightStatus2Zigbee(uint16_t shortaddr, String *response); -void ZigbeeHueStatus(String * response, uint16_t shortaddr); -void ZigbeeCheckHue(String * response, bool &appending); -void ZigbeeHueGroups(String * lights); -void ZigbeeHuePower(uint16_t shortaddr, bool power); -void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer); -void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct); -void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y); -void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat); -void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response); -class SBuffer hibernateDevice(const struct Z_Device &device); -class SBuffer hibernateDevices(void); -void hydrateDevices(const SBuffer &buf); -void loadZigbeeDevices(void); -void saveZigbeeDevices(void); -void eraseZigbeeDevices(void); -uint8_t Z_getDatatypeLen(uint8_t t); -bool Z_isDiscreteDataType(uint8_t t); -uint16_t CxToCluster(uint8_t cx); -uint8_t ClusterToCx(uint16_t cluster); -int8_t CmToMultiplier(uint8_t cm); -const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t attr_id, - uint8_t *attr_type, int8_t *multiplier); -uint8_t toPercentageCR2032(uint32_t voltage); -int32_t encodeSingleAttribute(class SBuffer &buf, double val_d, const char *val_str, uint8_t attrtype); -void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -bool Z_parseAttributeKey(class Z_attribute & attr); -void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -inline bool isXYZ(char c); -inline int8_t hexValue(char c); -void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz); -void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload); -bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf); -const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd); -inline char hexDigit(uint32_t h); -String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z); -uint32_t ZigbeeAliasOrNumber(const char *state_text); -void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h); -void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, int8_t zb_txradio_dbm); -uint8_t ZigbeeGetInstructionSize(uint8_t instr); -void ZigbeeGotoLabel(uint8_t label); -void ZigbeeStateMachine_Run(void); -int32_t ZigbeeProcessInput(class SBuffer &buf); -uint8_t ZNP_RSSI2Lqi(int8_t rssi); -int32_t EZ_RSTACK(uint8_t reset_code); -int32_t EZ_ERROR(uint8_t error_code); -int32_t EZ_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf); -int32_t EZ_GetEUI64(int32_t res, class SBuffer &buf); -int32_t EZ_GetNodeId(int32_t res, class SBuffer &buf); -int32_t EZ_NetworkParameters(int32_t res, class SBuffer &buf); -int32_t EZ_CheckKeyNWK(int32_t res, class SBuffer &buf); -int32_t EZ_RouteError(int32_t res, const class SBuffer &buf); -int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf); -void Z_PermitJoinDisable(void); -int32_t EZ_MessageSent(int32_t res, const class SBuffer &buf); -int32_t Z_EZSPGetEUI64(int32_t res, class SBuffer &buf); -int32_t Z_EZSPGetNodeId(int32_t res, class SBuffer &buf); -int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf); -int32_t ZNP_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); -int32_t ZNP_CheckNVWrite(int32_t res, class SBuffer &buf); -int32_t ZNP_Reboot(int32_t res, class SBuffer &buf); -int32_t ZNP_ReceiveCheckVersion(int32_t res, class SBuffer &buf); -int32_t EZ_ReceiveCheckVersion(int32_t res, class SBuffer &buf); -int32_t EZ_Set_ResetConfig(uint8_t value); -int32_t EZ_GotoIfResetConfig(uint8_t value); -int32_t Z_SwitchDeviceType(int32_t res, class SBuffer &buf); -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); -int32_t ZNP_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf); -int32_t ZNP_ReceiveNodeDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf); -int32_t Z_ClusterToCxBinding(uint16_t cluster); -void Z_AutoBindDefer(uint16_t shortaddr, uint8_t endpoint, const SBuffer &buf, - size_t in_index, size_t in_len, size_t out_index, size_t out_len); -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf); -int32_t ZNP_DataConfirm(int32_t res, const class SBuffer &buf); -int32_t ZNP_ReceiveStateChange(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); -int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf); -int32_t Z_BindRsp(int32_t res, const class SBuffer &buf); -int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf); -int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf); -int32_t EZ_ParentAnnceRsp(int32_t res, const class SBuffer &buf, bool rsp); -void Z_SendIEEEAddrReq(uint16_t shortaddr); -void Z_SendActiveEpReq(uint16_t shortaddr); -void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -void Z_SendDeviceInfoRequest(uint16_t shortaddr); -void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf); -void Z_IncomingMessage(class ZCLFrame &zcl_received); -void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len); -int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf); -int32_t EZ_Reset_Device(uint8_t value); -int32_t EZ_Recv_Default(int32_t res, const class SBuffer &buf); -void Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); -int32_t ZNP_Reset_Device(uint8_t value); -int32_t ZNP_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); -int32_t ZNP_Recv_Default(int32_t res, const class SBuffer &buf); -int32_t Z_Load_Devices(uint8_t value); -void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms); -int32_t Z_Query_Bulbs(uint8_t value); -int32_t Z_State_Ready(uint8_t value); -bool Z_LedStatusSet(bool onoff); -void ZigbeeInputLoop(void); -void ZigbeeInitSerial(void); -void ZigbeeZNPFlush(void); -void ZigbeeZNPSend(const uint8_t *msg, size_t len); -void CmndZbZNPSendOrReceive(bool send); -void CmndZbZNPReceive(void); -void CmndZbZNPSend(void); -void ZigbeeEZSPSend_Out(uint8_t out_byte); -void ZigbeeEZSPSendRaw(const uint8_t *msg, size_t len, bool send_cancel); -void ZigbeeEZSPSendCmd(const uint8_t *msg, size_t len); -void ZigbeeEZSPSendDATA_frm(bool send_cancel, uint8_t to_frm, uint8_t from_ack); -void ZigbeeEZSPSendDATA(const uint8_t *msg, size_t len); -int32_t ZigbeeProcessInputEZSP(class SBuffer &buf); -void EZSP_HandleAck(uint8_t new_ack); -int32_t ZigbeeProcessInputRaw(class SBuffer &buf); -void CmndZbEZSPSendOrReceive(bool send); -void CmndZbEZSPReceive(void); -void CmndZbEZSPSend(void); -void ZigbeeOutputLoop(void); -uint32_t ZigbeeUploadFlashStart(void); -uint32_t ZigbeeUploadAvailable(void); -char ZigbeeUploadFlashRead(void); -void XModemOutputByte(uint8_t out_char); -char XModemWaitACK(void); -bool XModemSendPacket(uint32_t packet_no); -void ZigbeeUploadSetSoftwareBootloader(); -void ZigbeeUploadSetBootloader(uint8_t state); -bool ZigbeeUploadBootloaderPrompt(void); -bool ZigbeeUploadXmodem(void); -bool ZigbeeUploadOtaReady(void); -bool ZigbeeUploadFinish(void); -uint8_t ZigbeeUploadInit(void); -bool ZigbeeUploadWriteBuffer(uint8_t *buf, size_t size); -void ZigbeeUploadDone(void); -void HandleZigbeeXfer(void); -void ZigbeeInit(void); -void CmndZbReset(void); -void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf, - uint16_t cluster, uint8_t cmd, const char *param); -void ZbApplyMultiplier(double &val_d, int8_t multiplier); -bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr, uint8_t transid); -bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok); -void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZigbeeZCLSendMessage & packet); -void ZbSendSend(class JsonParserToken val_cmd, uint16_t device, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint16_t manuf); -void ZbSendRead(JsonParserToken val_attr, ZigbeeZCLSendMessage & packet); -void CmndZbSend(void); -void ZbBindUnbind(bool unbind); -void CmndZbBind(void); -void CmndZbUnbind(void); -void CmndZbBindState(void); -void CmndZbProbe(void); -void CmndZbProbeOrPing(boolean probe); -void CmndZbPing(void); -void CmndZbName(void); -void CmndZbModelId(void); -void CmndZbLight(void); -void CmndZbForget(void); -void CmndZbSave(void); -void CmndZbRestore(void); -void CmndZbPermitJoin(void); -void CmndZbEZSPListen(void); -void ZigbeeGlowPermitJoinLight(void); -void CmndZbStatus(void); -bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root); -void CmndZbData(void); -void CmndZbConfig(void); -void ZigbeeShow(bool json); -bool Xdrv23(uint8_t function); -void BuzzerSet(uint8_t state); -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode); -void BuzzerSetStateToLed(uint32_t state); -void BuzzerBeep(uint32_t count); -void BuzzerEnabledBeep(uint32_t count, uint32_t duration); -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 AriluxRfInterrupt(void); -void AriluxRfHandler(void); -void AriluxRfInit(void); -void AriluxRfDisable(void); -bool Xdrv26(uint8_t function); -void ShutterLogPos(uint32_t i); -void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source); -void ShutterUpdateVelocity(uint8_t i); -void ShutterRtc50mS(void); -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index); -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index); -void ShutterInit(void); -void ShutterReportPosition(bool always, uint32_t index); -void ShutterLimitRealAndTargetPositions(uint32_t i); -void ShutterCalculateAccelerator(uint8_t i); -void ShutterDecellerateForStop(uint8_t i); -void ShutterPowerOff(uint8_t i); -void ShutterUpdatePosition(void); -bool ShutterState(uint32_t device); -void ShutterAllowPreStartProcedure(uint8_t i); -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos); -int32_t ShutterCalculatePosition(uint32_t i); -void ShutterRelayChanged(void); -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index); -void ShutterButtonHandler(void); -void ShutterSetPosition(uint32_t device, uint32_t position); -void ShutterToggle(bool dir); -void CmndShutterOpen(void); -void CmndShutterStopOpen(void); -void CmndShutterClose(void); -void CmndShutterStopClose(void); -void CmndShutterToggle(void); -void CmndShutterToggleDir(void); -void CmndShutterStopToggle(void); -void CmndShutterStopToggleDir(void); -void CmndShutterStop(void); -void CmndShutterIncDec(void); -void CmndShutterPosition(void); -void CmndShutterStopPosition(void); -void CmndShutterOpenTime(void); -void CmndShutterCloseTime(void); -void CmndShutterMotorDelay(void); -void CmndShutterMode(void); -void CmndShutterRelay(void); -void CmndShutterButton(void); -void CmndShutterSetHalfway(void); -void CmndShutterFrequency(void); -void CmndShutterSetClose(void); -void CmndShutterSetOpen(void); -void CmndShutterPwmRange(void); -void CmndShutterCalibration(void); -void ShutterOptionsSetHelper(uint16_t option); -void CmndShutterInvert(void); -void CmndShutterLock(void); -void CmndShutterEnableEndStopTime(void); -void CmndShutterInvertWebButtons(void); -bool Xdrv27(uint8_t function); -void Pcf8574SwitchRelay(void); -void Pcf8574Init(void); -void HandlePcf8574(void); -void Pcf8574SaveSettings(void); -bool Xdrv28(uint8_t function); -bool DeepSleepEnabled(void); -void DeepSleepReInit(void); -void DeepSleepPrepare(void); -void DeepSleepStart(void); -void DeepSleepEverySecond(void); -void CmndDeepsleepTime(void); -bool Xdrv29(uint8_t function); -uint8_t crc8(const uint8_t *p, uint8_t len); -void ExsSendCmd(uint8_t cmd, uint8_t value); -void ExsSetPower(uint8_t device, uint8_t power); -void ExsSetBri(uint8_t device, uint8_t bri); -void ExsSyncState(uint8_t device); -bool ExsSyncState(); -void ExsDebugState(); -void ExsPacketProcess(void); -bool ExsModuleSelected(void); -bool ExsSetChannels(void); -bool ExsSetPower(void); -void EsxMcuStart(void); -void ExsInit(void); -void ExsSerialInput(void); -void CmndExsDimm(void); -void CmndExsDimmTbl(void); -void CmndExsDimmVal(void); -void CmndExsDimms(void); -void CmndExsChLock(void); -void CmndExsState(void); -bool Xdrv30(uint8_t function); -uint32_t TasmotaClient_FlashStart(void); -uint8_t TasmotaClient_UpdateInit(void); -void TasmotaClient_Reset(void); -uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout); -uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count); -uint8_t TasmotaClient_execCmd(uint8_t cmd); -uint8_t TasmotaClient_execParam(uint8_t cmd, uint8_t* params, int count); -uint8_t TasmotaClient_exitProgMode(void); -uint8_t TasmotaClient_SetupFlash(void); -uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo); -void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data); -void TasmotaClient_Flash(void); -void TasmotaClient_SetFlagFlashing(bool value); -bool TasmotaClient_GetFlagFlashing(void); -void TasmotaClient_WriteBuffer(uint8_t *buf, size_t size); -void TasmotaClient_Init(void); -bool TasmotaClient_Available(void); -void TasmotaClient_Show(void); -void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param); -void CmndClientReset(void); -void CmndClientSend(void); -void TasmotaClient_ProcessIn(void); -bool Xdrv31(uint8_t function); -void HotPlugInit(void); -void HotPlugEverySecond(void); -void CmndHotPlugTime(void); -bool Xdrv32(uint8_t function); -bool NRF24initRadio(); -bool NRF24Detect(void); -bool Xdrv33(uint8_t function); -void WMotorV1Detect(void); -void WMotorV1Reset(void); -void WMotorV1SetFrequency(uint32_t freq); -void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val); -bool WMotorV1Command(void); -bool Xdrv34(uint8_t function); -void PWMModulePreInit(void); -void PWMDimmerSetBrightnessLeds(int32_t bri); -void PWMDimmerSetPoweredOffLed(void); -void PWMDimmerSetPower(void); -void PWMDimmerHandleDevGroupItem(void); -void PWMDimmerHandleButton(uint32_t button_index, bool pressed); -void CmndBriPreset(void); -void CmndPWMDimmerPWMs(void); -bool Xdrv35(uint8_t function); -void CmdSet(void); -void GenerateDeviceCryptKey(); -void CmdSendButton(void); -void SendBit(byte bitToSend); -void CmndSendRaw(void); -void enterrx(); -void entertx(); -void SendSyncPreamble(int l); -void CreateKeeloqPacket(); -void KeeloqInit(); -bool Xdrv36(uint8_t function); -void SonoffD1Received(void); -bool SonoffD1SerialInput(void); -void SonoffD1Send(); -bool SonoffD1SendPower(void); -bool SonoffD1SendDimmer(void); -bool SonoffD1ModuleSelected(void); -bool Xdrv37(uint8_t function); -void PingResponsePoll(void); -void CmndPing(void); -bool Xdrv38(uint8_t function); -void ThermostatInit(uint8_t ctr_output); -bool ThermostatMinuteCounter(uint8_t ctr_output); -inline bool ThermostatSwitchIdValid(uint8_t switchId); -inline bool ThermostatRelayIdValid(uint8_t relayId); -uint8_t ThermostatInputStatus(uint8_t input_switch); -uint8_t ThermostatOutputStatus(uint8_t output_switch); -int16_t ThermostatCelsiusToFahrenheit(const int32_t deg, uint8_t conv_type); -int16_t ThermostatFahrenheitToCelsius(const int32_t deg, uint8_t conv_type); -void ThermostatSignalPreProcessingSlow(uint8_t ctr_output); -void ThermostatSignalPostProcessingSlow(uint8_t ctr_output); -void ThermostatSignalProcessingFast(uint8_t ctr_output); -void ThermostatCtrState(uint8_t ctr_output); -void ThermostatHybridCtrPhase(uint8_t ctr_output); -bool ThermostatStateAutoToManual(uint8_t ctr_output); -bool ThermostatStateManualToAuto(uint8_t ctr_output); -void ThermostatEmergencyShutdown(uint8_t ctr_output); -void ThermostatState(uint8_t ctr_output); -void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command); -void ThermostatCalculatePI(uint8_t ctr_output); -void ThermostatWorkAutomaticPI(uint8_t ctr_output); -void ThermostatWorkAutomaticRampUp(uint8_t ctr_output); -void ThermostatPeakDetectorInit(uint8_t ctr_output); -void ThermostatPeakDetector(uint8_t ctr_output); -void ThermostatAutotuneParamCalc(uint8_t ctr_output); -void ThermostatWorkAutomaticPIAutotune(uint8_t ctr_output); -void ThermostatCtrWork(uint8_t ctr_output); -void ThermostatWork(uint8_t ctr_output); -void ThermostatDiagnostics(uint8_t ctr_output); -void ThermostatController(uint8_t ctr_output); -bool ThermostatTimerArm(uint8_t ctr_output, int16_t tempVal); -void ThermostatTimerDisarm(uint8_t ctr_output); -void ThermostatVirtualSwitch(uint8_t ctr_output); -void ThermostatVirtualSwitchCtrState(uint8_t ctr_output); -void ThermostatDebug(uint8_t ctr_output); -void ThermostatGetLocalSensor(uint8_t ctr_output); -void CmndThermostatModeSet(void); -void CmndClimateModeSet(void); -void CmndTempFrostProtectSet(void); -void CmndControllerModeSet(void); -void CmndInputSwitchSet(void); -void CmndInputSwitchUse(void); -void CmndSensorInputSet(void); -void CmndOutputRelaySet(void); -void CmndTimeAllowRampupSet(void); -void CmndTempFormatSet(void); -void CmndTempMeasuredSet(void); -void CmndTempTargetSet(void); -void CmndTempMeasuredGrdRead(void); -void CmndStateEmergencySet(void); -void CmndTimeManualToAutoSet(void); -void CmndPropBandSet(void); -void CmndTimeResetSet(void); -void CmndTimePiProportRead(void); -void CmndTimePiIntegrRead(void); -void CmndTimePiCycleSet(void); -void CmndTempAntiWindupResetSet(void); -void CmndTempHystSet(void); -void CmndPerfLevelAutotune(void); -void CmndTimeMaxActionSet(void); -void CmndTimeMinActionSet(void); -void CmndTimeSensLostSet(void); -void CmndTimeMinTurnoffActionSet(void); -void CmndTempRupDeltInSet(void); -void CmndTempRupDeltOutSet(void); -void CmndTimeRampupMaxSet(void); -void CmndTimeRampupCycleSet(void); -void CmndTempRampupPiAccErrSet(void); -void CmndDiagnosticModeSet(void); -void CmndCtrDutyCycleRead(void); -void CmndEnableOutputSet(void); -bool Xdrv39(uint8_t function); -bool TelegramInit(void); -String TelegramConnectToTelegram(String command); -void TelegramGetUpdates(uint32_t offset); -bool TelegramSendMessage(uint32_t chat_id, String text); -String TelegramExecuteCommand(const char *svalue); -void TelegramLoop(void); -void CmndTmState(void); -void CmndTmPoll(void); -void CmndTmToken(void); -void CmndTmChatId(void); -void CmndTmSend(void); -bool Xdrv40(uint8_t function); -void TCPLoop(void); -void TCPInit(void); -void CmndTCPStart(void); -void CmndTCPBaudrate(void); -bool Xdrv41(uint8_t function); -void I2S_Init(void); -void mp3_task(void *arg); -void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str); -void StatusCallback(void *cbData, int code, const char *string); -void Webradio(const char *url); -void mp3_task2(void *arg); -void StopPlaying(); -void Cmd_WebRadio(void); -void I2S_WR_Show(void); -void Play_mp3(const char *path); -void mp3_delete(void); -void Say(char *text); -void Cmd_Play(void); -void Cmd_Gain(void); -void Cmd_Say(void); -void Cmd_Time(void); -bool Xdrv42(uint8_t function); -void MLX90640UpdateGUI(void); -void MLX90640HandleWebGuiResponse(void); -void MLX90640HandleWebGui(void); -bool MLX90640Cmd(void); -void MLX90640init(); -void MLX90640every100msec(); -void MLX90640Show(uint8_t json); -bool Xdrv43(uint8_t function); -static uint8_t -miel_hvac_write(struct miel_hvac_softc *sc, const uint8_t *bytes, size_t len); -static void -miel_hvac_send(struct miel_hvac_softc *sc, uint8_t type, - const void *data, size_t len); -static void -miel_hvac_request(struct miel_hvac_softc *sc, uint8_t type); -static void -miel_hvac_init_update(struct miel_hvac_msg_update *update); -static bool -miel_hvac_set_power(struct miel_hvac_softc *sc); -static void -miel_hvac_respond_unsupported(void); -static void -miel_hvac_cmnd_setfanspeed(void); -static void -miel_hvac_cmnd_setmode(void); -static void -miel_hvac_cmnd_sethamode(void); -static void -miel_hvac_cmnd_settemp(void); -static void -miel_hvac_cmnd_setvane(void); -static void -miel_hvac_cmnd_setwidevane(void); -static void -miel_hvac_cmnd_remotetemp(void); -static void -miel_hvac_cmnd_request(void); -static void -miel_hvac_log_bytes(struct miel_hvac_softc *sc, const char *name, - const void *buf, size_t len); -static void -miel_hvac_input_connected(struct miel_hvac_softc *sc, - const void *buf, size_t len); -static void -miel_hvac_publish_settings(struct miel_hvac_softc *sc); -static void -miel_hvac_input_settings(struct miel_hvac_softc *sc, - const struct miel_hvac_data *d); -static void -miel_hvac_data_response(struct miel_hvac_softc *sc, - const struct miel_hvac_data *d); -static void -miel_hvac_input_sensor(struct miel_hvac_softc *sc, struct miel_hvac_data *dst, - const struct miel_hvac_data *src); -static void -miel_hvac_input_data(struct miel_hvac_softc *sc, - const void *buf, size_t len); -static void -miel_hvac_input_updated(struct miel_hvac_softc *sc, - const void *buf, size_t len); -static void -miel_hvac_pre_init(void); -static void -miel_hvac_loop(struct miel_hvac_softc *sc); -static void -miel_hvac_sensor(struct miel_hvac_softc *sc); -static void -miel_hvac_connect(struct miel_hvac_softc *sc); -static void -miel_hvac_tick(struct miel_hvac_softc *sc); -bool Xdrv44(uint8_t function); -bool WcPinUsed(void); -uint32_t WcSetup(int32_t fsiz); -int32_t WcSetOptions(uint32_t sel, int32_t value); -uint32_t WcGetWidth(void); -uint32_t WcGetHeight(void); -uint32_t WcSetMotionDetect(int32_t value); -void WcDetectMotion(void); -void fd_init(void); -uint32_t WcSetFaceDetect(int32_t value); -uint32_t WcGetPicstore(int32_t num, uint8_t **buff); -uint32_t WcGetFrame(int32_t bnum); -void HandleImage(void); -void HandleImageBasic(void); -void HandleWebcamMjpeg(void); -void HandleWebcamMjpegTask(void); -void HandleWebcamRoot(void); -uint32_t WcSetStreamserver(uint32_t flag); -void WcStreamControl(); -void WcLoop(void); -void WcPicSetup(void); -void WcShowStream(void); -void WcInit(void); -void CmndWebcam(void); -void CmndWebcamStream(void); -void CmndWebcamResolution(void); -void CmndWebcamMirror(void); -void CmndWebcamFlip(void); -void CmndWebcamSaturation(void); -void CmndWebcamBrightness(void); -void CmndWebcamContrast(void); -void CmndWebcamInit(void); -bool Xdrv81(uint8_t function); -void EthernetEvent(WiFiEvent_t event); -void EthernetInit(void); -IPAddress EthernetLocalIP(void); -char* EthernetHostname(void); -String EthernetMacAddress(void); -void CmndEthernet(void); -void CmndEthAddress(void); -void CmndEthType(void); -void CmndEthClockMode(void); -bool Xdrv82(uint8_t function); -void TTGO_Init(void); -void initPower(void); -static uint8_t axpWriteBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len); -static uint8_t axpReadBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len); -void TTGO_GetADC(void); -void TTGO_WebShow(uint32_t json); -void TTGO_audio_power(bool power); -void TTGO_LightSleep(void); -void TTGO_Sleep(int32_t stime); -void TTGO_loop(uint32_t flg); -bool TTGO_doubleclick(void); -bool TTGO_button(void); -bool Xdrv83(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 SetFlashMode(uint8_t mode); -void CmndHelp(void); -void CmndRtcDump(void); -void CmndCfgDump(void); -void CmndCfgPeek(void); -void CmndCfgPoke(void); -void CmndCfgXor(void); -void CmndException(void); -void CmndCpuCheck(void); -void CmndSerBufSize(void); -void CmndFreemem(void); -void CmndSetSensor(void); -void CmndFlashMode(void); -uint32_t DebugSwap32(uint32_t x); -void CmndFlashDump(void); -void CmndI2cWrite(void); -void CmndI2cRead(void); -void CmndI2cStretch(void); -void CmndI2cClock(void); -bool Xdrv99(uint8_t function); -void XsnsDriverState(void); -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(); -void LcdCenter(uint8_t row, char* txt); -bool LcdPrintLog(void); -void LcdTime(void); -void LcdRefresh(void); -bool Xdsp01(uint8_t function); -void SSD1306InitDriver(void); -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); -bool Ili9341Header(void); -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(); -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_RotConvert(int16_t *x, int16_t *y); -void ILI9488_CheckTouch(void); -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_RotConvert(int16_t *x, int16_t *y); -void RA8876_CheckTouch(void); -bool Xdsp10(uint8_t function); -void SevensegWrite(void); -void SevensegClear(void); -void SevensegInitMode(void); -void SevensegInit(uint8_t mode); -void SevensegInitDriver(void); -void SevensegOnOff(void); -void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void SevensegTime(boolean time_24); -void SevensegRefresh(void); -bool Xdsp11(uint8_t function); -void ST7789_InitDriver(); -void ST7789_RotConvert(int16_t *x, int16_t *y); -void ST7789_CheckTouch(); -bool Xdsp12(uint8_t function); -uint8_t XdspPresent(void); -bool XdspCall(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 Ws2812Clear(void); -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); -char* Ws2812GetColor(uint32_t led, char* scolor); -void Ws2812ForceSuspend (void); -void Ws2812ForceUpdate (void); -bool Ws2812SetChannels(void); -void Ws2812ShowScheme(void); -void Ws2812ModuleSelected(void); -void CmndLed(void); -void CmndPixels(void); -void CmndRotation(void); -void CmndWidth(void); -bool Xlgt01(uint8_t function); -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); -bool My92x1SetChannels(void); -void My92x1ModuleSelected(void); -bool Xlgt02(uint8_t function); -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); -void SM16716_Init(void); -bool Sm16716SetChannels(void); -void Sm16716ModuleSelected(void); -bool Xlgt03(uint8_t function); -void Sm2135SetLow(uint8_t pin); -void Sm2135SetHigh(uint8_t pin); -bool Sm2135Init(void); -bool Sm2135Write(uint8_t value); -bool Sm2135Start(uint8_t addr); -void Sm2135Stop(void); -bool Sm2135SetChannels(void); -void Sm2135ModuleSelected(void); -bool Xlgt04(uint8_t function); -void SnfL1Send(const char *buffer); -void SnfL1SerialSendOk(void); -bool SnfL1SerialInput(void); -bool SnfL1SetChannels(void); -void SnfL1ModuleSelected(void); -bool Xlgt05(uint8_t function); -bool ElectriqMoodLSetChannels(void); -void ElectriqMoodLModuleSelected(void); -bool Xlgt06(uint8_t function); -bool XlgtCall(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); -void CseSerialInput(void); -void CseEverySecond(void); -void CseSnsInit(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 PzemEvery250ms(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); -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); -void DDSU666Every250ms(void); -void Ddsu666SnsInit(void); -void Ddsu666DrvInit(void); -bool Xnrg11(uint8_t function); -bool solaxX1_RS485ReceiveReady(void); -void solaxX1_RS485Send(uint16_t msgLen); -uint8_t solaxX1_RS485Receive(uint8_t *value); -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); -void solaxX1_SendInverterAddress(void); -void solaxX1_QueryLiveData(void); -uint8_t solaxX1_ParseErrorCode(uint32_t code); -void solaxX1250MSecond(void); -void solaxX1SnsInit(void); -void solaxX1DrvInit(void); -void solaxX1Show(bool json); -bool Xnrg12(uint8_t function); -void FifLEEvery250ms(void); -void FifLESnsInit(void); -void FifLEDrvInit(void); -void FifLEReset(void); -void FifLEShow(bool json); -bool Xnrg13(uint8_t function); -void Bl0940Received(void); -void Bl0940SerialInput(void); -void Bl0940EverySecond(void); -void Bl0940SnsInit(void); -void Bl0940DrvInit(void); -bool Bl0940Command(void); -void Bl0940Show(bool json); -bool Xnrg14(uint8_t function); -void ADPSCallback(uint8_t phase); -void DataCallback(struct _ValueList * me, uint8_t flags); -void ResponseAppendTInfo(char sep); -void NewFrameCallback(struct _ValueList * me); -void TInfoDrvInit(void); -void TInfoInit(void); -void TInfoEvery250ms(void); -void TInfoShow(bool json); -bool Xnrg15(uint8_t function); -void IEM3000Every250ms(void); -void Iem3000SnsInit(void); -void Iem3000DrvInit(void); -bool Xnrg16(uint8_t function); -void WE517Every250ms(void); -void We517SnsInit(void); -void We517DrvInit(void); -bool Xnrg17(uint8_t function); -bool XnrgCall(uint8_t function); -void ICACHE_RAM_ATTR CounterIsrArg(void *arg); -void CounterInterruptDisable(bool state); -bool CounterPinState(void); -void CounterInit(void); -void CounterEverySecond(void); -void CounterSaveState(void); -void CounterShow(bool json); -void SyncACDimmer(void); -void CmndCounter(void); -void CmndCounterType(void); -void CmndCounterDebounce(void); -void CmndCounterDebounceLow(void); -void CmndCounterDebounceHigh(void); -bool Xsns01(uint8_t function); -bool adcAttachPin(uint8_t pin); -void AdcSaveSettings(uint32_t idx); -void AdcGetSettings(uint32_t idx); -void AdcInitParams(uint8_t idx); -void AdcAttach(uint8_t pin, uint8_t type); -void AdcInit(void); -uint16_t AdcRead(uint32_t pin, uint32_t factor); -void AdcEvery250ms(void); -uint8_t AdcGetButton(uint32_t pin); -uint16_t AdcGetLux(uint32_t idx); -uint16_t AdcGetRange(uint32_t idx); -void AdcGetCurrentPower(uint8_t idx, uint8_t factor); -void AdcEverySecond(void); -void AdcShowContinuation(bool *jsonflg); -void AdcShow(bool json); -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 OneWire1ReadBit(void); -uint8_t OneWire2ReadBit(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); -void Ds18x20Convert(void); -bool Ds18x20Read(uint8_t sensor, float &t); -void Ds18x20Name(uint8_t sensor); -void Ds18x20EverySecond(void); -void Ds18x20Show(bool json); -bool Xsns05(uint8_t function); -bool DhtWaitState(uint32_t sensor, uint32_t level); -bool DhtRead(uint32_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 BmpShow(bool json); -void BMP_EnterSleep(void); -bool Xsns09(uint8_t function); -uint8_t Bh1750Resolution(uint32_t sensor_index); -bool Bh1750SetResolution(uint32_t sensor_index); -bool Bh1750SetMTreg(uint32_t sensor_index); -bool Bh1750Read(uint32_t sensor_index); -void Bh1750Detect(void); -void Bh1750EverySecond(void); -void CmndBh1750Resolution(void); -void CmndBh1750MTime(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 Ads1115Label(char* label, uint32_t maxsize, uint8_t address); -void AdsEvery250ms(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); -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); -size_t PmsSendCmd(uint8_t command_id); -bool PmsReadData(void); -bool PmsCommandSensor(void); -void PmsSecond(void); -void PmsInit(void); -void PmsShow(bool json); -bool Xsns18(uint8_t function); -void MGSInit(void); -void 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); -void Sgp30Update(void); -void Sgp30Show(bool json); -bool Xsns21(uint8_t function); -uint8_t Sr04TModeDetect(void); -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third); -uint16_t Sr04TMode3Distance(); -uint16_t Sr04TMode2Distance(void); -void Sr04TReading(void); -void Sr04Show(bool json); -bool Xsns22(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); -bool Si1145Read(void); -void Si1145Detect(void); -void Si1145Update(void); -void Si1145Show(bool json); -bool Xsns24(uint8_t function); -void LM75ADDetect(void); -float LM75ADGetTemp(void); -void LM75ADShow(bool json); -bool Xsns26(uint8_t function); -void calculateColorTemperature(void); -uint8_t getProxIntLowThresh(void); -inline void setProxIntLowThresh(uint8_t threshold); -uint8_t getProxIntHighThresh(void); -inline void setProxIntHighThresh(uint8_t threshold); -uint8_t getLEDDrive(void); -void setLEDDrive(uint8_t drive); -uint8_t getProximityGain(void); -void setProximityGain(uint8_t drive); -uint8_t getAmbientLightGain(); -void setAmbientLightGain(uint8_t drive); -uint8_t getLEDBoost(void); -void setLEDBoost(uint8_t boost); -uint8_t getProxGainCompEnable(void); -void setProxGainCompEnable(uint8_t enable); -uint8_t getProxPhotoMask(void); -void setProxPhotoMask(uint8_t mask); -uint8_t getGestureEnterThresh(void); -inline void setGestureEnterThresh(uint8_t threshold); -uint8_t getGestureExitThresh(void); -inline void setGestureExitThresh(uint8_t threshold); -uint8_t getGestureGain(void); -void setGestureGain(uint8_t gain); -uint8_t getGestureLEDDrive(void); -void setGestureLEDDrive(uint8_t drive); -uint8_t getGestureWaitTime(void); -void setGestureWaitTime(uint8_t time); -void getLightIntLowThreshold(uint16_t &threshold); -void setLightIntLowThreshold(uint16_t threshold); -void getLightIntHighThreshold(uint16_t &threshold); -void setLightIntHighThreshold(uint16_t threshold); -void getProximityIntLowThreshold(uint8_t &threshold); -void setProximityIntLowThreshold(uint8_t threshold); -void getProximityIntHighThreshold(uint8_t &threshold); -void setProximityIntHighThreshold(uint8_t threshold); -uint8_t getAmbientLightIntEnable(void); -void setAmbientLightIntEnable(uint8_t enable); -uint8_t getProximityIntEnable(void); -void setProximityIntEnable(uint8_t enable); -uint8_t getGestureIntEnable(void); -void setGestureIntEnable(uint8_t enable); -void clearAmbientLightInt(void); -void clearProximityInt(void); -uint8_t getGestureMode(void); -void setGestureMode(uint8_t mode); -bool APDS9960_init(void); -inline 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); -inline void enablePower(void); -inline void disablePower(void); -inline void readAllColorAndProximityData(void); -void APDS9960_adjustATime(void); -void resetGestureParameters(void); -bool processGestureData(void); -bool decodeGesture(void); -void handleGesture(void); -void APDS9960_loop(void); -void 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_Interrupt_Counter_Report(void); -void MCP230xx_Interrupt_Retain_Report(void); -void MCP230xx_SwitchRelay(); -bool Xsns29(uint8_t function); -void Mpr121Init(struct mpr121 *pS, bool initial); -void Mpr121Show(struct mpr121 *pS, uint8_t function); -bool Xsns30(uint8_t function); -void CCS811Detect(void); -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); -void DS3231EverySecond(void); -bool Xsns33(uint8_t function); -bool HxIsReady(uint16_t timeout); -long HxRead(void); -void HxResetPart(void); -void HxReset(void); -void HxCalibrationStateTextJson(uint8_t msg_id); -void SetWeightDelta(); -bool HxCommand(void); -long HxWeight(void); -void HxInit(void); -void HxEvery100mSecond(void); -void HxSaveBeforeRestart(void); -void HxShow(bool json); -void HandleHxAction(void); -void HxSaveSettings(void); -void HxLogUpdates(void); -bool Xsns34(uint8_t function); -void ICACHE_RAM_ATTR TX2xStartRead(void); -bool Tx2xAvailable(void); -float atan2f(float a, float b); -void Tx2xCheckSampleCount(void); -void Tx2xResetStat(void); -void Tx2xResetStatData(void); -void Tx2xRead(void); -void Tx2xInit(void); -int32_t Tx2xNormalize(int32_t value); -void Tx2xShow(bool json); -bool Xsns35(uint8_t function); -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(); -void 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); -int32_t MAX31855_ShiftIn(uint8_t Length); -float MAX31855_GetProbeTemperature(int32_t RawData); -float MAX31855_GetReferenceTemperature(int32_t RawData); -void MAX31855_GetResult(void); -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); -void Scd30Detect(void); -void Scd30Update(void); -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); -void SPS30_Every_Second(); -void SPS30_Show(bool json); -bool SPS30_cmd(void); -bool Xsns44(byte function); -void Vl53l0Detect(void); -void Vl53l0Every_250MSecond(void); -void Vl53l0Every_Second(void); -void Vl53l0Show(boolean json); -bool Xsns45(byte function); -void MLX90614_Init(void); -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); -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg); -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr); -void ChirpReset(uint8_t addr); -void ChirpResetAll(void); -void ChirpClockSet(); -void ChirpSleep(uint8_t addr); -void ChirpSelect(uint8_t sensor); -uint8_t ChirpReadVersion(uint8_t addr); -bool ChirpSet(uint8_t addr); -bool ChirpScan(); -void ChirpDetect(void); -void ChirpServiceAllSensors(uint8_t job); -void ChirpEvery100MSecond(void); -void ChirpShow(bool json); -bool ChirpCmd(void); -bool Xsns48(uint8_t function); -void PAJ7620SelectBank(uint8_t bank); -void PAJ7620DecodeGesture(void); -void PAJ7620ReadGesture(void); -void PAJ7620Detect(void); -void PAJ7620Init(void); -void PAJ7620Loop(void); -void PAJ7620Show(bool json); -bool PAJ7620CommandSensor(void); -bool Xsns50(uint8_t function); -uint8_t RDM6300HexNibble(char chr); -void RDM6300HexStringToArray(uint8_t array[], uint8_t len, char buffer[]); -void RDM6300Init(); -void RDM6300ScanForTag(); -void RDM6300Show(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,const char *uid,const char *major,const char *minor); -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 ICACHE_RAM_ATTR SML_CounterUpd(uint8_t index); -void ICACHE_RAM_ATTR SML_CounterUpd1(void); -void ICACHE_RAM_ATTR SML_CounterUpd2(void); -void ICACHE_RAM_ATTR SML_CounterUpd3(void); -void ICACHE_RAM_ATTR SML_CounterUpd4(void); -uint32_t SML_getlinelen(char *lp); -uint32_t SML_getscriptsize(char *lp); -uint32_t SML_getscriptsize(char *lp); -bool Gpio_used(uint8_t gpiopin); -void SML_Init(void); -uint32_t SML_SetBaud(uint32_t meter, uint32_t br); -uint32_t SML_Status(uint32_t meter); -uint32_t SML_Write(uint32_t meter,char *hstr); -uint32_t SML_Read(int32_t meter,char *str, uint32_t slen); -float SML_GetVal(uint32_t index); -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); -uint8_t CalcEvenParity(uint8_t data); -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 Ina226Index); -bool Ina226TestPresence(uint8_t device); -void Ina226ResetActive(void); -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 Hih6Read(void); -void Hih6Detect(void); -void Hih6EverySecond(void); -void Hih6Show(bool json); -bool Xsns55(uint8_t function); -void HpmaSecond(void); -void HpmaInit(void); -void HpmaShow(bool json); -bool Xsns56(uint8_t function); -void Tsl2591Init(void); -bool Tsl2591Read(void); -void Tsl2591EverySecond(void); -void Tsl2591Show(bool json); -bool Xsns57(uint8_t function); -bool Dht12Read(void); -void Dht12Detect(void); -void Dht12EverySecond(void); -void Dht12Show(bool json); -bool Xsns58(uint8_t function); -uint32_t DS1624_Idx2Addr(uint32_t idx); -void DS1624_Restart(uint8_t config, uint32_t idx); -void DS1624_HotPlugUp(uint32_t idx); -void DS1624_HotPlugDown(int idx); -bool DS1624GetTemp(float *value, int idx); -void DS1624HotPlugScan(void); -void DS1624EverySecond(void); -void DS1624Show(bool json); -bool Xsns59(uint8_t function); -void UBXcalcChecksum(char* CK, size_t msgSize); -bool UBXcompareMsgHeader(const char* msgHeader); -void UBXinitCFG(void); -void UBXsendCFGLine(uint8_t _line); -void UBXTriggerTele(void); -void UBXDetect(void); -uint32_t UBXprocessGPS(); -void UBXsendHeader(void); -void UBXsendRecord(uint8_t *buf); -void UBXsendFooter(void); -void UBXsendFile(void); -void UBXSetRate(uint16_t interval); -void UBXSelectMode(uint16_t mode); -bool UBXHandlePOSLLH(); -void UBXHandleSTATUS(); -void UBXHandleTIME(); -void UBXHandleOther(void); -void UBXLoop50msec(void); -void UBXLoop(void); -void UBXShow(bool json); -bool UBXCmd(void); -bool Xsns60(uint8_t function); -void MINRFinit(void); -bool MINRFinitBLE(uint8_t _mode); -void MINRFhopChannel(); -bool MINRFreceivePacket(void); -void MINRFswapbuf(uint8_t *buf, uint8_t len); -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr); -void MINRFhandleScan(void); -void MINRFstartBeacon(uint16_t entry); -void MINRFbeaconCounter(void); -int MINRFdecryptPacket(char *_buf); -int MINRFdecryptMJYD2SPacket(char *_buf, uint8_t _light, char* _output); -void MINRFreverseMAC(uint8_t _MAC[]); -void MINRFAddKey(char* payload); -void MINRFKeyMACStringToBytes(char* _string,uint8_t _keyMAC[]); -void MINRFMACStringToBytes(char* _string, uint8_t _MAC[]); -void MINRFcomputefirstUsedPacketMode(void); -void MINRFrecalcBuffer(uint8_t *_buf, uint32_t offset); -void MINRFchangePacketModeTo(uint8_t _mode); -void MINRFpurgeFakeSensors(void); -void MINRFconfirmSensors(void); -void MINRFtriggerTele(void); -void MINRFhandleMiBeaconPacket(void); -void MINRFhandleCGD1Packet(void); -void MINRFhandleNlightPacket(void); -void MINRFhandleMJYD2SPacket(void); -void MINRFhandleLightPacket(void); -void MINRFaddLight(uint8_t _MAC[], uint8_t _type); -void MINRFhandleATCPacket(void); -void MINRF_EVERY_50_MSECOND(); -bool NRFCmd(void); -void MINRFShow(bool json); -bool Xsns61(uint8_t function); -void MI32stripColon(char* _string); -void MI32HexStringToBytes(char* _string, uint8_t* _byteArray); -void MI32_ReverseMAC(uint8_t _mac[]); -void MI32AddKey(char* payload); -int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type); -void MI32nullifyEndOfMQTT_DATA(); -void MI32triggerTele(void); -void MI32StatusInfo(); -void MI32Init(void); -void MI32StartTask(uint32_t task); -bool MI32ConnectActiveSensor(); -void MI32StartScanTask(); -void MI32ScanTask(void *pvParameters); -void MI32StartSensorTask(); -void MI32SensorTask(void *pvParameters); -bool MI32connectLYWSD03forNotification(); -void MI32StartTimeTask(); -void MI32TimeTask(void *pvParameters); -void MI32StartUnitTask(); -void MI32UnitTask(void *pvParameters); -void MI32StartBatteryTask(); -void MI32BatteryTask(void *pvParameters); -void MI32batteryRead(uint32_t _type); -void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize); -void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI); -void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI); -void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI); -void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID); -void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, uint8_t* addr); -void MI32addBeacon(uint8_t index, char* data); -void MI32showScanResults(); -void MI32readHT_LY(char *_buf); -bool MI32readBat(char *_buf); -void MI32Every50mSecond(); -void MI32EverySecond(bool restart); -bool MI32Cmd(void); -void MI32Show(bool json); -bool Xsns62(uint8_t function); -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay); -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot); -void HM10_ReverseMAC(uint8_t _mac[]); -void HM10_Reset(void); -void HM10_Discovery_Scan(void); -void HM10_Read_LYWSD03(void); -void HM10_Read_LYWSD02(void); -void HM10_Time_LYWSD02(void); -void HM10_Read_Flora(void); -void HM10_Read_CGD1(void); -void HM10_Read_MJ_HT_V1(void); -void HM10SerialInit(void); -void HM10parseMiBeacon(char * _buf, uint32_t _slot); -void HM10parseATC(char * _buf, uint32_t _slot); -char* HM10ParseResponse(char *buf, uint16_t bufsize); -void HM10readHT_LY(char *_buf); -void HM10readHT_CGD1(char *_buf); -void HM10readHT_MJ_HT_V1(char *_buf); -void HM10readTLMF(char *_buf); -bool HM10readBat(char *_buf); -bool HM10SerialHandleFeedback(); -void HM10_TaskEvery100ms(); -void HM10StatusInfo(); -void HM10EverySecond(bool restart); -bool HM10Cmd(void); -void HM10triggerTele(void); -void HM10Show(bool json); -bool Xsns62(uint8_t function); -bool AHT1XWrite(uint8_t aht1x_idx); -bool AHT1XRead(uint8_t aht1x_idx); -void AHT1XPoll(void); -unsigned char AHT1XReadStatus(uint8_t aht1x_address); -void AHT1XReset(uint8_t aht1x_address); -bool AHT1XInit(uint8_t aht1x_address); -void AHT1XDetect(void); -void AHT1XShow(bool json); -bool Xsns63(uint8_t function); -void HRXLInit(void); -void HRXLEverySecond(void); -void HRXLShow(bool json); -bool Xsns64(uint8_t function); -uint16_t HdcReadDeviceId(void); -uint16_t HdcReadManufacturerId(void); -void HdcConfig(uint16_t config); -void HdcReset(void); -int8_t HdcTransactionOpen(uint8_t addr, uint8_t reg); -int8_t HdcTransactionClose(uint8_t addr, uint8_t *reg_data, uint16_t len); -void HdcInit(void); -bool HdcTriggerRead(void); -bool HdcRead(void); -void HdcDetect(void); -void HdcEverySecond(void); -void HdcShow(bool json); -bool Xsns65(uint8_t function); -void IAQ_Init(void); -void IAQ_Read(void); -void IAQ_Show(uint8_t json); -bool Xsns66(byte function); -void ICACHE_RAM_ATTR AS3935Isr(void); -uint8_t AS3935ReadRegister(uint8_t reg, uint8_t mask, uint8_t shift); -void AS3935WriteRegister(uint8_t reg, uint8_t mask, uint8_t shift, uint8_t data); -void ICACHE_RAM_ATTR AS3935CountFreq(void); -bool AS3935AutoTuneCaps(uint8_t irqpin); -bool AS3935CalRCOResult(void); -bool AS3935CalibrateRCO(void); -void AS3935Reset(void); -void AS3935PwrDown(void); -void AS3935PwrUp(void); -uint8_t AS3935GetPwrStat(void); -uint8_t AS3935GetIRQ(void); -uint8_t AS3935TranslIrq(uint8_t irq, uint8_t distance); -uint8_t AS3935GetDistance(void); -int16_t AS3935CalcDistance(void); -uint32_t AS3935GetIntensity(void); -uint8_t AS3935GetTuneCaps(void); -void AS3935SetTuneCaps(uint8_t tune); -uint8_t AS3935GetDisturber(void); -void AS3935SetDisturber(uint8_t stat); -uint8_t AS3935GetMinLights(void); -void AS3935SetMinLights(uint8_t stat); -uint8_t AS3935TransMinLights(uint8_t min_lights); -uint8_t AS3935TranslMinLightsInt(uint8_t min_lights); -uint8_t AS3935GetNoiseFloor(void); -void AS3935SetNoiseFloor(uint8_t noise); -uint8_t AS3935GetGain(void); -void AS3935SetGain(uint8_t room); -uint8_t AS3935GetGainInt(void); -void AS3935CalcVrmsLevel(uint16_t &vrms, uint8_t &stage); -uint8_t AS3935GetSpikeRejection(void); -void AS3935SetSpikeRejection(uint8_t rej); -uint8_t AS3935GetWdth(void); -void AS3935SetWdth(uint8_t wdth); -bool AS3935AutoTune(void); -bool AS3935LowerNoiseFloor(void); -bool AS3935RaiseNoiseFloor(void); -bool AS3935SetDefault(void); -void AS3935InitSettings(void); -bool AS3935Setup(void); -bool AS3935init(void); -void AS3935Detect(void); -void AS3935EverySecond(void); -bool AS3935Cmd(void); -void AH3935Show(bool json); -bool Xsns67(uint8_t function); -void ICACHE_RAM_ATTR WindMeterUpdateSpeed(void); -void WindMeterInit(void); -void WindMeterEverySecond(void); -bool WindMeterShouldTriggerTele(); -void WindMeterResetStatData(void); -void WindMeterCheckSampleCount(void); -void WindMeterShow(bool json); -void WindMeterTriggerTele(void); -bool Xsns68Cmnd(void); -bool Xsns68(uint8_t function); -void sns_opentherm_init_boiler_status(); -void ICACHE_RAM_ATTR sns_opentherm_handleInterrupt(); -void sns_opentherm_processResponseCallback(unsigned long response, int st); -bool sns_opentherm_Init(); -void sns_opentherm_stat(bool json); -void sns_ot_start_handshake(); -void sns_ot_process_handshake(unsigned long response, int st); -void sns_opentherm_CheckSettings(void); -uint8_t sns_opentherm_parse_flag(char *flag); -uint8_t sns_opentherm_read_flags(char *data, uint32_t len); -void sns_opentherm_cmd(void); -void sns_opentherm_boiler_setpoint_cmd(void); -void sns_opentherm_hot_water_setpoint_cmd(void); -void sns_opentherm_save_settings_cmd(void); -void sns_opentherm_flags_cmd(void); -void sns_opentherm_set_central_heating_cmd(void); -bool Xsns69(uint8_t function); -unsigned long sns_opentherm_set_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); -void sns_opentherm_parse_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_slave_flags(struct OpenThermCommandT *self); -unsigned long sns_opentherm_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); -void sns_opentherm_parse_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_boiler_temperature(struct OpenThermCommandT *self); -unsigned long sns_opentherm_set_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status); -void sns_opentherm_parse_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_boiler_dhw_temperature(struct OpenThermCommandT *self); -unsigned long sns_opentherm_get_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); -void sns_opentherm_parse_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_flags(struct OpenThermCommandT *self); -unsigned long sns_opentherm_get_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); -void sns_opentherm_parse_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self); -unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *); -void sns_opentherm_parse_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_tele_generic_float(struct OpenThermCommandT *self); -void sns_opentherm_parse_dhw_setpoint(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_parse_flame_modulation(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_parse_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -unsigned long sns_opentherm_get_next_request(struct OT_BOILER_STATUS_T *boilerStatus); -void sns_opentherm_check_retry_request(); -void sns_opentherm_process_success_response(struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response); -void sns_opentherm_dump_telemetry(); -uint16_t VEML6075read16 (uint8_t reg); -void VEML6075write16 (uint8_t reg, uint16_t val); -float VEML6075calcUVA (void); -float VEML6075calcUVB (void); -float VEML6075calcUVI (void); -void VEML6075SetHD(uint8_t val); -uint8_t VEML6075ReadHD(void); -void VEML6075SetUvIt(uint8_t val); -uint8_t VEML6075GetUvIt(void); -void VEML6075Pwr(uint8_t val); -uint8_t VEML6075GetPwr(void); -void VEML6075ReadData(void); -bool VEML6075init(void); -void VEML6075Detect(void); -void VEML6075EverySecond(void); -bool VEML6075Cmd(void); -void VEML6075Show(bool json); -bool Xsns70(uint8_t function); -void VEML7700Detect(void); -uint16_t VEML7700TranslateItMs (uint8_t ittime); -uint8_t VEML7700TranslateItInt (uint16_t ittimems); -void VEML7700EverySecond(void); -void VEML7700Show(bool json); -bool VEML7700Cmd(void); -bool Xsns71(uint8_t function); -float MCP9808Read(uint8_t addr); -void MCP9808Detect(void); -void MCP9808EverySecond(void); -void MCP9808Show(bool json); -bool Xsns72(uint8_t function); -bool HP303B_Read(uint32_t hp303b_idx); -void HP303B_Detect(void); -void HP303B_EverySecond(void); -void HP303B_Show(bool json); -bool Xsns73(uint8_t function); -void LMT01_Init(void); -void ICACHE_RAM_ATTR LMT01_countPulse(void); -void LMT01_GetTemperature(void); -int LMT01_getPulses(void); -void LMT01_Show(bool Json); -bool Xsns74(uint8_t function); -void HandleMetrics(void); -bool Xsns75(uint8_t function); -void DYPInit(void); -void DYPEverySecond(void); -void DYPShow(bool json); -bool Xsns76(uint8_t function); -void Vl53l1Detect(void); -void Vl53l1Every_250MSecond(void); -void Vl53l1Every_Second(void); -void Vl53l1Show(bool json); -bool Xsns77(uint8_t function); -bool Xsns78(uint8_t function); -bool XsnsEnabled(uint32_t sns_index); -void XsnsSensorState(void); -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); -bool XsnsCall(uint8_t Function); -bool I2cEnabled(uint32_t i2c_index); -void I2cDriverState(void); -#line 191 "/workspace/Tasmota/tasmota/tasmota.ino" -void setup(void) { -#ifdef ESP32 -#ifdef DISABLE_ESP32_BROWNOUT - DisableBrownout(); -#endif -#endif - - global_state.data = 0xF; - - RtcRebootLoad(); - if (!RtcRebootValid()) { - RtcReboot.fast_reboot_count = 0; - } -#ifdef FIRMWARE_MINIMAL - RtcReboot.fast_reboot_count = 0; -#else - RtcReboot.fast_reboot_count++; -#endif - RtcRebootSave(); - - Serial.begin(baudrate); - - 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); - } - - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); - - SettingsLoad(); - SettingsDelta(); - - OsWatchInit(); - - GetFeatures(); - - if (1 == RtcReboot.fast_reboot_count) { - UpdateQuickPowerCycle(true); - XdrvCall(FUNC_SETTINGS_OVERRIDE); - } - - - 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; - ssleep = 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { - Settings.module = Settings.fallback_module; - - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("FRC: " D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - } - } - - Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); - Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP_getChipId() & 0x1FFF); - } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); - } - - GetEspHardwareType(); - GpioInit(); - - - - WifiConnect(); - - SetPowerOnState(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE), PROJECT, SettingsText(SET_DEVICENAME), my_version, my_image); -#ifdef FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); -#endif - - memcpy_P(log_data, VERSION_MARKER, 1); - - RtcInit(); - -#ifdef USE_ARDUINO_OTA - ArduinoOTAInit(); -#endif - - XdrvCall(FUNC_INIT); - XsnsCall(FUNC_INIT); -#ifdef USE_SCRIPT - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">BS",3,0); -#endif - - rules_flag.system_init = 1; -} - -void BacklogLoop(void) { - if (TimeReached(backlog_delay)) { - if (!BACKLOG_EMPTY && !backlog_mutex) { - backlog_mutex = true; - bool nodelay = false; - bool nodelay_detected = false; - String cmd; - do { -#ifdef SUPPORT_IF_STATEMENT - cmd = backlog.shift(); -#else - cmd = backlog[backlog_pointer]; - backlog[backlog_pointer] = (const char*) nullptr; - backlog_pointer++; - if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } -#endif - nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY)); - if (nodelay_detected) { nodelay = true; } - } while (!BACKLOG_EMPTY && nodelay_detected); - if (!nodelay_detected) { ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); } - if (nodelay) { backlog_delay = 0; } - backlog_mutex = false; - } - } -} - -void SleepDelay(uint32_t mseconds) { - if (mseconds) { - for (uint32_t wait = 0; wait < mseconds; wait++) { - delay(1); - if (Serial.available()) { break; } - } - } else { - delay(0); - } -} - -void loop(void) { - uint32_t my_sleep = millis(); - - XdrvCall(FUNC_LOOP); - XsnsCall(FUNC_LOOP); - - OsWatchLoop(); - - ButtonLoop(); - SwitchLoop(); -#ifdef USE_DEVICE_GROUPS - DeviceGroupsLoop(); -#endif - BacklogLoop(); - - if (TimeReached(state_50msecond)) { - SetNextTimeInterval(state_50msecond, 50); -#ifdef ROTARY_V1 - RotaryHandler(); -#endif - 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 (TimeReached(state_second)) { - SetNextTimeInterval(state_second, 1000); - PerformEverySecond(); - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); - } - - if (!serial_local) { SerialInput(); } - -#ifdef USE_ARDUINO_OTA - ArduinoOtaLoop(); -#endif - - uint32_t my_activity = millis() - my_sleep; - - if (Settings.flag3.sleep_normal) { - - SleepDelay(ssleep); - } else { - if (my_activity < (uint32_t)ssleep) { - SleepDelay((uint32_t)ssleep - my_activity); - } else { - if (global_state.network_down) { - SleepDelay(my_activity /2); - } - } - } - - if (!my_activity) { my_activity++; } - uint32_t loop_delay = ssleep; - 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 "/workspace/Tasmota/tasmota/sendemail.ino" -#ifdef USE_SENDMAIL - -#ifndef USE_ESP32MAIL - -#include "sendemail.h" -# 27 "/workspace/Tasmota/tasmota/sendemail.ino" -#ifndef SEND_MAIL_MINRAM -#define SEND_MAIL_MINRAM 12*1024 -#endif - -void script_send_email_body(void(*func)(char *)); - -#define xPSTR(a) a - -uint16_t SendMail(char *buffer) { - char *params,*oparams; - const char *mserv; - uint16_t port; - 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; - - - - 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; -} - - - -#ifdef ESP8266 -WiFiClient *g_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)) { -} -#else -WiFiClient *g_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 WiFiClientSecure()) { -} -#endif - -String SendEmail::readClient() { - delay(0); - String r = client->readStringUntil('\n'); - - r.trim(); - while (client->available()) { - delay(0); - r += client->readString(); - } - return r; -} - -bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { -bool status=false; -String buffer; - - if (!host.length()) { - return status; - } - - client->setTimeout(timeout); - -#ifdef DEBUG_EMAIL_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 - AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); -#endif - goto exit; - } - - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("220"))) { - goto exit; - } - - buffer = F("EHLO "); - buffer += client->localIP().toString(); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - 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("AUTH LOGIN"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) - { - goto exit; - } - base64 b; - buffer = b.encode(user); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) { - goto exit; - } - buffer = b.encode(passwd); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("235"))) { - goto exit; - } - } - - - buffer = F("MAIL FROM:"); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - buffer = F("RCPT TO:"); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - - buffer = F("DATA"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("354"))) { - goto exit; - } - - buffer = F("MIME-Version: 1.0\r\n"); - client->print(buffer); - buffer = F("Content-Type: Multipart/mixed; boundary=frontier\r\n"); - client->print(buffer); - - buffer = F("From: "); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = F("To: "); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - 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 - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - -#ifdef USE_SCRIPT - if (*msg=='*' && *(msg+1)==0) { - g_client=client; - script_send_email_body(xsend_message_txt); - } else { - client->println(msg); - } -#else - client->println(msg); -#endif - client->println('.'); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - buffer = F("QUIT"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - status=true; -exit: - - return status; -} - -void xsend_message_txt(char *msg) { -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),msg); -#endif -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - if (*msg=='@') { - msg++; - attach_File(msg); - } else if (*msg=='&') { - msg++; - attach_Array(msg); - } else { - g_client->print(F("--frontier\r\n")); - g_client->print(F("Content-Type: text/plain\r\n\r\n")); - g_client->println(msg); - g_client->print(F("\r\n--frontier\r\n")); - } -#else - if (*msg=='&') { - msg++; - attach_Array(msg); - } else { - g_client->print(F("--frontier\r\n")); - g_client->print(F("Content-Type: text/plain\r\n\r\n")); - g_client->println(msg); - g_client->print(F("\r\n--frontier\r\n")); - } -#endif -} - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -#include -extern FS *fsp; - -void attach_File(char *path) { - g_client->print(F("--frontier\r\n")); - g_client->print(F("Content-Type: text/plain\r\n")); - char buff[64]; - char *cp = path; - while (*cp=='/') cp++; - File file = fsp->open(path, "r"); - if (file) { - sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"), cp); - g_client->write(buff); - uint16_t flen = file.size(); - uint8_t fbuff[64]; - uint16_t blen = sizeof(fbuff); - while (flen>0) { - file.read(fbuff, blen); - flen -= blen; - g_client->write(fbuff, blen); - if (flenprint(F("\r\n\r\nfile not found!\r\n")); - } - g_client->print(F("\r\n--frontier\r\n")); -} - -#endif - -float *get_array_by_name(char *name, uint16_t *alen); -void flt2char(float num, char *nbuff); - -void attach_Array(char *aname) { - float *array = 0; - uint16_t alen; - array = get_array_by_name(aname, &alen); - g_client->print(F("--frontier\r\n")); - g_client->print(F("Content-Type: text/plain\r\n")); - if (array && alen) { -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("array found %d"),alen); -#endif - char buff[64]; - sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s.txt\"\r\n\r\n"), aname); - g_client->write(buff); - - strcpy(buff, GetDateAndTime(DT_LOCAL).c_str()); - strcat(buff,"\t"); - g_client->write(buff); - - float *fp=array; - for (uint32_t cnt = 0; cntwrite(nbuff, strlen(nbuff)); - } - } else { - g_client->print(F("\r\n\r\narray not found!\r\n")); - } - g_client->print(F("\r\n--frontier\r\n")); -} - -#else -# 507 "/workspace/Tasmota/tasmota/sendemail.ino" -#include "ESP32_MailClient.h" -#include "SD.h" - - - - -#ifndef SEND_MAIL32_MINRAM -#define SEND_MAIL32_MINRAM 30*1024 -#endif - -void script_send_email_body(void(*func)(char *)); - -#define xPSTR(a) a - -SMTPData smtpData; -#define MAX_ATTCHMENTS 8 -char *attachments[MAX_ATTCHMENTS]; -uint8_t num_attachments; - - - - - -uint16_t SendMail(char *buffer) { - char *params,*oparams; - const char *mserv; - uint16_t port; - const char *user; - const char *pstr; - const char *passwd; - const char *from; - const char *to; - const char *subject; - const char *cmd; - uint16_t status=1; - uint16_t blen; - char *endcmd; - - - uint32_t mem=ESP.getFreeHeap(); - - if (mempicmax) cnt=1; - len=WcGetPicstore(cnt-1,&buff); - if (len) { - char str[12]; - sprintf(str,"img_%1d.jpg",cnt+1); - smtpData.addAttachData(str, "image/jpg",buff,len); - } -#endif - } else { - smtpData.addMessage(txt); - } -} -# 828 "/workspace/Tasmota/tasmota/sendemail.ino" -#endif - - -#endif -# 1 "/workspace/Tasmota/tasmota/settings.ino" -# 24 "/workspace/Tasmota/tasmota/settings.ino" -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(RtcSettings); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcSettingsSave(void) -{ - if (GetRtcSettingsCrc() != rtc_settings_crc) { - RtcSettings.valid = RTC_MEM_VALID; -#ifdef ESP8266 - ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); -#else - RtcDataSettings = RtcSettings; -#endif - rtc_settings_crc = GetRtcSettingsCrc(); - } -} - -void RtcSettingsLoad(void) -{ -#ifdef ESP8266 - ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); -#else - RtcSettings = RtcDataSettings; -#endif - if (RtcSettings.valid != RTC_MEM_VALID) { - memset(&RtcSettings, 0, sizeof(RtcSettings)); - 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(RtcReboot); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcRebootSave(void) -{ - if (GetRtcRebootCrc() != rtc_reboot_crc) { - RtcReboot.valid = RTC_MEM_VALID; -#ifdef ESP8266 - ESP.rtcUserMemoryWrite(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); -#else - RtcDataReboot = RtcReboot; -#endif - rtc_reboot_crc = GetRtcRebootCrc(); - } -} - -void RtcRebootReset(void) -{ - RtcReboot.fast_reboot_count = 0; - RtcRebootSave(); -} - -void RtcRebootLoad(void) -{ -#ifdef ESP8266 - ESP.rtcUserMemoryRead(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); -#else - RtcReboot = RtcDataReboot; -#endif - if (RtcReboot.valid != RTC_MEM_VALID) { - memset(&RtcReboot, 0, sizeof(RtcReboot)); - RtcReboot.valid = RTC_MEM_VALID; - - RtcRebootSave(); - } - rtc_reboot_crc = GetRtcRebootCrc(); -} - -bool RtcRebootValid(void) -{ - return (RTC_MEM_VALID == RtcReboot.valid); -} -# 155 "/workspace/Tasmota/tasmota/settings.ino" -extern "C" { -#include "spi_flash.h" -} -#include "eboot_command.h" - -#ifdef ESP8266 - -#if AUTOFLASHSIZE - -#include "flash_hal.h" - - -const uint32_t SPIFFS_END = (FS_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; - -#endif - - -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) -{ -#ifdef ESP8266 - 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; -#endif -} - -bool VersionCompatible(void) -{ -#ifdef ESP8266 - - if (Settings.flag3.compatibility_check) { - return true; - } - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - uint32_t start_address = ebcmd.args[0]; - uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; - uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; - - uint32_t version[3] = { 0 }; - bool found = false; - for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { - ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); - if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { - version[1] = 0xFFFFFFFF; - found = true; - } else { - for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { - version[0] = version[1]; - version[1] = version[2]; - version[2] = buffer[i]; - if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { - found = true; - break; - } - } - } - if (found) { break; } - } - delete[] buffer; - - if (!found) { version[1] = 0; } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); - - if (version[1] < VERSION_COMPATIBLE) { - uint32_t eboot_magic = 0; - ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); - return false; - } - -#endif - - return true; -} - -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(Settings); - 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(Settings) -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); -} - - - - - -void UpdateQuickPowerCycle(bool update) { -#ifndef FIRMWARE_MINIMAL - if (Settings.flag3.fast_power_cycle_disable) { return; } - - const uint32_t QPC_COUNT = 7; - const uint32_t QPC_SIGNATURE = 0xFFA55AFF; - -#ifdef ESP8266 - const uint32_t qpc_sector = SETTINGS_LOCATION - CFG_ROTATES; - const uint32_t qpc_location = qpc_sector * SPI_FLASH_SEC_SIZE; - - uint32_t qpc_buffer[QPC_COUNT +1]; - ESP.flashRead(qpc_location, (uint32*)&qpc_buffer, sizeof(qpc_buffer)); - if (update && (QPC_SIGNATURE == qpc_buffer[0])) { - uint32_t counter = 1; - while ((0 == qpc_buffer[counter]) && (counter <= QPC_COUNT)) { counter++; } - if (QPC_COUNT == counter) { - SettingsErase(3); - EspRestart(); - } else { - qpc_buffer[0] = 0; - ESP.flashWrite(qpc_location + (counter * 4), (uint32*)&qpc_buffer, 4); - AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter); - } - } - else if ((qpc_buffer[0] != QPC_SIGNATURE) || (0 == qpc_buffer[1])) { - qpc_buffer[0] = QPC_SIGNATURE; - - if (ESP.flashEraseSector(qpc_sector)) { - ESP.flashWrite(qpc_location, (uint32*)&qpc_buffer, 4); - AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset")); - } - } -#else - uint32_t pc_register; - QPCRead(&pc_register, sizeof(pc_register)); - if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AF0)) { - uint32_t counter = pc_register & 0xF; - if (0xF == counter) { counter = 0; } - counter++; - if (QPC_COUNT == counter) { - SettingsErase(3); - EspRestart(); - } else { - pc_register = 0xFFA55AF0 | counter; - QPCWrite(&pc_register, sizeof(pc_register)); - AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter); - } - } - else if (pc_register != QPC_SIGNATURE) { - pc_register = QPC_SIGNATURE; - QPCWrite(&pc_register, sizeof(pc_register)); - AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset")); - } -#endif - -#endif -} - - - - - -uint32_t GetSettingsTextLen(void) { - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - } - return position - Settings.text_pool; -} - -bool settings_text_mutex = false; -uint32_t settings_text_busy_count = 0; - -bool SettingsUpdateFinished(void) { - uint32_t wait_loop = 10; - while (settings_text_mutex && wait_loop) { - yield(); - delayMicroseconds(1); - wait_loop--; - } - return (wait_loop > 0); -} - -bool SettingsUpdateText(uint32_t index, const char* replace_me) { - if (index >= SET_MAX) { - return false; - } - - - uint32_t replace_len = strlen_P(replace_me); - char replace[replace_len +1]; - memcpy_P(replace, replace_me, sizeof(replace)); - uint32_t index_save = index; - - uint32_t start_pos = 0; - uint32_t end_pos = 0; - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - if (1 == index) { - start_pos = position - Settings.text_pool; - } - else if (0 == index) { - end_pos = position - Settings.text_pool -1; - } - index--; - } - uint32_t char_len = position - Settings.text_pool; - - uint32_t current_len = end_pos - start_pos; - int diff = replace_len - current_len; - - - - - int too_long = (char_len + diff) - settings_text_size; - if (too_long > 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); - return false; - } - - if (settings_text_mutex && !SettingsUpdateFinished()) { - settings_text_busy_count++; - } else { - settings_text_mutex = true; - - if (diff != 0) { - - memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); - } - - memmove_P(Settings.text_pool + start_pos, replace, replace_len); - - memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); - - settings_text_mutex = false; - } - -#ifdef DEBUG_FUNC_SETTINGSUPDATETEXT - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d, Busy %d, Id %02d = \"%s\""), GetSettingsTextLen(), settings_text_size, settings_text_busy_count, index_save, replace); -#else - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d, Busy %d"), GetSettingsTextLen(), settings_text_size, settings_text_busy_count); -#endif - - return true; -} - -char* SettingsText(uint32_t index) -{ - char* position = Settings.text_pool; - - if (index >= SET_MAX) { - position += settings_text_size -1; - } else { - SettingsUpdateFinished(); - for (;index > 0; index--) { - while (*position++ != '\0') { } - } - } - return position; -} - - - - - -void UpdateBackwardCompatibility(void) -{ - - strlcpy(Settings.user_template_name, SettingsText(SET_TEMPLATE_NAME), sizeof(Settings.user_template_name)); -} - -uint32_t GetSettingsAddress(void) -{ - return settings_location * SPI_FLASH_SEC_SIZE; -} - -void SettingsSave(uint8_t rotate) -{ -# 525 "/workspace/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - UpdateBackwardCompatibility(); - 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(Settings); - Settings.cfg_crc = GetSettingsCrc(); - Settings.cfg_crc32 = GetSettingsCrc32(); - -#ifdef ESP8266 - if (ESP.flashEraseSector(settings_location)) { - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); - } - - 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(Settings)); -#else - SettingsWrite(&Settings, sizeof(Settings)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "Saved, " D_COUNT " %d, " D_BYTES " %d"), Settings.save_flag, sizeof(Settings)); -#endif - - settings_crc32 = Settings.cfg_crc32; - } -#endif - RtcSettingsSave(); -} - -void SettingsLoad(void) { -#ifdef ESP8266 - - - settings_location = 0; - uint32_t save_flag = 0; - uint32_t flash_location = SETTINGS_LOCATION; - for (uint32_t i = 0; i < CFG_ROTATES; i++) { - ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); - if ((Settings.cfg_crc32 != 0xFFFFFFFF) && (Settings.cfg_crc32 != 0x00000000) && (Settings.cfg_crc32 == GetSettingsCrc32())) { - if (Settings.save_flag > save_flag) { - save_flag = Settings.save_flag; - settings_location = flash_location; - if (Settings.flag.stop_flash_rotate && (0 == i)) { - break; - } - } - } - flash_location--; - delay(1); - } - if (settings_location > 0) { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); - AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); - } -#else - SettingsRead(&Settings, sizeof(Settings)); - AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded, " D_COUNT " %lu"), Settings.save_flag); -#endif - -#ifndef FIRMWARE_MINIMAL - if ((0 == settings_location) || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { - SettingsDefault(); - } - settings_crc32 = GetSettingsCrc32(); -#endif - - RtcSettingsLoad(); -} - -void EspErase(uint32_t start_sector, uint32_t end_sector) -{ - bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); - for (uint32_t sector = start_sector; sector < end_sector; sector++) { - - bool result = ESP.flashEraseSector(sector); - - - - if (serial_output) { - Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); - delay(10); - } else { - yield(); - } - OsWatchLoop(); - } -} - -#ifdef ESP8266 -void SettingsErase(uint8_t type) -{ -# 654 "/workspace/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; - uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - if (1 == type) { - - _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; - } - else if (2 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = SETTINGS_LOCATION +1; - } - else if (3 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; - } - else if (4 == type) { - - _sectorStart = SETTINGS_LOCATION +1; - _sectorEnd = _sectorStart +1; - } - - - - - - - else { - return; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); - - - EsptoolErase(_sectorStart, _sectorEnd); -#endif -} -#endif - -void SettingsSdkErase(void) -{ - WiFi.disconnect(false); - SettingsErase(1); - 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(Settings)); - - Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(Settings); - - Settings.version = VERSION; - - -} - - -const uint8_t default_fingerprint1[] PROGMEM = { MQTT_FINGERPRINT1 }; -const uint8_t default_fingerprint2[] PROGMEM = { MQTT_FINGERPRINT2 }; - -void SettingsDefaultSet2(void) -{ - memset((char*)&Settings +16, 0x00, sizeof(Settings) -16); - - - SysBitfield flag = { 0 }; - SysBitfield2 flag2 = { 0 }; - SysBitfield3 flag3 = { 0 }; - SysBitfield4 flag4 = { 0 }; - SysBitfield5 flag5 = { 0 }; - -#ifdef ESP8266 - Settings.gpio16_converted = 0xF5A0; - -#endif -#ifdef ESP32 - Settings.config_version = 1; -#endif - - flag.stop_flash_rotate |= APP_FLASH_CYCLE; - flag.global_state |= APP_ENABLE_LEDLINK; - flag3.sleep_normal |= APP_NORMAL_SLEEP; - flag3.no_power_feedback |= APP_NO_RELAY_SCAN; - flag3.fast_power_cycle_disable |= APP_DISABLE_POWERCYCLE; - flag3.bootcount_update |= DEEPSLEEP_BOOTCOUNT; - flag3.compatibility_check |= OTA_COMPATIBILITY; - Settings.save_data = SAVE_DATA; - Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; - 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; - } - - - flag.interlock |= APP_INTERLOCK_MODE; - Settings.interlock[0] = APP_INTERLOCK_GROUP_1; - Settings.interlock[1] = APP_INTERLOCK_GROUP_2; - Settings.interlock[2] = APP_INTERLOCK_GROUP_3; - Settings.interlock[3] = APP_INTERLOCK_GROUP_4; - Settings.module = MODULE; - Settings.fallback_module = FALLBACK_MODULE; - ModuleDefault(WEMOS); - - SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME)); - SettingsUpdateText(SET_FRIENDLYNAME2, PSTR(FRIENDLY_NAME"2")); - SettingsUpdateText(SET_FRIENDLYNAME3, PSTR(FRIENDLY_NAME"3")); - SettingsUpdateText(SET_FRIENDLYNAME4, PSTR(FRIENDLY_NAME"4")); - SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); - SettingsUpdateText(SET_OTAURL, PSTR(OTA_URL)); - - - 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.ledpwm_on = 255; - - Settings.pulse_timer[0] = APP_PULSETIME; - - - - Settings.serial_config = TS_SERIAL_8N1; - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - Settings.seriallog_level = SERIAL_LOG_LEVEL; - - - flag4.network_ethernet |= 1; -#ifdef ESP32 - Settings.eth_type = ETH_TYPE; - Settings.eth_clk_mode = ETH_CLKMODE; - Settings.eth_address = ETH_ADDR; -#endif - - - flag4.network_wifi |= 1; - flag3.use_wifi_scan |= WIFI_SCAN_AT_RESTART; - flag3.use_wifi_rescan |= WIFI_SCAN_REGULARLY; - Settings.wifi_output_power = 170; - Settings.param[P_ARP_GRATUITOUS] = WIFI_ARP_INTERVAL; - 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; - - SettingsUpdateText(SET_STASSID1, PSTR(STA_SSID1)); - SettingsUpdateText(SET_STASSID2, PSTR(STA_SSID2)); - SettingsUpdateText(SET_STAPWD1, PSTR(STA_PASS1)); - SettingsUpdateText(SET_STAPWD2, PSTR(STA_PASS2)); - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - - - SettingsUpdateText(SET_SYSLOG_HOST, PSTR(SYS_LOG_HOST)); - Settings.syslog_port = SYS_LOG_PORT; - Settings.syslog_level = SYS_LOG_LEVEL; - - - flag2.emulation |= EMULATION; - flag4.alexa_gen_1 |= EMULATION_HUE_1ST_GEN; - flag3.gui_hostname_ip |= GUI_SHOW_HOSTNAME; - flag3.mdns_enabled |= MDNS_ENABLED; - Settings.webserver = WEB_SERVER; - Settings.weblog_level = WEB_LOG_LEVEL; - SettingsUpdateText(SET_WEBPWD, PSTR(WEB_PASSWORD)); - SettingsUpdateText(SET_CORS, PSTR(CORS_DOMAIN)); - - - flag.button_restrict |= KEY_DISABLE_MULTIPRESS; - flag.button_swap |= KEY_SWAP_DOUBLE_PRESS; - flag.button_single |= KEY_ONLY_SINGLE_PRESS; - Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; - - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } - - - flag.mqtt_enabled |= MQTT_USE; - flag.mqtt_response |= MQTT_RESULT_COMMAND; - flag.mqtt_offline |= MQTT_LWT_MESSAGE; - flag.mqtt_power_retain |= MQTT_POWER_RETAIN; - flag.mqtt_button_retain |= MQTT_BUTTON_RETAIN; - flag.mqtt_switch_retain |= MQTT_SWITCH_RETAIN; - flag.mqtt_sensor_retain |= MQTT_SENSOR_RETAIN; - - flag.device_index_enable |= MQTT_POWER_FORMAT; - flag3.time_append_timezone |= MQTT_APPEND_TIMEZONE; - flag3.button_switch_force_local |= MQTT_BUTTON_SWITCH_FORCE_LOCAL; - flag3.no_hold_retain |= MQTT_NO_HOLD_RETAIN; - flag3.use_underscore |= MQTT_INDEX_SEPARATOR; - flag3.grouptopic_mode |= MQTT_GROUPTOPIC_FORMAT; - SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); - Settings.mqtt_port = MQTT_PORT; - SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); - SettingsUpdateText(SET_MQTT_USER, MQTT_USER); - SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); - SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); - SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); - Settings.mqtt_retry = MQTT_RETRY_SECS; - SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); - SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); - SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); - SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); - SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); - memcpy_P(Settings.mqtt_fingerprint[0], default_fingerprint1, sizeof(default_fingerprint1)); - memcpy_P(Settings.mqtt_fingerprint[1], default_fingerprint2, sizeof(default_fingerprint2)); - Settings.tele_period = TELE_PERIOD; - Settings.mqttlog_level = MQTT_LOG_LEVEL; - - - flag.no_power_on_check |= ENERGY_VOLTAGE_ALWAYS; - flag2.current_resolution |= 3; - - - flag2.energy_resolution |= ENERGY_RESOLUTION; - flag3.dds2382_model |= ENERGY_DDS2382_MODE; - flag3.hardware_energy_total |= ENERGY_HARDWARE_TOTALS; - 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; -# 911 "/workspace/Tasmota/tasmota/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; - - - flag.ir_receive_decimal |= IR_DATA_RADIX; - flag3.receive_raw |= IR_ADD_RAW_DATA; - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - - - flag.rf_receive_decimal |= RF_DATA_RADIX; - - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - - - Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; -# 946 "/workspace/Tasmota/tasmota/settings.ino" - flag.temperature_conversion |= TEMP_CONVERSION; - flag.pressure_conversion |= PRESSURE_CONVERSION; - flag2.pressure_resolution |= PRESSURE_RESOLUTION; - flag2.humidity_resolution |= HUMIDITY_RESOLUTION; - flag2.temperature_resolution |= TEMP_RESOLUTION; - flag3.ds18x20_internal_pullup |= DS18X20_PULL_UP; - flag3.counter_reset_on_tele |= COUNTER_RESET; - - - - - - - flag2.calc_resolution |= CALC_RESOLUTION; - - - flag3.timers_enable |= TIMERS_ENABLED; - - - flag.hass_light |= HASS_AS_LIGHT; - flag.hass_discovery |= HOME_ASSISTANT_DISCOVERY_ENABLE; - flag3.hass_tele_on_power |= TELE_ON_POWER; - - - flag.knx_enabled |= KNX_ENABLED; - flag.knx_enable_enhancement |= KNX_ENHANCED; - - - flag.pwm_control |= LIGHT_MODE; - flag.ws_clock_reverse |= LIGHT_CLOCK_DIRECTION; - flag.light_signal |= LIGHT_PAIRS_CO2; - flag.not_power_linked |= LIGHT_POWER_CONTROL; - flag.decimal_text |= LIGHT_COLOR_RADIX; - flag3.pwm_multi_channels |= LIGHT_CHANNEL_MODE; - flag3.slider_dimmer_stay_on |= LIGHT_SLIDER_POWER; - flag4.alexa_ct_range |= LIGHT_ALEXA_CT_RANGE; - flag4.pwm_ct_mode |= LIGHT_PWM_CT_MODE; - flag4.white_blend_mode |= LIGHT_WHITE_BLEND_MODE; - flag4.virtual_ct |= LIGHT_VIRTUAL_CT; - flag4.virtual_ct_cw |= LIGHT_VIRTUAL_CT_CW; - - Settings.pwm_frequency = PWM_FREQ; - Settings.pwm_range = PWM_RANGE; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - Settings.light_color[i] = DEFAULT_LIGHT_COMPONENT; - - } - Settings.light_correction = 1; - Settings.light_dimmer = DEFAULT_LIGHT_DIMMER; - - Settings.light_speed = 1; - - Settings.light_width = 1; - - Settings.light_pixels = WS2812_LEDS; - - Settings.ws_width[WS_SECOND] = 1; - Settings.ws_color[WS_SECOND][WS_RED] = 255; - - Settings.ws_color[WS_SECOND][WS_BLUE] = 255; - Settings.ws_width[WS_MINUTE] = 3; - - Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; - - Settings.ws_width[WS_HOUR] = 5; - Settings.ws_color[WS_HOUR][WS_RED] = 255; - - - - Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; - Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; - - - - 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_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; - - - 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); - } - SettingsUpdateText(SET_NTPSERVER1, PSTR(NTP_SERVER1)); - SettingsUpdateText(SET_NTPSERVER2, PSTR(NTP_SERVER2)); - SettingsUpdateText(SET_NTPSERVER3, PSTR(NTP_SERVER3)); - for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { - SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); - } - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsResetStd(); - SettingsResetDst(); - - 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_startingoffset = STARTING_OFFSET; - - SettingsDefaultWebColor(); - - memset(&Settings.monitors, 0xFF, 20); - SettingsEnableAllI2cDrivers(); - - - flag3.tuya_apply_o20 |= TUYA_SETOPTION_20; - flag3.tuya_serial_mqtt_publish |= MQTT_TUYA_RECEIVED; - - flag3.buzzer_enable |= BUZZER_ENABLE; - flag3.shutter_mode |= SHUTTER_SUPPORT; - flag3.pcf8574_ports_inverted |= PCF8574_INVERT_PORTS; - flag4.zigbee_use_names |= ZIGBEE_FRIENDLY_NAMES; - flag4.remove_zbreceived |= ZIGBEE_RMV_ZBRECEIVED; - flag4.zb_index_ep |= ZIGBEE_INDEX_EP; - flag4.mqtt_tls |= MQTT_TLS_ENABLED; - flag4.mqtt_no_retain |= MQTT_NO_RETAIN; - -#ifdef USER_TEMPLATE - JsonTemplate((char *)USER_TEMPLATE); -#endif - - Settings.flag = flag; - Settings.flag2 = flag2; - Settings.flag3 = flag3; - Settings.flag4 = flag4; -} - - - -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 SettingsDefaultWebColor(void) -{ - char scolor[10]; - for (uint32_t i = 0; i < COL_LAST; i++) { - WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); - } -} - -void SettingsEnableAllI2cDrivers(void) -{ - Settings.i2c_drivers[0] = 0xFFFFFFFF; - Settings.i2c_drivers[1] = 0xFFFFFFFF; - Settings.i2c_drivers[2] = 0xFFFFFFFF; -} - - - -void SettingsDelta(void) -{ - if (Settings.version != VERSION) { - -#ifdef ESP8266 - if (Settings.version < 0x07000002) { - Settings.web_color2[0][0] = Settings.web_color[0][0]; - Settings.web_color2[0][1] = Settings.web_color[0][1]; - Settings.web_color2[0][2] = Settings.web_color[0][2]; - } - if (Settings.version < 0x07000003) { - SettingsEnableAllI2cDrivers(); - } - if (Settings.version < 0x07000004) { - Settings.ex_wifi_output_power = 170; - } - if (Settings.version < 0x07010202) { - Settings.ex_serial_config = TS_SERIAL_8N1; - } - if (Settings.version < 0x07010204) { - if (Settings.flag3.mqtt_buttons == 1) { - strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); - } else { - Settings.ex_cors_domain[0] = 0; - } - } - if (Settings.version < 0x07010205) { - Settings.seriallog_level = Settings.ex_seriallog_level; - Settings.sta_config = Settings.ex_sta_config; - Settings.sta_active = Settings.ex_sta_active; - memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); - } - if (Settings.version < 0x07010206) { - Settings.flag4 = Settings.ex_flag4; - Settings.mqtt_port = Settings.ex_mqtt_port; - memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); - } - if (Settings.version < 0x08000000) { - char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); - char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); - char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); - char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); - char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); - char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); - char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); - char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); - char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); - char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); - char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); - char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); - char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); - char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); - char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); - char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); - char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); - - memset(Settings.text_pool, 0x00, settings_text_size); - SettingsUpdateText(SET_OTAURL, temp); - SettingsUpdateText(SET_MQTTPREFIX1, temp21); - SettingsUpdateText(SET_MQTTPREFIX2, temp22); - SettingsUpdateText(SET_MQTTPREFIX3, temp23); - SettingsUpdateText(SET_STASSID1, temp31); - SettingsUpdateText(SET_STASSID2, temp32); - SettingsUpdateText(SET_STAPWD1, temp41); - SettingsUpdateText(SET_STAPWD2, temp42); - SettingsUpdateText(SET_HOSTNAME, temp5); - SettingsUpdateText(SET_SYSLOG_HOST, temp6); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (!strlen(Settings.ex_mqtt_user)) { - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); - } else { - char aws_mqtt_host[66]; - snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); - SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); - SettingsUpdateText(SET_MQTT_USER, ""); - } -#else - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); -#endif - SettingsUpdateText(SET_MQTT_CLIENT, temp8); - SettingsUpdateText(SET_MQTT_PWD, temp10); - SettingsUpdateText(SET_MQTT_TOPIC, temp11); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - - SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); - SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); - SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); - - SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); - SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); - SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); - SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); - SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); - SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); - SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); - SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); - SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); - SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); - SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); - SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); - - - - - } - if (Settings.version < 0x08020003) { - SettingsUpdateText(SET_TEMPLATE_NAME, Settings.user_template_name); - Settings.zb_channel = 0; - } -#endif - - if (Settings.version < 0x08020004) { - Settings.flag3.mqtt_buttons = 0; -#ifdef ESP8266 - Settings.config_version = 0; -#endif -#ifdef ESP32 - Settings.config_version = 1; -#endif - } - if (Settings.version < 0x08020006) { -#ifdef ESP32 - Settings.module = WEMOS; - ModuleDefault(WEMOS); -#endif - - if (Settings.rules[0][0] == 0) { Settings.rules[0][1] = 0; } - if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; } - if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; } - } - if (Settings.version < 0x08030002) { - SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); - Settings.ledpwm_off = 0; - Settings.ledpwm_on = 255; - Settings.ledpwm_mask = 0; - } - if (Settings.version < 0x08030104) { - Settings.flag4.network_wifi = 1; - Settings.flag4.network_ethernet = 1; - } -#ifdef ESP32 - if (Settings.version < 0x08030105) { - Settings.eth_type = ETH_TYPE; - Settings.eth_clk_mode = ETH_CLKMODE; - Settings.eth_address = ETH_ADDR; - } -#endif - if (Settings.version < 0x08030106) { - Settings.fallback_module = FALLBACK_MODULE; - } - if (Settings.version < 0x08040003) { - Settings.energy_power_delta[0] = Settings.hass_new_discovery; - Settings.energy_power_delta[1] = 0; - Settings.energy_power_delta[2] = 0; - } -#ifdef ESP8266 - if (Settings.version < 0x09000002) { - char parameters[32]; - snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"), - Settings.ex_adc_param_type, Settings.ex_adc_param1, Settings.ex_adc_param2, Settings.ex_adc_param3, Settings.ex_adc_param4); - SettingsUpdateText(SET_ADC_PARAM1, parameters); - } -#endif - - Settings.version = VERSION; - SettingsSave(1); - } - -} -# 1 "/workspace/Tasmota/tasmota/support.ino" -# 20 "/workspace/Tasmota/tasmota/support.ino" -IPAddress syslog_host_addr; -uint32_t syslog_host_hash = 0; - -extern "C" { -extern struct rst_info resetInfo; -} - - - - - -#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 = t - oswatch_last_loop_time; - -#ifdef DEBUG_THEO - int32_t rssi = WiFi.RSSI(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP_getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); -#endif - if (last_run >= (OSWATCH_RESET_TIME * 1000)) { - - RtcSettings.oswatch_blocked_loop = 1; - RtcSettingsSave(); - - - - - - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); - } -} - -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(); - -} - -bool OsWatchBlockedLoop(void) -{ - return oswatch_blocked_loop; -} - -uint32_t ResetReason(void) -{ -# 102 "/workspace/Tasmota/tasmota/support.ino" - return ESP_ResetInfoReason(); -} - -String GetResetReason(void) -{ - if (oswatch_blocked_loop) { - char buff[32]; - strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); - return String(buff); - } else { - return ESP_getResetReason(); - } -} -# 132 "/workspace/Tasmota/tasmota/support.ino" -String GetBinary8(uint8_t value, size_t count) { - if (count > 8) { count = 8; } - value <<= (8 - count); - String result; - result.reserve(count + 1); - for (uint32_t i = 0; i < count; i++) { - result += (value &0x80) ? '1' : '0'; - value <<= 1; - } - return result; -} - - -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; -} - -uint32_t ChrCount(const char *str, const char *delim) { - uint32_t count = 0; - char* read = (char*)str; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (ch == *delim) { count++; } - } - return count; -} - - -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; - if (*pt == '\0') { return 0.0; } - - 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++; - uint32_t max_decimals = 0; - while ((max_decimals < 8) && isdigit(pt[max_decimals])) { max_decimals++; } - pt[max_decimals] = '\0'; - 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; - - - - do { - int 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* RemoveControlCharacter(char* p) { - - char* write = p; - char* read = p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (!iscntrl(ch)) { - *write++ = ch; - } - } - *write++ = '\0'; - return p; -} - -char* ReplaceCommaWithDot(char* p) { - - char* write = (char*)p; - char* read = (char*)p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (ch == ',') { - 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) -{ - if (*p != '\0') { - while ((*p != '\0') && isblank(*p)) { p++; } - char* q = p + strlen(p) -1; - while ((q >= p) && isblank(*q)) { q--; } - q++; - *q = '\0'; - } - return p; -} -# 479 "/workspace/Tasmota/tasmota/support.ino" -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(void) -{ - - - - - - - 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(void) -{ - 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); -} - -uint32_t ParseParameters(uint32_t count, uint32_t *params) -{ - char *p; - uint32_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p), i++) { - params[i] = strtoul(str, nullptr, 0); - } - return i; -} - - -bool NewerVersion(char* version_str) -{ - uint32_t version = 0; - uint32_t i = 0; - char *str_ptr; - - char version_dup[strlen(version_str) +1]; - strncpy(version_dup, version_str, sizeof(version_dup)); - - 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)) { - 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++; - } - } - - - 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) -{ - strncpy_P(dest, S_RSLT_POWER, size); - if ((devices_present + option) > 1) { - char sidx[8]; - 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); -} - -void GetEspHardwareType(void) -{ -#ifdef ESP8266 - - uint32_t efuse1 = *(uint32_t*)(0x3FF00050); - uint32_t efuse2 = *(uint32_t*)(0x3FF00054); - - - - is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); - if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { - is_8285 = false; - } -#else - is_8285 = false; -#endif -} - -String GetDeviceHardware(void) -{ - char buff[10]; -#ifdef ESP8266 - if (is_8285) { - strcpy_P(buff, PSTR("ESP8285")); - } else { - strcpy_P(buff, PSTR("ESP8266EX")); - } -#else - strcpy_P(buff, PSTR("ESP32")); -#endif - return String(buff); -} - -float ConvertTemp(float c) -{ - float result = c; - - global_update = uptime; - global_temperature_celsius = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = c * 1.8 + 32; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -float ConvertTempToCelsius(float c) -{ - float result = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = (c - 32) / 1.8; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -char TempUnit(void) -{ - - return (Settings.flag.temperature_conversion) ? D_UNIT_FAHRENHEIT[0] : D_UNIT_CELSIUS[0]; -} - -float ConvertHumidity(float h) -{ - float result = h; - - global_update = uptime; - global_humidity = h; - - result = result + (0.1 * Settings.hum_comp); - - return result; -} - -float CalcTempHumToDew(float t, float h) -{ - if (isnan(h) || isnan(t)) { return NAN; } - - if (Settings.flag.temperature_conversion) { - t = (t - 32) / 1.8; - } - - float gamma = TaylorLog(h / 100) + 17.62 * t / (243.5 + t); - float result = (243.5 * gamma / (17.62 - gamma)); - - if (Settings.flag.temperature_conversion) { - result = result * 1.8 + 32; - } - return result; -} - -float ConvertPressure(float p) -{ - float result = p; - - global_update = uptime; - global_pressure_hpa = 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); -} - -float ConvertSpeed(float s) -{ - - return s * kSpeedConversionFactor[Settings.flag2.speed_conversion]; -} - -String SpeedUnit(void) -{ - char speed[8]; - return String(GetTextIndexed(speed, sizeof(speed), Settings.flag2.speed_conversion, kSpeedUnit)); -} - -void ResetGlobalValues(void) -{ - if ((uptime - global_update) > GLOBAL_VALUES_VALID) { - global_update = 0; - global_temperature_celsius = NAN; - global_humidity = 0.0f; - global_pressure_hpa = 0.0f; - } -} - -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); - if (prefix_length) { - char prefix[prefix_length +1]; - snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); - if (strcasecmp(prefix, XdrvMailbox.command)) { - return false; - } - } - 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 "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" - "ON|" D_ON "|TRUE|" D_TRUE "|START|" 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,0,0, - 1,1,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; -} - -String GetSerialConfig(void) { - - - - - - const char kParity[] = "NEOI"; - - char config[4]; - config[0] = '5' + (Settings.serial_config & 0x3); - config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; - config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); - config[3] = '\0'; - return String(config); -} - -void SetSerialBegin(void) { - baudrate = Settings.baudrate * 300; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); - Serial.flush(); - Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); -} - -void SetSerialConfig(uint32_t serial_config) { - if (serial_config > TS_SERIAL_8O2) { - serial_config = TS_SERIAL_8N1; - } - if (serial_config != Settings.serial_config) { - Settings.serial_config = serial_config; - SetSerialBegin(); - } -} - -void SetSerialBaudrate(uint32_t ubaudrate) { - baudrate = ubaudrate; - Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - SetSerialBegin(); - } -} - -void SetSerial(uint32_t ubaudrate, uint32_t serial_config) { - Settings.flag.mqtt_serial = 0; - Settings.serial_config = serial_config; - baudrate = ubaudrate; - Settings.baudrate = baudrate / 300; - SetSeriallog(LOG_LEVEL_NONE); - SetSerialBegin(); -} - -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 > 1) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - Serial.write(code); - size -= 2; - codes += 2; - } -} - - -void SerialSendDecimal(char *values) -{ - char *p; - uint8_t code; - for (char* str = strtok_r(values, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { - code = (uint8_t)atoi(str); - Serial.write(code); - } -} - -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); - - - - - - - uint32_t j = sizeof(Settings.web_color) / 3; -# 1027 "/workspace/Tasmota/tasmota/support.ino" - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - 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 j = sizeof(Settings.web_color) / 3; - - - - - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - 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; - case 3: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL_MILLIS).c_str()); - 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 ResponseAppendTHD(float f_temperature, float f_humidity) -{ - char temperature[FLOATSZ]; - dtostrfd(f_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[FLOATSZ]; - dtostrfd(f_humidity, Settings.flag2.humidity_resolution, humidity); - char dewpoint[FLOATSZ]; - dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings.flag2.temperature_resolution, dewpoint); - - return ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_DEWPOINT "\":%s"), temperature, humidity, dewpoint); -} - -int ResponseJsonEnd(void) -{ - return ResponseAppend_P(PSTR("}")); -} - -int ResponseJsonEndEnd(void) -{ - return ResponseAppend_P(PSTR("}}")); -} - - - - - -#ifdef ESP8266 -uint16_t GpioConvert(uint8_t gpio) { - if (gpio > ARRAY_SIZE(kGpioConvert)) { - return AGPIO(GPIO_USER); - } - return pgm_read_word(kGpioConvert + gpio); -} - -uint16_t Adc0Convert(uint8_t adc0) { - if (adc0 > 7) { - return AGPIO(GPIO_USER); - } - else if (0 == adc0) { - return GPIO_NONE; - } - return AGPIO(GPIO_ADC_INPUT + adc0 -1); -} - -void TemplateConvert(uint8_t template8[], uint16_t template16[]) { - for (uint32_t i = 0; i < (sizeof(mytmplt) / 2) -2; i++) { - template16[i] = GpioConvert(template8[i]); - } - template16[(sizeof(mytmplt) / 2) -2] = Adc0Convert(template8[sizeof(mytmplt8285) -1]); - - - - -} - -void ConvertGpios(void) { - if (Settings.gpio16_converted != 0xF5A0) { - - TemplateConvert((uint8_t*)&Settings.ex_user_template8, (uint16_t*)&Settings.user_template); - - for (uint32_t i = 0; i < sizeof(Settings.ex_my_gp8.io); i++) { - Settings.my_gp.io[i] = GpioConvert(Settings.ex_my_gp8.io[i]); - } - Settings.my_gp.io[(sizeof(myio) / 2) -1] = Adc0Convert(Settings.ex_my_adc0); - Settings.gpio16_converted = 0xF5A0; - - - - - } -} -# 1231 "/workspace/Tasmota/tasmota/support.ino" -#endif - -uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index = 0); -uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) { - uint16_t real_gpio = gpio << 5; - uint16_t mask = 0xFFE0; - if (index < GPIO_ANY) { - real_gpio += index; - mask = 0xFFFF; - } - for (uint32_t i = 0; i < ARRAY_SIZE(gpio_pin); i++) { - if ((gpio_pin[i] & mask) == real_gpio) { - return i; - } - } - return 99; -} - -bool PinUsed(uint32_t gpio, uint32_t index = 0); -bool PinUsed(uint32_t gpio, uint32_t index) { - return (Pin(gpio, index) < 99); -} - -uint32_t GetPin(uint32_t lpin) { - if (lpin < ARRAY_SIZE(gpio_pin)) { - return gpio_pin[lpin]; - } else { - return GPIO_NONE; - } -} - -void SetPin(uint32_t lpin, uint32_t gpio) { - gpio_pin[lpin] = gpio; -} - -void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) -{ - if (PinUsed(gpio_pin, index)) { - digitalWrite(Pin(gpio_pin, index), state &1); - } -} - -uint8_t ModuleNr(void) -{ - - - 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); -} - -bool ValidTemplate(const char *search) { - char template_name[strlen(SettingsText(SET_TEMPLATE_NAME)) +1]; - char search_name[strlen(search) +1]; - - LowerCase(template_name, SettingsText(SET_TEMPLATE_NAME)); - LowerCase(search_name, search); - - return (strstr(template_name, search_name) != nullptr); -} - -String AnyModuleName(uint32_t index) -{ - if (USER_MODULE == index) { - return String(SettingsText(SET_TEMPLATE_NAME)); - } else { - char name[TOPSZ]; - return String(GetTextIndexed(name, sizeof(name), index, kModuleNames)); - } -} - -String ModuleName(void) -{ - return AnyModuleName(Settings.module); -} - -#ifdef ESP8266 -void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option) { - uint8_t module_template = pgm_read_byte(kModuleTemplateList + module); - - - - - uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE }; - if (module_template < TMP_WEMOS) { - memcpy_P(&template8, &kModules8266[module_template], 6); - memcpy_P(&template8[8], &kModules8266[module_template].gp.io[6], 6); - } else { - memcpy_P(&template8, &kModules8285[module_template - TMP_WEMOS], sizeof(template8)); - } - - - - - uint16_t template16[(sizeof(mytmplt) / 2)] = { GPIO_NONE }; - TemplateConvert(template8, template16); - - uint32_t index = 0; - uint32_t size = sizeof(mycfgio); - switch (option) { - case 2: { - index = (sizeof(mytmplt) / 2) -1; - size = 2; - break; - } - case 3: { - size = sizeof(mytmplt); - break; - } - } - memcpy(ptr, &template16[index], size); - - - -} -#endif - -void ModuleGpios(myio *gp) -{ - uint16_t *dest = (uint16_t *)gp; - uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)]; - - memset(dest, GPIO_NONE, sizeof(myio)); - if (USER_MODULE == Settings.module) { - memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); - } else { -#ifdef ESP8266 - GetInternalTemplate(&src, Settings.module, 1); -#else - memcpy_P(&src, &kModules.gp, sizeof(mycfgio)); -#endif - } - - - - - uint32_t j = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - dest[j] = src[i]; - j++; - } - - - -} - -gpio_flag ModuleFlag(void) -{ - gpio_flag flag; - - if (USER_MODULE == Settings.module) { - flag = Settings.user_template.flag; - } else { -#ifdef ESP8266 - GetInternalTemplate(&flag, Settings.module, 2); -#else - memcpy_P(&flag, &kModules.flag, sizeof(gpio_flag)); -#endif - } - - return flag; -} - -void ModuleDefault(uint32_t module) -{ - if (USER_MODULE == module) { module = WEMOS; } - Settings.user_template_base = module; - char name[TOPSZ]; - SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames)); -#ifdef ESP8266 - GetInternalTemplate(&Settings.user_template, module, 3); -#else - memcpy_P(&Settings.user_template, &kModules, sizeof(mytmplt)); -#endif -} - -void SetModuleType(void) -{ - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; -} - -bool FlashPin(uint32_t pin) -{ - return (((pin > 5) && (pin < 9)) || (11 == pin)); -} - -uint32_t ValidPin(uint32_t pin, uint32_t gpio) -{ - if (FlashPin(pin)) { - return GPIO_NONE; - } - - - if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { - if ((9 == pin) || (10 == pin)) { - return GPIO_NONE; - } - } - - return gpio; -} - -bool ValidGPIO(uint32_t pin, uint32_t gpio) -{ -#ifdef ESP8266 -#ifdef USE_ADC_VCC - if (ADC0_PIN == pin) { return false; } -#endif -#endif - return (GPIO_USER == ValidPin(pin, BGPIO(gpio))); -} - -bool GetUsedInModule(uint32_t val, uint16_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(char* dataBuf) -{ - - - - - - if (strlen(dataBuf) < 9) { return false; } - - JsonParser parser((char*) dataBuf); - JsonParserObject root = parser.getRootObject(); - if (!root) { return false; } - - - JsonParserToken val = root[PSTR(D_JSON_NAME)]; - if (val) { - SettingsUpdateText(SET_TEMPLATE_NAME, val.getStr()); - } - JsonParserArray arr = root[PSTR(D_JSON_GPIO)]; - if (arr) { -#ifdef ESP8266 - bool old_template = false; - uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE }; - if (13 == arr.size()) { - uint32_t gpio = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(template8) -1; i++) { - gpio = arr[i].getUInt(); - if (gpio > 255) { - break; - } - template8[i] = gpio; - } - old_template = (gpio < 256); - } - if (old_template) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TPL: Converting template ...")); - - val = root[PSTR(D_JSON_FLAG)]; - if (val) { - template8[ARRAY_SIZE(template8) -1] = val.getUInt() & 0x0F; - } - TemplateConvert(template8, Settings.user_template.gp.io); - Settings.user_template.flag.data = 0; - } else { -#endif - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { - JsonParserToken val = arr[i]; - if (!val) { break; } - uint16_t gpio = val.getUInt(); - if (gpio == (AGPIO(GPIO_NONE) +1)) { - gpio = AGPIO(GPIO_USER); - } - Settings.user_template.gp.io[i] = gpio; - } - val = root[PSTR(D_JSON_FLAG)]; - if (val) { - Settings.user_template.flag.data = val.getUInt(); - } - } -#ifdef ESP8266 - } -#endif - val = root[PSTR(D_JSON_BASE)]; - if (val) { - uint32_t base = val.getUInt(); - if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } - Settings.user_template_base = base -1; - } - - - - - return true; -} - -void TemplateJson(void) -{ - - - - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME)); - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { - uint16_t gpio = Settings.user_template.gp.io[i]; - if (gpio == AGPIO(GPIO_USER)) { - gpio = AGPIO(GPIO_NONE) +1; - } - ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", gpio); - } - ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); -} - - - - - -inline int32_t TimeDifference(uint32_t prev, uint32_t next) -{ - return ((int32_t) (next - prev)); -} - -int32_t TimePassedSince(uint32_t timestamp) -{ - - - return TimeDifference(timestamp, millis()); -} - -bool TimeReached(uint32_t 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); -} - -int32_t TimePassedSinceUsec(uint32_t timestamp) -{ - return TimeDifference(timestamp, micros()); -} - -bool TimeReachedUsec(uint32_t timer) -{ - - const long passed = TimePassedSinceUsec(timer); - return (passed >= 0); -} - - - - - -#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) -{ - 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--; - } - if (!retry) Wire.endTransmission(); - 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 "\"}")); - } -} - -void I2cResetActive(uint32_t addr, uint32_t count = 1) -{ - addr &= 0x7F; - count &= 0x7F; - while (count-- && (addr < 128)) { - i2c_active[addr / 32] &= ~(1 << (addr % 32)); - addr++; - } - -} - -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++; - } - -} - -void I2cSetActiveFound(uint32_t addr, const char *types) -{ - I2cSetActive(addr); - AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr); -} - -bool I2cActive(uint32_t addr) -{ - addr &= 0x7F; - if (i2c_active[addr / 32] & (1 << (addr % 32))) { - return true; - } - return false; -} - -bool I2cSetDevice(uint32_t addr) -{ - addr &= 0x7F; - if (I2cActive(addr)) { - return false; - } - Wire.beginTransmission((uint8_t)addr); - return (0 == Wire.endTransmission()); -} -#endif -# 1919 "/workspace/Tasmota/tasmota/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) -{ - - - uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; - WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); - } - if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { - char syslog_preamble[64]; - snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), NetworkHostname()); - 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) && - (masterlog_level <= seriallog_level)) { - Serial.printf("%s%s\r\n", mxtime, log_data); - } -#ifdef USE_WEBSERVER - if (Settings.webserver && - (loglevel <= Settings.weblog_level) && - (masterlog_level <= 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 (Settings.flag.mqtt_enabled && - !global_state.mqtt_down && - (loglevel <= Settings.mqttlog_level) && - (masterlog_level <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } - - if (!global_state.network_down && - (loglevel <= syslog_level) && - (masterlog_level <= syslog_level)) { Syslog(); } - - prepped_loglevel = 0; -} - -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 PrepLog_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); - - prepped_loglevel = 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) -{ -# 2087 "/workspace/Tasmota/tasmota/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(const char *sensor, uint32_t misses) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); -} - -void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size) { - snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); - for (uint32_t i = 0; i < count; i++) { - if (1 == size) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer)); - } else { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X%02X"), log_data, *(buffer +1), *(buffer)); - } - buffer += size; - } - AddLog(loglevel); -} - - - - - -#ifdef USE_UNISHOX_COMPRESSION - -#include - -Unishox compressor; - -String Decompress(const char * compressed, size_t uncompressed_size) { - String content(""); - - uncompressed_size += 2; - - - - - - content.reserve(uncompressed_size); - char * buffer = content.begin(); - - int32_t len = compressor.unishox_decompress(compressed, strlen_P(compressed), buffer, uncompressed_size); - if (len > 0) { - buffer[len] = 0; - content = buffer; - } - return content; -} - -#endif - - - - - - -uint32_t HwRandom(void) { -#if ESP8266 - - #define _RAND_ADDR 0x3FF20E44UL -#else - #define _RAND_ADDR 0x3FF75144UL -#endif - static uint32_t last_ccount = 0; - uint32_t ccount; - uint32_t result = 0; - do { - ccount = ESP.getCycleCount(); - result ^= *(volatile uint32_t *)_RAND_ADDR; - } while (ccount - last_ccount < 64); - last_ccount = ccount; - return result ^ *(volatile uint32_t *)_RAND_ADDR; -#undef _RAND_ADDR -} -# 1 "/workspace/Tasmota/tasmota/support_button.ino" -# 20 "/workspace/Tasmota/tasmota/support_button.ino" -#define BUTTON_V2 -#ifdef BUTTON_V2 - - - - -#define MAX_RELAY_BUTTON1 5 -#ifdef ESP32 -#define TOUCH_PIN_THRESHOLD 12 -#define TOUCH_HIT_THRESHOLD 3 -#endif - -const char kMultiPress[] PROGMEM = - "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; - -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; -#ifdef ESP32 - uint8_t touch_mask = 0; - uint8_t touch_hits[MAX_KEYS] = { 0 }; -#endif - uint8_t present = 0; -} Button; - -#ifdef ESP32 -struct TOUCH_BUTTON { - uint8_t pin_threshold = TOUCH_PIN_THRESHOLD; - uint8_t hit_threshold = TOUCH_HIT_THRESHOLD; - uint8_t calibration = 0; -} TOUCH_BUTTON; -#endif - - - -void ButtonPullupFlag(uint8 button_bit) -{ - bitSet(Button.no_pullup_mask, button_bit); -} - -void ButtonInvertFlag(uint8 button_bit) -{ - bitSet(Button.inverted_mask, button_bit); -} -#ifdef ESP32 -void ButtonTouchFlag(uint8 button_bit) -{ - bitSet(Button.touch_mask, button_bit); -} -#endif -void ButtonInit(void) -{ - Button.present = 0; -#ifdef ESP8266 - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - Button.present++; - } -#endif - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if (PinUsed(GPIO_KEY1, i)) { - Button.present++; -#ifdef ESP8266 - pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_KEY1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); -#else - pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : INPUT_PULLUP); -#endif - } -#ifdef USE_ADC - else if (PinUsed(GPIO_ADC_BUTTON, i) || PinUsed(GPIO_ADC_BUTTON_INV, i)) { - Button.present++; - } -#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; -} -# 136 "/workspace/Tasmota/tasmota/support_button.ino" -void ButtonHandler(void) -{ - if (uptime < 4) { return; } - - 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++) { - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; - -#ifdef ESP8266 - 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 -#endif - if (PinUsed(GPIO_KEY1, button_index)) { - button_present = 1; -#ifdef ESP32 - if (bitRead(Button.touch_mask, button_index)) { - uint32_t _value = touchRead(Pin(GPIO_KEY1, button_index)); - button = NOT_PRESSED; - if (_value != 0) { - if (_value < TOUCH_BUTTON.pin_threshold) { - if (++Button.touch_hits[button_index] > TOUCH_BUTTON.hit_threshold) { - if (!bitRead(TOUCH_BUTTON.calibration, button_index+1)) { - button = PRESSED; - } - } - } else { - Button.touch_hits[button_index] = 0; - } - } else { - Button.touch_hits[button_index] = 0; - } - if (bitRead(TOUCH_BUTTON.calibration, button_index+1)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("PLOT: %u, %u, %u,"), button_index+1, _value, Button.touch_hits[button_index]); - } - } else -#endif - { - button = (digitalRead(Pin(GPIO_KEY1, button_index)) != bitRead(Button.inverted_mask, button_index)); - } - } -#ifdef USE_ADC - else if (PinUsed(GPIO_ADC_BUTTON, button_index)) { - button_present = 1; - button = AdcGetButton(Pin(GPIO_ADC_BUTTON, button_index)); - } - else if (PinUsed(GPIO_ADC_BUTTON_INV, button_index)) { - button_present = 1; - button = AdcGetButton(Pin(GPIO_ADC_BUTTON_INV, button_index)); - } -#endif - if (button_present) { - XdrvMailbox.index = button_index; - XdrvMailbox.payload = button; - if (XdrvCall(FUNC_BUTTON_PRESSED)) { - - } -#ifdef ESP8266 - 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 (!Settings.flag3.mqtt_buttons) { - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } else { - MqttButtonTopic(button_index +1, 1, 0); - } - } - } -#endif - else { - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - - if (Settings.flag.button_single) { - if (!Settings.flag3.mqtt_buttons) { - 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 { - MqttButtonTopic(button_index +1, 1, 0); - } - } 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 (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - if (Settings.flag3.mqtt_buttons) { - MqttButtonTopic(button_index +1, 3, 1); - } else { - SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); - } - } else { - if (!Settings.flag.button_restrict) { - 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] < 7)) { - - bool single_press = false; - if (Button.press_counter[button_index] < 3) { -#ifdef ESP8266 - if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - single_press = true; - } else -#endif - { - 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; - } - } - } - } -#ifdef ROTARY_V1 - if (!RotaryButtonPressed(button_index)) { -#endif - if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { - - } else { - if (Button.press_counter[button_index] < 6) { - if (WifiState() > WIFI_RESTART) { - restart_flag = 1; - } - if (!Settings.flag3.mqtt_buttons) { - if (Button.press_counter[button_index] == 1) { - ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); - } else { - SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); - if (0 == button_index) { - bool valid_relay = PinUsed(GPIO_REL1, Button.press_counter[button_index]-1); -#ifdef ESP8266 - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - valid_relay = (Button.press_counter[button_index] <= devices_present); - } -#endif - if ((Button.press_counter[button_index] > 1) && valid_relay && (Button.press_counter[button_index] <= MAX_RELAY_BUTTON1)) { - ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); - - } - } - } - } - - } else { - if (!Settings.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - if (Settings.flag3.mqtt_buttons) { - if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) { - MqttButtonTopic(button_index +1, Button.press_counter[button_index], 0); - } - } - } -#ifdef ROTARY_V1 - } -#endif - Button.press_counter[button_index] = 0; - } - } - } - - } - } - Button.last_state[button_index] = button; - } -} - -void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) -{ - char scommand[CMDSZ]; - char stopic[TOPSZ]; - char mqttstate[7]; - - SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); - - if (!Settings.flag.hass_discovery) { - GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); - snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); - MqttPublish(stopic); - } -} - -void ButtonLoop(void) -{ - if (Button.present) { - if (TimeReached(Button.debounce)) { - SetNextTimeInterval(Button.debounce, Settings.button_debounce); - ButtonHandler(); - } - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_command.ino" -# 20 "/workspace/Tasmota/tasmota/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_SO "|" 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_SERIALCONFIG "|" - 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_DEVICENAME "|" 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 "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|" - D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_WIFI "|" -#ifdef USE_I2C - D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" -#endif -#ifdef USE_DEVICE_GROUPS - D_CMND_DEVGROUP_NAME "|" -#ifdef USE_DEVICE_GROUPS_SEND - D_CMND_DEVGROUP_SEND "|" -#endif - D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" -#endif - D_CMND_SENSOR "|" D_CMND_DRIVER -#ifdef ESP32 - "|" D_CMND_TOUCH_CAL "|" D_CMND_TOUCH_THRES "|" D_CMND_TOUCH_NUM "|" D_CMND_CPU_FREQUENCY -#endif - ; - -void (* const TasmotaCommand[])(void) PROGMEM = { - &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, - &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, - &CmndSetoption, &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, &CmndSerialConfig, - &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, - &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, - &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode, - &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndWifi, -#ifdef USE_I2C - &CmndI2cScan, CmndI2cDriver, -#endif -#ifdef USE_DEVICE_GROUPS - &CmndDevGroupName, -#ifdef USE_DEVICE_GROUPS_SEND - &CmndDevGroupSend, -#endif - &CmndDevGroupShare, &CmndDevGroupStatus, -#endif - &CmndSensor, &CmndDriver -#ifdef ESP32 - ,&CmndTouchCal, &CmndTouchThres, &CmndTouchNum, &CmndCpuFrequency -#endif - }; - -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) -{ - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndFloat(float value, uint32_t decimals) -{ - char stemp1[TOPSZ]; - dtostrfd(value, decimals, stemp1); - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); -} - -void ResponseCmndIdxNumber(int value) -{ - Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndChar_P(const char* value) -{ - Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndChar(const char* value) -{ - Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, EscapeJSONString(value).c_str()); -} - -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, EscapeJSONString(value).c_str()); -} - -void ResponseCmndAll(uint32_t text_index, uint32_t count) -{ - uint32_t real_index = text_index; - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < count; i++) { - if ((SET_MQTT_GRP_TOPIC == text_index) && (1 == i)) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, EscapeJSONString(SettingsText(real_index +i)).c_str()); - } - ResponseJsonEnd(); -} - - - -void ExecuteCommand(const char *cmnd, uint32_t source) -{ - - - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("ExecuteCommand")); -#endif - ShowSource(source); - - const char *pos = cmnd; - while (*pos && isspace(*pos)) { - pos++; - } - - const char *start = pos; - - while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { - if ('/' == *pos) { - start = pos + 1; - } - pos++; - } - if ('\0' == *start || pos <= start) { - return; - } - - uint32_t size = pos - start; - char stopic[size + 2]; - stopic[0] = '/'; - memcpy(stopic+1, start, size); - stopic[size+1] = '\0'; - - char svalue[strlen(pos) +1]; - strlcpy(svalue, pos, sizeof(svalue)); - CommandHandler(stopic, svalue, strlen(svalue)); -} -# 179 "/workspace/Tasmota/tasmota/support_command.ino" -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("CommandHandler")); -#endif - - while (*dataBuf && isspace(*dataBuf)) { - dataBuf++; - data_len--; - } - - bool grpflg = false; - uint32_t real_index = SET_MQTT_GRP_TOPIC; - for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { - if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - char *group_topic = SettingsText(real_index +i); - if (*group_topic && strstr(topicBuf, group_topic) != nullptr) { - grpflg = true; - break; - } - } - - char stemp1[TOPSZ]; - GetFallbackTopic_P(stemp1, ""); - fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); - - char *type = strrchr(topicBuf, '/'); - - uint32_t index = 1; - bool user_index = false; - if (type != nullptr) { - type++; - uint32_t i; - int nLen; - char *s = type; - for (nLen = 0; *s; s++, nLen++) { - *s=toupper(*s); - } - i = nLen; - if (i > 0) { - while (isdigit(type[i-1])) { - i--; - } - } - if (i < nLen) { - index = atoi(type + i); - user_index = true; - } - type[i] = '\0'; - } - - 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 "\"}")); - - 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() + Settings.param[P_BACKLOG_DELAY]; - - char command[CMDSZ] = { 0 }; - 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; - -#ifdef USE_SCRIPT_SUB_COMMAND - - if (!Script_SubCmd()) { - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } - } -#else - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } -#endif - - } - - if (type == nullptr) { - blinks = 201; - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); - type = (char*)stemp1; - } - - if (mqtt_data[0] != '\0') { -# 303 "/workspace/Tasmota/tasmota/support_command.ino" - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, type); - } - 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] = blcommand; - backlog_index++; - if (backlog_index >= MAX_BACKLOG) backlog_index = 0; -#endif - } - blcommand = strtok(nullptr, ";"); - } - - mqtt_data[0] = '\0'; - backlog_delay = 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 / 100)) && (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); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - mqtt_data[0] = '\0'; - } -} - -void CmndStatus(void) -{ - uint32_t payload = XdrvMailbox.payload; - - if (payload > MAX_STATUS) { return; } - if (!Settings.flag.mqtt_enabled && (6 == payload)) { return; } - if (!energy_flg && (9 == payload)) { return; } - if (!CrashFlag() && (12 == payload)) { return; } - if (!Settings.flag3.shutter_mode && (13 == payload)) { return; } - - char stemp[200]; - char stemp2[TOPSZ]; - - if (0 == 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 ? "," : ""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); - } - 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_DEVICENAME "\":\"%s\",\"" 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(), EscapeJSONString(SettingsText(SET_DEVICENAME)).c_str(), stemp, mqtt_topic, - SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, - Settings.ledmask, Settings.save_data, - Settings.flag.save_state, - SettingsText(SET_MQTT_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(STAT, PSTR(D_CMND_STATUS)); - } - - if ((0 == payload) || (1 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" 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,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d" -#ifdef ESP8266 - ",\"" D_JSON_SAVEADDRESS "\":\"%X\"" -#endif - "}}"), - baudrate, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), - GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, - Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag -#ifdef ESP8266 - , GetSettingsAddress() -#endif - ); - MqttPublishPrefixTopic_P(STAT, 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\"" -#ifdef ESP8266 - ",\"" D_JSON_BOOTVERSION "\":%d" -#endif - ",\"" D_JSON_COREVERSION "\":\"" ARDUINO_CORE_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"CpuFrequency\":%d,\"Hardware\":\"%s\"" - "%s}}"), - my_version, my_image, GetBuildDateAndTime().c_str() -#ifdef ESP8266 - , ESP.getBootVersion() -#endif - , ESP.getSdkVersion(), - ESP.getCpuFreqMHz(), GetDeviceHardware().c_str(), - GetStatistics().c_str()); - MqttPublishPrefixTopic_P(STAT, 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_MQTTLOG "\":%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\",\"%08X\",\"%08X\"]}}"), - Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, - SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings.tele_period, - Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), - Settings.flag3.data, Settings.flag4.data, Settings.flag5.data); - MqttPublishPrefixTopic_P(STAT, 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,\"" -#ifdef ESP32 - D_JSON_PSRMAXMEMORY "\":%d,\"" D_JSON_PSRFREEMEMORY "\":%d,\"" -#endif - D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d" -#ifdef ESP8266 - ",\"" D_JSON_FLASHCHIPID "\":\"%06X\"" -#endif - ",\"FlashFrequency\":%d,\"" D_JSON_FLASHMODE "\":%d,\"" - D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), - ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP_getFreeHeap()/1024, -#ifdef ESP32 - ESP.getPsramSize()/1024, ESP.getFreePsram()/1024, -#endif - ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024 -#ifdef ESP8266 - , ESP.getFlashChipId() -#endif - , ESP.getFlashChipSpeed()/1000000, ESP.getFlashChipMode(), - LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6, feature7); - XsnsDriverState(); - ResponseAppend_P(PSTR(",\"Sensors\":")); - XsnsSensorState(); - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(STAT, 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,\"" D_CMND_WIFIPOWER "\":%s}}"), - NetworkHostname(), NetworkAddress().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(), NetworkMacAddress().c_str(), - Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "5")); - } - - if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { - 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}}"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, EscapeJSONString(SettingsText(SET_MQTT_CLIENT)).c_str(), - mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); - MqttPublishPrefixTopic_P(STAT, 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\"}}"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), - GetDateAndTime(DT_STD).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}}"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), - GetDateAndTime(DT_STD).c_str(), stemp); -#endif - MqttPublishPrefixTopic_P(STAT, 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,%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[0], Settings.energy_power_delta[1], Settings.energy_power_delta[2], 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(STAT, 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(STAT, PSTR(D_CMND_STATUS "8")); - } else { - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "10")); - } - } - - if ((0 == payload) || (11 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); - MqttShowState(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "11")); - } - - if (CrashFlag()) { - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "12")); - } - } - -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - if ((0 == payload) || (13 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS13_SHUTTER "\":")); - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (0 == Settings.shutter_startrelay[i]) { break; } - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("{\"" D_STATUS13_SHUTTER "%d\":{\"Relay1\":%d,\"Relay2\":%d,\"Open\":%d,\"Close\":%d," - "\"50perc\":%d,\"Delay\":%d,\"Opt\":\"%s\"," - "\"Calib\":[%d,%d,%d,%d,%d]," - "\"Mode\":\"%d\"}}"), - i, Settings.shutter_startrelay[i], Settings.shutter_startrelay[i] +1, Settings.shutter_opentime[i], Settings.shutter_closetime[i], - Settings.shutter_set50percent[i], Settings.shutter_motordelay[i], GetBinary8(Settings.shutter_options[i], 4).c_str(), - Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], - Settings.shutter_mode); - } - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "13")); - } - } -#endif - -#ifdef USE_SCRIPT_STATUS - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); -#endif - - if (payload) { - XdrvRulesProcess(); - } - - 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 CmndTempOffset(void) -{ - if (XdrvMailbox.data_len > 0) { - int value = (int)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > -127) && (value < 127)) { - Settings.temp_comp = value; - } - } - ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1); -} - -void CmndHumOffset(void) -{ - if (XdrvMailbox.data_len > 0) { - int value = (int)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > -101) && (value < 101)) { - Settings.hum_comp = value; - } - } - ResponseCmndFloat((float)(Settings.hum_comp) / 10, 1); -} - -void CmndGlobalTemp(void) -{ - if (XdrvMailbox.data_len > 0) { - float temperature = CharToFloat(XdrvMailbox.data); - if (!isnan(temperature) && Settings.flag.temperature_conversion) { - temperature = (temperature - 32) / 1.8; - } - if ((temperature >= -50.0f) && (temperature <= 100.0f)) { - ConvertTemp(temperature); - global_update = 1; - } - } - ResponseCmndFloat(global_temperature_celsius, 1); -} - -void CmndGlobalHum(void) -{ - if (XdrvMailbox.data_len > 0) { - float humidity = CharToFloat(XdrvMailbox.data); - if ((humidity >= 0.0) && (humidity <= 100.0)) { - ConvertHumidity(humidity); - global_update = 1; - } - } - ResponseCmndFloat(global_humidity, 1); -} - -void CmndSleep(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { - Settings.sleep = XdrvMailbox.payload; - ssleep = XdrvMailbox.payload; - WiFiSetSleepMode(); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, ssleep); - -} - -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) { - SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? PSTR(OTA_URL) : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_OTAURL)); -} - -void CmndSeriallog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - 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 2: - restart_flag = 2; - restart_halt = true; - ResponseCmndChar(D_JSON_HALTING); - break; - case -1: - CmndCrash(); - break; - case -2: - CmndWDT(); - break; - case -3: - CmndBlockedLoop(); - break; - case 99: - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - break; - default: - ResponseCmndChar_P(PSTR(D_JSON_ONE_TO_RESTART)); - } -} - -void CmndPowerOnState(void) -{ -#ifdef ESP8266 - if (my_module_type != MOTOR) -#endif - { - - - - - - - - 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)) { - uint32_t items = 1; - if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { - items = MAX_PULSETIMERS; - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; - SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); - } - } - 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, index, - Settings.pulse_timer[index -1], GetPulseTimer(index -1)); - } - ResponseJsonEnd(); - } -} - -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) -{ - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR(D_CMND_SETOPTION)); - - if (XdrvMailbox.index < 146) { - uint32_t ptype; - uint32_t pindex; - if (XdrvMailbox.index <= 31) { - ptype = 2; - pindex = XdrvMailbox.index; - } - else if (XdrvMailbox.index <= 49) { - ptype = 1; - pindex = XdrvMailbox.index -32; - } - else if (XdrvMailbox.index <= 81) { - ptype = 3; - pindex = XdrvMailbox.index -50; - } - else if (XdrvMailbox.index <= 113) { - ptype = 4; - pindex = XdrvMailbox.index -82; - } - else { - ptype = 5; - pindex = XdrvMailbox.index -114; - } - - if (XdrvMailbox.payload >= 0) { - if (1 == ptype) { - 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; -#ifdef USE_LIGHT - if (P_RGB_REMAP == pindex) { - LightUpdateColorMapping(); - restart_flag = 2; - } -#endif -#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) - if (P_IR_UNKNOW_THRESHOLD == pindex) { - IrReceiveUpdateThreshold(); - } -#endif - } else { - ptype = 99; - } - } else { - if (XdrvMailbox.payload <= 1) { - if (2 == ptype) { - 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 (3 == ptype) { - bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - switch (pindex) { - case 5: - if (0 == XdrvMailbox.payload) { - restart_flag = 2; - } - break; - case 10: - WiFiSetSleepMode(); - break; - case 18: - case 25: - restart_flag = 2; - break; - } - } - else if (4 == ptype) { - bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); - switch (pindex) { - case 3: - case 6: - case 15: - case 20: - case 21: - case 22: - case 24: - case 25: - restart_flag = 2; - break; - } - } - else if (5 == ptype) { - bitWrite(Settings.flag5.data, pindex, XdrvMailbox.payload); - } - } else { - ptype = 99; - } - } - } - - if (ptype < 99) { - if (1 == ptype) { - ResponseCmndIdxNumber(Settings.param[pindex]); - } else { - uint32_t flag = Settings.flag.data; - if (3 == ptype) { - flag = Settings.flag3.data; - } - else if (4 == ptype) { - flag = Settings.flag4.data; - } - else if (5 == ptype) { - flag = Settings.flag5.data; - } - ResponseCmndIdxChar(GetStateText(bitRead(flag, 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 CmndSpeedUnit(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { - Settings.flag2.speed_conversion = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.speed_conversion); -} - -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) { - if (XdrvMailbox.index == 2) { - Settings.fallback_module = XdrvMailbox.payload; - } else { - Settings.last_module = Settings.module; - Settings.module = XdrvMailbox.payload; - SetModuleType(); - if (Settings.last_module != XdrvMailbox.payload) { - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - restart_flag = 2; - } - } - } - uint8_t module_real = Settings.module; - uint8_t module_number = ModuleNr(); - if (XdrvMailbox.index == 2) { - module_real = Settings.fallback_module; - module_number = (USER_MODULE == Settings.fallback_module) ? 0 : Settings.fallback_module +1; - strcat(XdrvMailbox.command, "2"); - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, module_number, AnyModuleName(module_real).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, XdrvMailbox.command); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndGpio(void) -{ - if (XdrvMailbox.index < ARRAY_SIZE(Settings.my_gp.io)) { - myio cmodule; - ModuleGpios(&cmodule); - if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) { - bool present = false; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { - uint32_t midx = pgm_read_word(kGpioNiceList + i); - if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < midx)) { - present = true; - break; - } - } - if (present) { - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { - if (ValidGPIO(i, cmodule.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) { - if (jsflg) { ResponseAppend_P(PSTR(",")); } - jsflg = true; - uint32_t sensor_type = Settings.my_gp.io[i]; - if (!ValidGPIO(i, cmodule.io[i])) { - sensor_type = cmodule.io[i]; - if (AGPIO(GPIO_USER) == sensor_type) { - sensor_type = GPIO_NONE; - } - } - char sindex[4] = { 0 }; - uint32_t sensor_name_idx = BGPIO(sensor_type); - uint32_t nice_list_search = sensor_type & 0xFFE0; - for (uint32_t j = 0; j < ARRAY_SIZE(kGpioNiceList); j++) { - uint32_t nls_idx = pgm_read_word(kGpioNiceList + j); - if (((nls_idx & 0xFFE0) == nice_list_search) && ((nls_idx & 0x001F) > 0)) { - snprintf_P(sindex, sizeof(sindex), PSTR("%d"), (sensor_type & 0x001F) +1); - break; - } - } - const char *sensor_names = kSensorNames; - if (sensor_name_idx > GPIO_FIX_START) { - sensor_name_idx = sensor_name_idx - GPIO_FIX_START -1; - sensor_names = kSensorNamesFixed; - } - char stemp1[TOPSZ]; - ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s%s\"}"), - i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex); - } - } - if (jsflg) { - ResponseJsonEnd(); - } else { - ResponseCmndChar(D_JSON_NOT_SUPPORTED); - } - } -} - -void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines) { - myio cmodule; - ModuleGpios(&cmodule); - bool jsflg = false; - for (uint32_t i = offset; i < size; i++) { - uint32_t ridx = pgm_read_word(NiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - 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\""), ridx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == size -1)) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); - jsflg = false; - lines++; - } - } -} - -void CmndGpios(void) -{ - - - - - - - uint32_t lines = 1; - ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines); -#ifdef ESP8266 -#ifndef USE_ADC_VCC - ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines); -#endif -#endif - 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); - } - SettingsUpdateText(SET_TEMPLATE_NAME, "Merged"); - uint32_t j = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); 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_P(PSTR(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) && PinUsed(GPIO_PWM1, XdrvMailbox.index -1)) { - 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))) { - uint32_t pwm_range = XdrvMailbox.payload; - uint32_t pwm_resolution = 0; - while (pwm_range) { - pwm_resolution++; - pwm_range >>= 1; - } - pwm_range = (1 << pwm_resolution) - 1; - uint32_t old_pwm_range = Settings.pwm_range; - Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : pwm_range; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (Settings.pwm_value[i] > Settings.pwm_range) { - Settings.pwm_value[i] = Settings.pwm_range; - } - } - if (Settings.pwm_range != old_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 < 1010)) { - 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(baudrate); -} - -void CmndSerialConfig(void) -{ - - - - - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.data_len < 3) { - if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { - SetSerialConfig(XdrvMailbox.payload); - } - } - else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { - uint8_t serial_config = XdrvMailbox.payload -5; - - bool valid = true; - char parity = (XdrvMailbox.data[1] & 0xdf); - if ('E' == parity) { - serial_config += 0x08; - } - else if ('O' == parity) { - serial_config += 0x10; - } - else if ('N' != parity) { - valid = false; - } - - if ('2' == XdrvMailbox.data[2]) { - serial_config += 0x04; - } - else if ('1' != XdrvMailbox.data[2]) { - valid = false; - } - - if (valid) { - SetSerialConfig(serial_config); - } - } - } - ResponseCmndChar(GetSerialConfig().c_str()); -} - -void CmndSerialSend(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { - 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)); - } - else if (6 == XdrvMailbox.index) { - SerialSendDecimal(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_DEBUG_MORE)) { - 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) { - SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_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 <= MAX_NTP_SERVERS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); - } else { - uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(ntp_server, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? PSTR(NTP_SERVER1) : (2 == XdrvMailbox.index) ? PSTR(NTP_SERVER2) : PSTR(NTP_SERVER3) : XdrvMailbox.data); - SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); - - ntp_force_sync = true; - } - ResponseCmndIdxChar(SettingsText(ntp_server)); - } - } -} - -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; - } - Settings.wifi_channel = 0; - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str()); -} - -void CmndSsid(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_STASSID1, MAX_SSIDS); - } else { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - } - ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); - } - } -} - -void CmndPassword(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { - SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + 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)) { - SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_HOSTNAME)); -} - -void CmndWifiConfig(void) -{ - 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; - if (WifiState() > WIFI_RESTART) { - restart_flag = 2; - } - } - char stemp1[TOPSZ]; - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); -} - -void CmndWifi(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag4.network_wifi = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndStateText(Settings.flag4.network_wifi); -} - -void CmndDevicename(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - SettingsUpdateText(SET_DEVICENAME, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? SettingsText(SET_FRIENDLYNAME1) : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_DEVICENAME)); -} - -void CmndFriendlyname(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { - ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); - } else { - if (XdrvMailbox.data_len > 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); - } - SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); - } - ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + 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); - } - } -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - ShutterInit(); - } -#endif - } - 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 = APP_INTERLOCK_MODE; - 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; - ResponseCmndNumber(Settings.tele_period); -} - -void CmndReset(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 211; - ResponseCmndChar(PSTR(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; - Settings.bootcount_reset_time = 0; - ResponseCmndDone(); - break; - default: - ResponseCmndChar(PSTR(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 < 5)) { - 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 (!PinUsed(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 (!PinUsed(GPIO_LEDLNK)) { - SetLedPower(Settings.ledstate &8); - } else { - SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); - } - } - bool state = bitRead(led_power, XdrvMailbox.index -1); - if (!PinUsed(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) { -#ifdef USE_PWM_DIMMER - PWMDimmerSetBrightnessLeds(0); -#endif - Settings.ledmask = XdrvMailbox.payload; -#ifdef USE_PWM_DIMMER - PWMDimmerSetBrightnessLeds(-1); -#endif - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); - ResponseCmndChar(stemp1); -} - -void CmndLedPwmOff(void) { - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload < 0) { - Settings.ledpwm_off = 0; - } - else if (XdrvMailbox.payload > 255) { - Settings.ledpwm_off = 255; - } else { - Settings.ledpwm_off = XdrvMailbox.payload; - } - UpdateLedPowerAll(); - } - ResponseCmndNumber(Settings.ledpwm_off); -} - -void CmndLedPwmOn(void) { - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload < 0) { - Settings.ledpwm_on = 0; - } - else if (XdrvMailbox.payload > 255) { - Settings.ledpwm_on = 255; - } else { - Settings.ledpwm_on = XdrvMailbox.payload; - } - UpdateLedPowerAll(); - } - ResponseCmndNumber(Settings.ledpwm_on); -} - -void CmndLedPwmMode(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { - if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - uint32_t mask = 1 << (XdrvMailbox.index -1); - switch (XdrvMailbox.payload) { - case 0: - Settings.ledpwm_mask &= (0xFF ^ mask); - break; - case 1: - Settings.ledpwm_mask |= mask; - break; - case 2: - Settings.ledpwm_mask ^= mask; - break; - } - UpdateLedPowerAll(); - } - bool state = bitRead(Settings.ledpwm_mask, XdrvMailbox.index -1); - ResponseCmndIdxChar(GetStateText(state)); - } -} - -void CmndWifiPower(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.wifi_output_power = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - if (Settings.wifi_output_power > 205) { - Settings.wifi_output_power = 205; - } - WifiSetOutputPower(); - } - ResponseCmndChar(WifiGetOutputPower().c_str()); -} - -#ifdef USE_I2C -void CmndI2cScan(void) -{ - if (i2c_flg) { - I2cScan(mqtt_data, sizeof(mqtt_data)); - } -} - -void CmndI2cDriver(void) -{ - if (XdrvMailbox.index < MAX_I2C_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); - I2cDriverState(); - ResponseJsonEnd(); -} -#endif - -#ifdef USE_DEVICE_GROUPS -void CmndDevGroupName(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DEV_GROUP_NAMES)) { - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.data_len > TOPSZ) - XdrvMailbox.data[TOPSZ - 1] = 0; - else if (1 == XdrvMailbox.data_len && ('"' == XdrvMailbox.data[0] || '0' == XdrvMailbox.data[0])) - XdrvMailbox.data[0] = 0; - SettingsUpdateText(SET_DEV_GROUP_NAME1 + XdrvMailbox.index - 1, XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndAll(SET_DEV_GROUP_NAME1, MAX_DEV_GROUP_NAMES); - } -} - -#ifdef USE_DEVICE_GROUPS_SEND -void CmndDevGroupSend(void) -{ - uint8_t device_group_index = (XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0); - if (device_group_index < device_group_count) { - if (!_SendDeviceGroupMessage(device_group_index, (DevGroupMessageType)(DGR_MSGTYPE_UPDATE_COMMAND + DGR_MSGTYPFLAG_WITH_LOCAL))) { - ResponseCmndChar(XdrvMailbox.data); - } - } -} -#endif - -void CmndDevGroupShare(void) -{ - uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out }; - ParseParameters(2, parm); - Settings.device_group_share_in = parm[0]; - Settings.device_group_share_out = parm[1]; - Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":\"%X\",\"Out\":\"%X\"}}"), Settings.device_group_share_in, Settings.device_group_share_out); -} - -void CmndDevGroupStatus(void) -{ - DeviceGroupStatus((XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0)); -} -#endif - -void CmndSensor(void) -{ - XsnsCall(FUNC_COMMAND_SENSOR); -} - -void CmndDriver(void) -{ - XdrvCall(FUNC_COMMAND_DRIVER); -} - -#ifdef ESP32 - -void CmndCpuFrequency(void) { - if ((80 == XdrvMailbox.payload) || (160 == XdrvMailbox.payload) || (240 == XdrvMailbox.payload)) { - setCpuFrequencyMhz(XdrvMailbox.payload); - } - ResponseCmndNumber(getCpuFrequencyMhz()); -} - -void CmndTouchCal(void) -{ - if (XdrvMailbox.payload >= 0) { - if (XdrvMailbox.payload < MAX_KEYS + 1) TOUCH_BUTTON.calibration = bitSet(TOUCH_BUTTON.calibration, XdrvMailbox.payload); - if (XdrvMailbox.payload == 0) TOUCH_BUTTON.calibration = 0; - if (XdrvMailbox.payload == 255) TOUCH_BUTTON.calibration = 255; - } - Response_P(PSTR("{\"" D_CMND_TOUCH_CAL "\": %u"), TOUCH_BUTTON.calibration); - ResponseJsonEnd(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Button Touchvalue Hits,")); -} - -void CmndTouchThres(void) -{ - if (XdrvMailbox.payload >= 0) { - if (XdrvMailbox.payload<256){ - TOUCH_BUTTON.pin_threshold = XdrvMailbox.payload; - } - } - Response_P(PSTR("{\"" D_CMND_TOUCH_THRES "\": %u"), TOUCH_BUTTON.pin_threshold); - ResponseJsonEnd(); -} - -void CmndTouchNum(void) -{ - if (XdrvMailbox.payload >= 0) { - if (XdrvMailbox.payload<32){ - TOUCH_BUTTON.hit_threshold = XdrvMailbox.payload; - } - } - Response_P(PSTR("{\"" D_CMND_TOUCH_NUM "\": %u"), TOUCH_BUTTON.hit_threshold); - ResponseJsonEnd(); - -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_cores.ino" -# 26 "/workspace/Tasmota/tasmota/support_cores.ino" -void resetPins() -{ -# 37 "/workspace/Tasmota/tasmota/support_cores.ino" -} - - - - - -#ifdef ESP8266 - -void HwWdtDisable(void) { - *((volatile uint32_t*) 0x60000900) &= ~(1); -} - -void HwWdtEnable(void) { - *((volatile uint32_t*) 0x60000900) |= 1; -} - -void WdtDisable(void) { - ESP.wdtDisable(); - HwWdtDisable(); -} - -void WdtEnable(void) { - HwWdtEnable(); - ESP.wdtEnable(0); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_crash_recorder.ino" -# 20 "/workspace/Tasmota/tasmota/support_crash_recorder.ino" -#ifdef ESP8266 - -const uint32_t crash_magic = 0x53415400; -const uint32_t crash_rtc_offset = 32; -const uint32_t crash_dump_max_len = 31; - - - - - - -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) -{ - uint32_t addr_written = 0; - uint32_t value; - - for (uint32_t i = stack; i < stack_end; i += 4) { - value = *((uint32_t*) i); - if ((value >= 0x40000000) && (value < 0x40300000)) { - ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); - addr_written++; - if (addr_written >= crash_dump_max_len) { break; } - } - } - value = crash_magic + addr_written; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - -void CmndCrash(void) -{ - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); -} - - -void CmndWDT(void) -{ - volatile uint32_t dummy = 0; - while (1) { - dummy++; - } -} - - -void CmndBlockedLoop(void) -{ - while (1) { - delay(1000); - } -} - - -void CrashDumpClear(void) -{ - uint32_t value = 0; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - - - - -bool CrashFlag(void) -{ - return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); -} - -void CrashDump(void) -{ - ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), - resetInfo.exccause, - GetResetReason().c_str(), - resetInfo.epc1, - resetInfo.epc2, - resetInfo.epc3, - resetInfo.excvaddr, - resetInfo.depc); - - uint32_t value; - ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); - if (crash_magic == (value & 0xFFFFFF00)) { - ResponseAppend_P(PSTR(",\"CallChain\":[")); - uint32_t count = value & 0x3F; - for (uint32_t i = 0; i < count; i++) { - ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_device_groups.ino" -# 24 "/workspace/Tasmota/tasmota/support_device_groups.ino" -#ifdef USE_DEVICE_GROUPS - - -#define DGR_MEMBER_TIMEOUT 45000 -#define DGR_ANNOUNCEMENT_INTERVAL 60000 -#define DEVICE_GROUP_MESSAGE "TASMOTA_DGR" - -const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE; - -struct device_group_member { - struct device_group_member * flink; - IPAddress ip_address; - uint16_t received_sequence; - uint16_t acked_sequence; - uint32_t unicast_count; -}; - -struct device_group { - uint32_t next_announcement_time; - uint32_t next_ack_check_time; - uint32_t member_timeout_time; - uint16_t outgoing_sequence; - uint16_t last_full_status_sequence; - uint16_t message_length; - uint16_t ack_check_interval; - uint8_t message_header_length; - uint8_t initial_status_requests_remaining; - char group_name[TOPSZ]; - uint8_t message[128]; - struct device_group_member * device_group_members; -#ifdef USE_DEVICE_GROUPS_SEND - uint8_t values_8bit[DGR_ITEM_LAST_8BIT]; - uint16_t values_16bit[DGR_ITEM_LAST_16BIT - DGR_ITEM_MAX_8BIT - 1]; - uint32_t values_32bit[DGR_ITEM_LAST_32BIT - DGR_ITEM_MAX_16BIT - 1]; -#endif -}; - -WiFiUDP device_groups_udp; -struct device_group * device_groups; -uint32_t next_check_time; -bool device_groups_initialized = false; -bool device_groups_up = false; -bool building_status_message = false; -bool ignore_dgr_sends = false; - -char * IPAddressToString(const IPAddress& ip_address) -{ - static char buffer[16]; - sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); - return buffer; -} - -uint8_t * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t flags, bool hold_sequence = false) -{ - uint8_t * message_ptr = &device_group->message[device_group->message_header_length]; - if (!hold_sequence && !++device_group->outgoing_sequence) device_group->outgoing_sequence = 1; - *message_ptr++ = device_group->outgoing_sequence & 0xff; - *message_ptr++ = device_group->outgoing_sequence >> 8; - *message_ptr++ = flags & 0xff; - *message_ptr++ = flags >> 8; - return message_ptr; -} - - -bool DeviceGroupItemShared(bool incoming, uint8_t item) -{ - uint32_t mask; - if (item == DGR_ITEM_LIGHT_BRI || item == DGR_ITEM_BRI_POWER_ON) - mask = DGR_SHARE_LIGHT_BRI; - else if (item == DGR_ITEM_POWER) - mask = DGR_SHARE_POWER; - else if (item == DGR_ITEM_LIGHT_SCHEME) - mask = DGR_SHARE_LIGHT_SCHEME; - else if (item == DGR_ITEM_LIGHT_FIXED_COLOR || DGR_ITEM_LIGHT_CHANNELS) - mask = DGR_SHARE_LIGHT_COLOR; - else if (item == DGR_ITEM_LIGHT_FADE || item == DGR_ITEM_LIGHT_SPEED) - mask = DGR_SHARE_LIGHT_FADE; - else if (item == DGR_ITEM_BRI_PRESET_LOW || item == DGR_ITEM_BRI_PRESET_HIGH) - mask = DGR_SHARE_DIMMER_SETTINGS; - else if (item == DGR_ITEM_EVENT) - mask = DGR_SHARE_EVENT; - else - return true; - return mask & (incoming ? Settings.device_group_share_in : Settings.device_group_share_out); -} - -void DeviceGroupsInit(void) -{ - - if (!device_group_count) { - - - - if (Settings.flag4.multiple_device_groups) { - for (uint32_t relay_index = 0; relay_index < MAX_RELAYS; relay_index++) { - if (PinUsed(GPIO_REL1, relay_index)) device_group_count = relay_index + 1; - } - if (device_group_count > MAX_DEV_GROUP_NAMES) device_group_count = MAX_DEV_GROUP_NAMES; - } - - - else { - device_group_count = 1; - } - } - - - - for (; device_group_count < MAX_DEV_GROUP_NAMES; device_group_count++) { - if (!*SettingsText(SET_DEV_GROUP_NAME1 + device_group_count)) break; - } - - - device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); - if (!device_groups) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating %u-element array"), device_group_count); - return; - } - - struct device_group * device_group = device_groups; - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { - strcpy(device_group->group_name, SettingsText(SET_DEV_GROUP_NAME1 + device_group_index)); - - - - if (!device_group->group_name[0]) { - strcpy(device_group->group_name, SettingsText(SET_MQTT_GRP_TOPIC)); - if (device_group_index) { - snprintf_P(device_group->group_name, sizeof(device_group->group_name), PSTR("%s%u"), device_group->group_name, device_group_index + 1); - } - } - device_group->message_header_length = sprintf_P((char *)device_group->message, PSTR("%s%s"), kDeviceGroupMessage, device_group->group_name) + 1; - device_group->last_full_status_sequence = -1; - } - - - if (!Settings.device_group_share_in && !Settings.device_group_share_out) { - Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; - } - - device_groups_initialized = true; -} - -void DeviceGroupsStart() -{ - if (Settings.flag4.device_groups_enabled && !device_groups_up && !restart_flag) { - - - if (!device_groups_initialized) { - DeviceGroupsInit(); - if (!device_groups_initialized) return; - } - - - if (!device_groups_udp.beginMulticast(WiFi.localIP(), IPAddress(DEVICE_GROUPS_ADDRESS), DEVICE_GROUPS_PORT)) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error subscribing")); - return; - } - device_groups_up = true; - - - - - next_check_time = millis() + 2000; - struct device_group * device_group = device_groups; - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { - device_group->next_announcement_time = -1; - device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message; - device_group->initial_status_requests_remaining = 10; - device_group->next_ack_check_time = next_check_time; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering members")); - } -} - -void DeviceGroupsStop() -{ - device_groups_udp.flush(); - device_groups_up = false; -} - -void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received) -{ - char log_buffer[512]; - bool item_processed = false; - uint16_t message_sequence; - uint16_t flags; - int device_group_index = device_group - device_groups; - int log_length; - int log_remaining; - char * log_ptr; - - - uint8_t * message_end_ptr = message + message_length; - uint8_t * message_ptr = message + strlen((char *)message) + 1; - - - if (message_ptr + 4 > message_end_ptr) goto badmsg; - message_sequence = *message_ptr++; - message_sequence |= *message_ptr++ << 8; - flags = *message_ptr++; - flags |= *message_ptr++ << 8; - - - log_length = sprintf(log_buffer, PSTR("DGR: %s %s message %s %s: seq=%u, flags=%u"), (received ? PSTR("Received") : PSTR("Sending")), device_group->group_name, (received ? PSTR("from") : PSTR("to")), (device_group_member ? IPAddressToString(device_group_member->ip_address) : received ? PSTR("local") : PSTR("network")), message_sequence, flags); - log_ptr = log_buffer + log_length; - log_remaining = sizeof(log_buffer) - log_length; - - - if (flags == DGR_FLAG_ANNOUNCEMENT) goto write_log; - - - - if (flags == DGR_FLAG_ACK) { - if (received && device_group_member && (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536)) { - device_group_member->acked_sequence = message_sequence; - } - goto write_log; - } - - - if (device_group_member) { - if (received) { - if (!(flags & DGR_FLAG_MORE_TO_COME)) { - *(message_ptr - 2) = DGR_FLAG_ACK; - *(message_ptr - 1) = 0; - SendReceiveDeviceGroupMessage(device_group, device_group_member, message, message_ptr - message, false); - } - } - - - else { - log_length = snprintf(log_ptr, log_remaining, PSTR(", last ack=%u"), device_group_member->acked_sequence); - log_ptr += log_length; - log_remaining -= log_length; - goto write_log; - } - } - - - if ((flags & DGR_FLAG_STATUS_REQUEST)) goto write_log; - - - if (received) { - - - if (device_group_member) { - if (message_sequence <= device_group_member->received_sequence) { - if (message_sequence == device_group_member->received_sequence || device_group_member->received_sequence - message_sequence > 64536) { - log_length = snprintf(log_ptr, log_remaining, PSTR(" (old)")); - log_ptr += log_length; - log_remaining -= log_length; - goto write_log; - } - } - device_group_member->received_sequence = message_sequence; - } -# 294 "/workspace/Tasmota/tasmota/support_device_groups.ino" - XdrvMailbox.command = nullptr; - XdrvMailbox.index = flags | message_sequence << 16; - if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index |= DGR_FLAG_LOCAL; - XdrvMailbox.topic = (char *)&device_group_index; - if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true; - - - - ignore_dgr_sends = true; - } - - uint8_t item; - int32_t value; - for (;;) { - if (message_ptr >= message_end_ptr) goto badmsg; - item = *message_ptr++; - if (!item) break; - -#ifdef DEVICE_GROUPS_DEBUG - switch (item) { - case DGR_ITEM_FLAGS: - case DGR_ITEM_LIGHT_FADE: - case DGR_ITEM_LIGHT_SPEED: - case DGR_ITEM_LIGHT_BRI: - case DGR_ITEM_LIGHT_SCHEME: - case DGR_ITEM_LIGHT_FIXED_COLOR: - case DGR_ITEM_BRI_PRESET_LOW: - case DGR_ITEM_BRI_PRESET_HIGH: - case DGR_ITEM_BRI_POWER_ON: - case DGR_ITEM_POWER: - case DGR_ITEM_EVENT: - case DGR_ITEM_LIGHT_CHANNELS: - break; - default: - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: *** Invalid item=%u"), item); - } -#endif - - log_length = snprintf(log_ptr, log_remaining, PSTR(", %u="), item); - log_ptr += log_length; - log_remaining -= log_length; - log_length = 0; - if (item <= DGR_ITEM_LAST_32BIT) { - value = *message_ptr++; - if (item > DGR_ITEM_MAX_8BIT) { - value |= *message_ptr++ << 8; - if (item > DGR_ITEM_MAX_16BIT) { - value |= *message_ptr++ << 16; - value |= *message_ptr++ << 24; -#ifdef USE_DEVICE_GROUPS_SEND - device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1] = (item == DGR_ITEM_POWER ? value & 0xffffff : value); -#endif - } -#ifdef USE_DEVICE_GROUPS_SEND - else { - device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] = value; - } -#endif - } -#ifdef USE_DEVICE_GROUPS_SEND - else { - device_group->values_8bit[item] = value; - } -#endif - log_length = snprintf(log_ptr, log_remaining, PSTR("%u"), value); - } - else { - value = *message_ptr++; - if (received) XdrvMailbox.data = (char *)message_ptr; - if (message_ptr + value >= message_end_ptr) goto badmsg; - if (item <= DGR_ITEM_MAX_STRING) { - log_length = snprintf(log_ptr, log_remaining, PSTR("'%s'"), message_ptr); - } - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - log_length = snprintf(log_ptr, log_remaining, PSTR("%u,%u,%u,%u,%u,%u"), *message_ptr, *(message_ptr + 1), *(message_ptr + 2), *(message_ptr + 3), *(message_ptr + 4), *(message_ptr + 5)); - break; - } - } - message_ptr += value; - } - log_ptr += log_length; - log_remaining -= log_length; - - if (received && DeviceGroupItemShared(true, item)) { - item_processed = true; - XdrvMailbox.command_code = item; - XdrvMailbox.payload = value; - XdrvMailbox.data_len = value; - *log_ptr++ = '*'; - log_remaining--; - switch (item) { - case DGR_ITEM_POWER: - if (Settings.flag4.multiple_device_groups) { - if (device_group_index < devices_present) { - bool on = (value & 1); - if (on != (power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); - } - } - else if (XdrvMailbox.index & DGR_FLAG_LOCAL) { - uint8_t mask_devices = value >> 24; - if (mask_devices > devices_present) mask_devices = devices_present; - for (uint32_t i = 0; i < mask_devices; i++) { - uint32_t mask = 1 << i; - bool on = (value & mask); - if (on != (power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); - } - } - break; -#ifdef USE_RULES - case DGR_ITEM_EVENT: - CmndEvent(); - break; -#endif - case DGR_ITEM_COMMAND: - ExecuteCommand(XdrvMailbox.data, SRC_REMOTE); - break; - } - XdrvCall(FUNC_DEVICE_GROUP_ITEM); - } - } - - if (received) { - if (item_processed) { - XdrvMailbox.command_code = DGR_ITEM_EOL; - XdrvCall(FUNC_DEVICE_GROUP_ITEM); - } - } - -write_log: - *log_ptr++ = 0; - AddLog_P(LOG_LEVEL_DEBUG_MORE, log_buffer); - - - - if (received) { - if ((flags & DGR_FLAG_STATUS_REQUEST)) { - if ((flags & DGR_FLAG_RESET) || device_group_member->acked_sequence != device_group->last_full_status_sequence) { - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); - } - } - } - - - else { - int attempt; - IPAddress ip_address = (device_group_member ? device_group_member->ip_address : IPAddress(DEVICE_GROUPS_ADDRESS)); - for (attempt = 1; attempt <= 5; attempt++) { - if (device_groups_udp.beginPacket(ip_address, DEVICE_GROUPS_PORT)) { - device_groups_udp.write(message, message_length); - if (device_groups_udp.endPacket()) break; - } - delay(10); - } - if (attempt > 5) AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending message")); - } - goto cleanup; - -badmsg: - AddLog_P(LOG_LEVEL_ERROR, PSTR("%s ** incorrect length"), log_buffer); - -cleanup: - if (received) { - skip_light_fade = false; - ignore_dgr_sends = false; - } -} - -bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...) -{ - - if (!device_groups_up) return 1; - - - if (device_group_index >= device_group_count) return 0; - - - bool with_local = ((message_type & DGR_MSGTYPFLAG_WITH_LOCAL) != 0); - message_type = (DevGroupMessageType)(message_type & 0x7F); - - - if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0; - - - struct device_group * device_group = &device_groups[device_group_index]; - - - if (device_group->initial_status_requests_remaining) return 1; - - -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Building %s %spacket"), device_group->group_name, (message_type == DGR_MSGTYP_FULL_STATUS ? PSTR("full status ") : PSTR(""))); -#endif - uint16_t original_sequence = device_group->outgoing_sequence; - uint16_t flags = 0; - if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) - flags = DGR_FLAG_MORE_TO_COME; - else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) - flags = DGR_FLAG_DIRECT; - uint8_t * message_ptr = BeginDeviceGroupMessage(device_group, flags, building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE); - - - - - if (message_type == DGR_MSGTYP_FULL_STATUS) { - device_group->last_full_status_sequence = device_group->outgoing_sequence; - device_group->message_length = 0; - - - - building_status_message = true; - - - SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); - XdrvMailbox.index = 0; - if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL; - XdrvMailbox.command_code = DGR_ITEM_STATUS; - XdrvMailbox.topic = (char *)&device_group_index; - XdrvCall(FUNC_DEVICE_GROUP_ITEM); - building_status_message = false; - - - *(message_ptr - 2) |= DGR_FLAG_FULL_STATUS; - - - if (!device_group->message_length) { - *message_ptr++ = 0; - device_group->message_length = message_ptr - device_group->message; - } - } - - else { -#ifdef USE_DEVICE_GROUPS_SEND - uint8_t out_buffer[128]; - bool escaped; - char chr; - char oper; - uint32_t old_value; - uint8_t * out_ptr = out_buffer; -#endif - struct item { - uint8_t item; - uint32_t value; - void * value_ptr; - } item_array[32]; - bool shared; - uint8_t item; - uint32_t value; - uint8_t * value_ptr; - uint8_t * first_item_ptr = message_ptr; - struct item * item_ptr; - va_list ap; - - - item_ptr = item_array; -#ifdef USE_DEVICE_GROUPS_SEND - if (message_type == DGR_MSGTYPE_UPDATE_COMMAND) { - value_ptr = (uint8_t *)XdrvMailbox.data; - while ((item = strtoul((char *)value_ptr, (char **)&value_ptr, 0))) { - item_ptr->item = item; - if (*value_ptr != '=') return 1; - value_ptr++; - if (item <= DGR_ITEM_MAX_32BIT) { - oper = 0; - if (*value_ptr == '@') { - oper = value_ptr[1]; - value_ptr += 2; - } - value = (isdigit(*value_ptr) ? strtoul((char *)value_ptr, (char **)&value_ptr, 0) : 1); - if (oper) { - old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1])); - value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value))); - } - item_ptr->value = value; - } - else { - item_ptr->value_ptr = out_ptr; - if (item <= DGR_ITEM_MAX_STRING) { - escaped = false; - while ((chr = *value_ptr++)) { - if (chr == ' ' && !escaped) break; - if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr; - } - *out_ptr = 0; - } - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - for (int i = 0; i < 6; i++) { - *out_ptr++ = strtoul((char *)value_ptr, (char **)&value_ptr, 0); - if (*value_ptr == ',') value_ptr++; - } - break; - } - } - } - item_ptr++; - } - } - else { -#endif - va_start(ap, message_type); - while ((item = va_arg(ap, int))) { - item_ptr->item = item; - if (item <= DGR_ITEM_MAX_32BIT) - item_ptr->value = va_arg(ap, int); - else if (item <= DGR_ITEM_MAX_STRING) - item_ptr->value_ptr = va_arg(ap, char *); - else { - item_ptr->value_ptr = va_arg(ap, uint8_t *); - } - item_ptr++; - } - va_end(ap); -#ifdef USE_DEVICE_GROUPS_SEND - } -#endif - item_ptr->item = 0; - - - - - - if (device_group->message_length) { - int kept_item_count = 0; - - - - uint8_t * previous_message_ptr = message_ptr; - while (item = *previous_message_ptr++) { - - - if (item <= DGR_ITEM_MAX_32BIT) { - value = 1; - if (item > DGR_ITEM_MAX_8BIT) { - value = 2; - if (item > DGR_ITEM_MAX_16BIT) { - value = 4; - } - } - } - else { - value = *previous_message_ptr + 1; - } - - - for (item_ptr = item_array; item_ptr->item; item_ptr++) { - if (item_ptr->item == item) break; - } - - - if (!item_ptr->item) { - kept_item_count++; - *message_ptr++ = item; - memmove(message_ptr, previous_message_ptr, value); - message_ptr += value; - } - - - previous_message_ptr += value; - } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: %u items carried over"), kept_item_count); -#endif - } - - - for (item_ptr = item_array; (item = item_ptr->item); item_ptr++) { - - - shared = true; - if (!device_group_index && message_type != DGR_MSGTYPE_UPDATE_COMMAND) shared = DeviceGroupItemShared(false, item); - if (shared) { - *message_ptr++ = item; - - - if (item <= DGR_ITEM_MAX_32BIT) { - value = item_ptr->value; - *message_ptr++ = value & 0xff; - if (item > DGR_ITEM_MAX_8BIT) { - value >>= 8; - *message_ptr++ = value & 0xff; - if (item > DGR_ITEM_MAX_16BIT) { - value >>= 8; - *message_ptr++ = value & 0xff; - value >>= 8; - - if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? devices_present : 1); - *message_ptr++ = value; - } - } - } - - - else { - if (item <= DGR_ITEM_MAX_STRING) { - value = strlen((const char *)item_ptr->value_ptr) + 1; - } - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - value = 6; - break; - } - } - - - *message_ptr++ = value; - memcpy(message_ptr, item_ptr->value_ptr, value); - message_ptr += value; - } - } - } - - - if (message_ptr != first_item_ptr) { - *message_ptr++ = 0; - device_group->message_length = message_ptr - device_group->message; - } - - - if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return 0; - } - - - if (!device_group->message_length) { - device_group->outgoing_sequence = original_sequence; - return 0; - } - - - SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); - -#ifdef USE_DEVICE_GROUPS_SEND - - if (with_local) { - struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox; - SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, true); - XdrvMailbox = save_XdrvMailbox; - } -#endif - - uint32_t now = millis(); - if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { - device_group->message_length = 0; - device_group->next_ack_check_time = 0; - } - else { - device_group->ack_check_interval = 200; - device_group->next_ack_check_time = now + device_group->ack_check_interval; - if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; - device_group->member_timeout_time = now + DGR_MEMBER_TIMEOUT; - } - - device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL; - if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; - return 0; -} - -void ProcessDeviceGroupMessage(uint8_t * message, int message_length) -{ - - uint8_t device_group_index = 0; - struct device_group * device_group = device_groups; - char * message_group_name = (char *)message + sizeof(DEVICE_GROUP_MESSAGE) - 1; - for (;;) { - if (!strcmp(message_group_name, device_group->group_name)) break; - if (++device_group_index >= device_group_count) return; - device_group++; - } - - - struct device_group_member * device_group_member; - IPAddress remote_ip = device_groups_udp.remoteIP(); - struct device_group_member * * flink = &device_group->device_group_members; - for (;;) { - device_group_member = *flink; - if (!device_group_member) { - device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); - if (device_group_member == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating member block")); - return; - } - device_group_member->ip_address = remote_ip; - *flink = device_group_member; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s added"), IPAddressToString(remote_ip)); - break; - } - else if (device_group_member->ip_address == remote_ip) { - break; - } - flink = &device_group_member->flink; - } - - SendReceiveDeviceGroupMessage(device_group, device_group_member, message, message_length, true); -} - -void DeviceGroupStatus(uint8_t device_group_index) -{ - if (Settings.flag4.device_groups_enabled && device_group_index < device_group_count) { - char buffer[1024]; - int member_count = 0; - struct device_group * device_group = &device_groups[device_group_index]; - buffer[0] = buffer[1] = 0; - for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member; device_group_member = device_group_member->flink) { - snprintf_P(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence); - member_count++; - } - Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}}"), device_group_index, device_group->group_name, device_group->outgoing_sequence, member_count, &buffer[1]); - } -} - -void DeviceGroupsLoop(void) -{ - if (!device_groups_up || restart_flag) return; - - while (device_groups_udp.parsePacket()) { - uint8_t packet_buffer[512]; - int length = device_groups_udp.read(packet_buffer, sizeof(packet_buffer) - 1); - if (length > 0) { - packet_buffer[length] = 0; - if (!strncmp_P((char *)packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { - ProcessDeviceGroupMessage(packet_buffer, length); - } - } - } - - uint32_t now = millis(); - - - if ((long)(now - next_check_time) >= 0) { -#ifdef DEVICE_GROUPS_DEBUG -AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking next_check_time=%u, now=%u"), next_check_time, now); -#endif - next_check_time = now + DGR_ANNOUNCEMENT_INTERVAL * 2; - - struct device_group * device_group = device_groups; - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++, device_group++) { - - - if (device_group->next_ack_check_time) { - - - if ((long)(now - device_group->next_ack_check_time) >= 0) { - - - if (device_group->initial_status_requests_remaining) { - if (--device_group->initial_status_requests_remaining) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending initial status request for group %s"), device_group->group_name); -#endif - SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); - device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; - next_check_time = device_group->next_ack_check_time = now + 200; - continue; - } - - - - else { - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); - } - } - - - else { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for ack's")); -#endif - bool acked = true; - struct device_group_member ** flink = &device_group->device_group_members; - struct device_group_member * device_group_member; - while ((device_group_member = *flink)) { - - - if (device_group_member->acked_sequence != device_group->outgoing_sequence) { - - - - if ((long)(now - device_group->member_timeout_time) >= 0) { - *flink = device_group_member->flink; - free(device_group_member); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Member %s removed"), IPAddressToString(device_group_member->ip_address)); - continue; - } - - - SendReceiveDeviceGroupMessage(device_group, device_group_member, device_group->message, device_group->message_length, false); - device_group_member->unicast_count++; - acked = false; - } - flink = &device_group_member->flink; - } - - - - if (acked) { - device_group->next_ack_check_time = 0; - device_group->message_length = 0; - } - - - - - else { - device_group->ack_check_interval *= 2; - if (device_group->ack_check_interval > 5000) device_group->ack_check_interval = 5000; - device_group->next_ack_check_time = now + device_group->ack_check_interval; - } - } - } - - if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time; - } - - - - - -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now); -#endif - if ((long)(now - device_group->next_announcement_time) >= 0) { - SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, false); - device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000); - } - if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time; - } - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_eeprom.ino" -# 26 "/workspace/Tasmota/tasmota/support_eeprom.ino" -#ifdef USE_EEPROM - -#ifdef USE_24C256 - -#include -#define EEPROM_ADDRESS 0x50 -static Eeprom24C128_256 m_eeprom(EEPROM_ADDRESS); - -void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { - m_eeprom.writeBytes(addr,len,(uint8_t*)buff); -} -void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { - m_eeprom.readBytes(addr,len,(uint8_t*)buff); -} - -uint32_t eeprom_init(uint32_t size) { - if (i2c_flg) { - if (I2cActive(EEPROM_ADDRESS) || I2cSetDevice(EEPROM_ADDRESS)) { - - I2cSetActiveFound(EEPROM_ADDRESS, "24C256"); - return 1; - } - } - return 0; -} - -#else - -#ifdef ESP32 - - -uint32_t eeprom_init(uint32_t size) { - return EEPROM.begin(size); -} -void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { - EEPROM.writeBytes(addr, buff, len); - EEPROM.commit(); -} -void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { - EEPROM.readBytes(addr, buff, len); -} - -#else - -uint32_t eeprom_init(uint32_t size) { - EEPROM.begin(size); - return 1; -} -void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) { - for (uint32_t cnt=0; cnt 100) { free_block_size -= 100; } - return free_block_size; -} - -void ESP_Restart(void) { - - ESP.reset(); -} - -#endif - - - - - -#ifdef ESP32 - - - -#include -#include - -void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) { - nvs_handle handle; - noInterrupts(); - nvs_open(sNvsName, NVS_READONLY, &handle); - size_t size = nSettingsLen; - nvs_get_blob(handle, sName, pSettings, &size); - nvs_close(handle); - interrupts(); -} - -void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) { - nvs_handle handle; - noInterrupts(); - nvs_open(sNvsName, NVS_READWRITE, &handle); - nvs_set_blob(handle, sName, pSettings, nSettingsLen); - nvs_commit(handle); - nvs_close(handle); - interrupts(); -} - -void NvmErase(const char *sNvsName) { - nvs_handle handle; - noInterrupts(); - nvs_open(sNvsName, NVS_READWRITE, &handle); - nvs_erase_all(handle); - nvs_commit(handle); - nvs_close(handle); - interrupts(); -} - -void SettingsErase(uint8_t type) { - if (1 == type) { - } else if (2 == type) { - } else if (3 == type) { - } - - NvmErase("main"); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type); -} - -void SettingsRead(void *data, size_t size) { - NvmLoad("main", "Settings", data, size); -} - -void SettingsWrite(const void *pSettings, unsigned nSettingsLen) { - NvmSave("main", "Settings", pSettings, nSettingsLen); -} - -void QPCRead(void *pSettings, unsigned nSettingsLen) { - NvmLoad("qpc", "pcreg", pSettings, nSettingsLen); -} - -void QPCWrite(const void *pSettings, unsigned nSettingsLen) { - NvmSave("qpc", "pcreg", pSettings, nSettingsLen); -} - -void ZigbeeErase(void) { - NvmErase("zb"); -} - -void ZigbeeRead(void *pSettings, unsigned nSettingsLen) { - NvmLoad("zb", "zigbee", pSettings, nSettingsLen); -} - -void ZigbeeWrite(const void *pSettings, unsigned nSettingsLen) { - NvmSave("zb", "zigbee", pSettings, nSettingsLen); -} - - - - -static bool bNetIsTimeSync = false; - -void SntpInit() { - bNetIsTimeSync = true; -} - -uint32_t SntpGetCurrentTimestamp(void) { - time_t now = 0; - if (bNetIsTimeSync || ntp_force_sync) - { - - - configTime(0, 0, SettingsText(SET_NTPSERVER1), SettingsText(SET_NTPSERVER2), SettingsText(SET_NTPSERVER3)); - bNetIsTimeSync = false; - ntp_force_sync = false; - } - time(&now); - return now; -} - - - - - -void CrashDump(void) { -} - -bool CrashFlag(void) { - return false; -} - -void CrashDumpClear(void) { -} - -void CmndCrash(void) { - - - - -} - - -void CmndWDT(void) { - - - - - - -} - -void CmndBlockedLoop(void) { - - - - - -} - - - - - -#include "soc/soc.h" -#include "soc/rtc_cntl_reg.h" - -void DisableBrownout(void) { - - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); -} - - - - - -String ESP32GetResetReason(uint32_t cpu_no) { - - switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) { - case POWERON_RESET : return F("Vbat power on reset"); - case SW_RESET : return F("Software reset digital core"); - case OWDT_RESET : return F("Legacy watch dog reset digital core"); - case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); - case SDIO_RESET : return F("Reset by SLC module, reset digital core"); - case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); - case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); - case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); - case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); - case TGWDT_CPU_RESET : return F("Time Group reset CPU"); - case SW_CPU_RESET : return F("Software reset CPU"); - case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); - case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); - case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); - case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); - default : return F("NO_MEAN"); - } -} - -String ESP_getResetReason(void) { - return ESP32GetResetReason(0); -} - -uint32_t ESP_ResetInfoReason(void) { - RESET_REASON reason = rtc_get_reset_reason(0); - if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; } - if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; } - if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; } - if (SW_RESET == reason) { return REASON_EXT_SYS_RST; } -} - -uint32_t ESP_getChipId(void) { - uint32_t id = 0; - for (uint32_t i = 0; i < 17; i = i +8) { - id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; - } - return id; -} - -uint32_t ESP_getSketchSize(void) { - static uint32_t sketchsize = 0; - - if (!sketchsize) { - sketchsize = ESP.getSketchSize(); - } - return sketchsize; -} - -uint32_t ESP_getFreeHeap(void) { - - return ESP.getMaxAllocHeap(); -} - -uint32_t ESP_getMaxAllocHeap(void) { - - uint32_t free_block_size = ESP.getMaxAllocHeap(); - if (free_block_size > 100) { free_block_size -= 100; } - return free_block_size; -} - -void ESP_Restart(void) { - ESP.restart(); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_esptool.ino" -# 20 "/workspace/Tasmota/tasmota/support_esptool.ino" -#ifdef ESP8266 -#define USE_ESPTOOL -#endif - -#ifdef USE_ESPTOOL - - - - - - - -#define READ_REG(REG) (*((volatile uint32_t *)(REG))) -#define WRITE_REG(REG,VAL) *((volatile uint32_t *)(REG)) = (VAL) -#define REG_SET_MASK(reg,mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) - -#define SPI_BASE_REG 0x60000200 - -#define SPI_CMD_REG (SPI_BASE_REG + 0x00) -#define SPI_FLASH_RDSR (1<<27) -#define SPI_FLASH_SE (1<<24) -#define SPI_FLASH_BE (1<<23) -#define SPI_FLASH_WREN (1<<30) - -#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) -#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) -#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) -#define SPI_W0_REG (SPI_BASE_REG + 0x40) -#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) - -#define SPI_ST 0x7 - - -#define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / SPI_FLASH_SEC_SIZE) - - -static const uint32_t STATUS_WIP_BIT = (1 << 0); - - -inline static void spi_wait_ready(void) -{ - while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } -} - - - -static bool spiflash_is_ready(void) -{ - spi_wait_ready(); - WRITE_REG(SPI_RD_STATUS_REG, 0); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); - while(READ_REG(SPI_CMD_REG) != 0) { } - uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); - return (status_value & STATUS_WIP_BIT) == 0; -} - -static void spi_write_enable(void) -{ - while(!spiflash_is_ready()) { } - WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); - while(READ_REG(SPI_CMD_REG) != 0) { } -} - -bool EsptoolEraseSector(uint32_t sector) -{ - spi_write_enable(); - spi_wait_ready(); - - WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); - while(READ_REG(SPI_CMD_REG) != 0) { } - while(!spiflash_is_ready()) { } - - return true; -} - -void EsptoolErase(uint32_t start_sector, uint32_t end_sector) -{ - int next_erase_sector = start_sector; - int remaining_erase_sector = end_sector - start_sector; - - while (remaining_erase_sector > 0) { - spi_write_enable(); - - uint32_t command = SPI_FLASH_SE; - uint32_t sectors_to_erase = 1; - if (remaining_erase_sector >= SECTORS_PER_BLOCK && - next_erase_sector % SECTORS_PER_BLOCK == 0) { - command = SPI_FLASH_BE; - sectors_to_erase = SECTORS_PER_BLOCK; - } - uint32_t addr = next_erase_sector * SPI_FLASH_SEC_SIZE; - - spi_wait_ready(); - WRITE_REG(SPI_ADDR_REG, addr & 0xffffff); - WRITE_REG(SPI_CMD_REG, command); - while(READ_REG(SPI_CMD_REG) != 0) { } - remaining_erase_sector -= sectors_to_erase; - next_erase_sector += sectors_to_erase; - - while (!spiflash_is_ready()) { } - yield(); - OsWatchLoop(); - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_features.ino" -# 24 "/workspace/Tasmota/tasmota/support_features.ino" -void GetFeatures(void) -{ - feature_drv1 = 0x00000000; - -#if defined(USE_ENERGY_SENSOR) && defined(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 -#if defined(USE_WEBSERVER) && defined(WEBSERVER_ADVERTISE) - feature_drv1 |= 0x00000100; -#endif -#if defined(USE_WEBSERVER) && defined(USE_EMULATION_HUE) - feature_drv1 |= 0x00000200; -#endif - - feature_drv1 |= 0x00000400; - - - - - - - -#if defined(USE_DISCOVERY) && defined(MQTT_HOST_DISCOVERY) - feature_drv1 |= 0x00002000; -#endif -#if defined(USE_LIGHT) && defined(USE_ARILUX_RF) - feature_drv1 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_WS2812) - feature_drv1 |= 0x00008000; -#endif -#if defined(USE_LIGHT) && defined(USE_WS2812) && defined(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 -#if defined(USE_IR_REMOTE) && defined(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 -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - feature_drv1 |= 0x02000000; -#endif -#if defined(USE_TIMERS) && defined(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 -#if defined(USE_ENERGY_SENSOR) && defined(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 -#if defined(USE_DISPLAY) && defined(USE_DISPLAY_MODES1TO5) - feature_drv2 |= 0x00000020; -#endif -#if defined(USE_DISPLAY) && defined(USE_DISPLAY_GRAPH) - feature_drv2 |= 0x00000040; -#endif -#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_LCD) - feature_drv2 |= 0x00000080; -#endif -#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SSD1306) - feature_drv2 |= 0x00000100; -#endif -#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_MATRIX) - feature_drv2 |= 0x00000200; -#endif -#if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_ILI9341) - feature_drv2 |= 0x00000400; -#endif -#if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_EPAPER_29) - feature_drv2 |= 0x00000800; -#endif -#if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SH1106) - feature_drv2 |= 0x00001000; -#endif -#ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; -#endif -#if defined(USE_I2C) && defined(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 -#if defined(USE_WEBSERVER) && defined(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 -#if defined(USE_ADC_VCC) || defined(USE_ADC) - feature_sns1 |= 0x00000002; -#endif -#ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(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 -#if defined(USE_I2C) && defined(USE_SHT) - feature_sns1 |= 0x00000100; -#endif -#if defined(USE_I2C) && defined(USE_HTU) - feature_sns1 |= 0x00000200; -#endif -#if defined(USE_I2C) && defined(USE_BMP) - feature_sns1 |= 0x00000400; -#endif -#if defined(USE_I2C) && defined(USE_BMP) && defined(USE_BME680) - feature_sns1 |= 0x00000800; -#endif -#if defined(USE_I2C) && defined(USE_BH1750) - feature_sns1 |= 0x00001000; -#endif -#if defined(USE_I2C) && defined(USE_VEML6070) - feature_sns1 |= 0x00002000; -#endif -#if defined(USE_I2C) && defined(USE_ADS1115_I2CDEV) - feature_sns1 |= 0x00004000; -#endif -#if defined(USE_I2C) && defined(USE_ADS1115) - feature_sns1 |= 0x00008000; -#endif -#if defined(USE_I2C) && defined(USE_INA219) - feature_sns1 |= 0x00010000; -#endif -#if defined(USE_I2C) && defined(USE_SHT3X) - feature_sns1 |= 0x00020000; -#endif -#ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; -#endif -#if defined(USE_I2C) && defined(USE_TSL2561) - feature_sns1 |= 0x00080000; -#endif -#ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; -#endif -#ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; -#endif -#if defined(USE_I2C) && defined(USE_MGS) - feature_sns1 |= 0x00400000; -#endif -#ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; -#endif -#if defined(USE_I2C) && defined(USE_SGP30) - feature_sns1 |= 0x01000000; -#endif -#ifdef USE_SR04 - feature_sns1 |= 0x02000000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_SDM120) - feature_sns1 |= 0x04000000; -#endif -#if defined(USE_I2C) && defined(USE_SI1145) - feature_sns1 |= 0x08000000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_SDM630) - feature_sns1 |= 0x10000000; -#endif -#if defined(USE_I2C) && defined(USE_LM75AD) - feature_sns1 |= 0x20000000; -#endif -#if defined(USE_I2C) && defined(USE_APDS9960) - feature_sns1 |= 0x40000000; -#endif -#ifdef USE_TM1638 - feature_sns1 |= 0x80000000; -#endif - - - feature_sns2 = 0x00000000; - -#if defined(USE_I2C) && defined(USE_MCP230xx) - feature_sns2 |= 0x00000001; -#endif -#if defined(USE_I2C) && defined(USE_MPR121) - feature_sns2 |= 0x00000002; -#endif -#if defined(USE_I2C) && defined(USE_CCS811) - feature_sns2 |= 0x00000004; -#endif -#if defined(USE_I2C) && defined(USE_MPU6050) - feature_sns2 |= 0x00000008; -#endif -#if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_OUTPUT) - feature_sns2 |= 0x00000010; -#endif -#if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_DISPLAYOUTPUT) - feature_sns2 |= 0x00000020; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) - feature_sns2 |= 0x00000040; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_CSE7766) - feature_sns2 |= 0x00000080; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) - feature_sns2 |= 0x00000100; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_AC) - feature_sns2 |= 0x00000200; -#endif -#if defined(USE_I2C) && defined(USE_DS3231) - feature_sns2 |= 0x00000400; -#endif -#ifdef USE_HX711 - feature_sns2 |= 0x00000800; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_DC) - feature_sns2 |= 0x00001000; -#endif -#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) - feature_sns2 |= 0x00002000; -#endif -#if defined(USE_I2C) && defined(USE_MGC3130) - feature_sns2 |= 0x00004000; -#endif -#ifdef USE_RF_SENSOR - feature_sns2 |= 0x00008000; -#endif -#if defined(USE_RF_SENSOR) && defined(USE_THEO_V2) - feature_sns2 |= 0x00010000; -#endif -#if defined(USE_RF_SENSOR) && defined(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 -#if defined(USE_I2C) && defined(USE_MAX44009) - feature_sns2 |= 0x00200000; -#endif -#if defined(USE_I2C) && defined(USE_SCD30) - feature_sns2 |= 0x00400000; -#endif -#ifdef USE_HRE - feature_sns2 |= 0x00800000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_ADE7953) - feature_sns2 |= 0x01000000; -#endif -#if defined(USE_I2C) && defined(USE_SPS30) - feature_sns2 |= 0x02000000; -#endif -#if defined(USE_I2C) && defined(USE_VL53L0X) - feature_sns2 |= 0x04000000; -#endif -#if defined(USE_I2C) && defined(USE_MLX90614) - feature_sns2 |= 0x08000000; -#endif -#ifdef USE_MAX31865 - feature_sns2 |= 0x10000000; -#endif -#if defined(USE_I2C) && defined(USE_CHIRP) - feature_sns2 |= 0x20000000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_SOLAX_X1) - feature_sns2 |= 0x40000000; -#endif -#if defined(USE_I2C) && defined(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 -#if defined(USE_I2C) && defined(USE_INA226) - feature5 |= 0x00000010; -#endif -#ifdef USE_A4988_STEPPER - feature5 |= 0x00000020; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_DDS2382) - feature5 |= 0x00000040; -#endif -#if defined(USE_LIGHT) && defined(USE_SM2135) - feature5 |= 0x00000080; -#endif -#ifdef USE_SHUTTER - feature5 |= 0x00000100; -#endif -#if defined(USE_I2C) && defined(USE_PCF8574) - feature5 |= 0x00000200; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_DDSU666) - feature5 |= 0x00000400; -#endif -#ifdef USE_DEEPSLEEP - feature5 |= 0x00000800; -#endif -#ifdef USE_SONOFF_SC - feature5 |= 0x00001000; -#endif -#ifdef USE_SONOFF_RF - feature5 |= 0x00002000; -#endif -#if defined(USE_LIGHT) && defined(USE_SONOFF_L1) - feature5 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_EXS_DIMMER) - feature5 |= 0x00008000; -#endif -#ifdef USE_TASMOTA_CLIENT - feature5 |= 0x00010000; -#endif -#if defined(USE_I2C) && defined(USE_HIH6) - feature5 |= 0x00020000; -#endif -#ifdef USE_HPMA - feature5 |= 0x00040000; -#endif -#if defined(USE_I2C) && defined(USE_TSL2591) - feature5 |= 0x00080000; -#endif -#if defined(USE_I2C) && defined(USE_DHT12) - feature5 |= 0x00100000; -#endif -#if defined(USE_I2C) && defined(USE_DS1624) - feature5 |= 0x00200000; -#endif -#ifdef USE_GPS - feature5 |= 0x00400000; -#endif -#if defined(USE_I2C) && defined(USE_HOTPLUG) - feature5 |= 0x00800000; -#endif -#ifdef USE_NRF24 - feature5 |= 0x01000000; -#endif -#ifdef USE_MIBLE - feature5 |= 0x02000000; -#endif -#ifdef USE_HM10 - feature5 |= 0x04000000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_LE01MR) - feature5 |= 0x08000000; -#endif -#if defined(USE_I2C) && defined(USE_AHT1x) - feature5 |= 0x10000000; -#endif -#if defined(USE_I2C) && defined(USE_WEMOS_MOTOR_V1) - feature5 |= 0x20000000; -#endif -#ifdef USE_DEVICE_GROUPS - feature5 |= 0x40000000; -#endif -#ifdef USE_PWM_DIMMER - feature5 |= 0x80000000; -#endif - - - - feature6 = 0x00000000; - -#ifdef USE_KEELOQ - feature6 |= 0x00000001; -#endif -#ifdef USE_HRXL - feature6 |= 0x00000002; -#endif -#ifdef USE_SONOFF_D1 - feature6 |= 0x00000004; -#endif -#if defined(USE_I2C) && defined(USE_HDC1080) - feature6 |= 0x00000008; -#endif -#if defined(USE_I2C) && defined(USE_IAQ) - feature6 |= 0x00000010; -#endif -#if defined(USE_DISPLAY) && defined(USE_DISPLAY_SEVENSEG) - feature6 |= 0x00000020; -#endif -#if defined(USE_I2C) && defined(USE_AS3935) - feature6 |= 0x00000040; -#endif -#ifdef USE_PING - feature6 |= 0x00000080; -#endif -#ifdef USE_WINDMETER - feature6 |= 0x00000100; -#endif -#ifdef USE_OPENTHERM - feature6 |= 0x00000200; -#endif -#ifdef USE_THERMOSTAT - feature6 |= 0x00000400; -#endif -#if defined(USE_I2C) && defined(USE_VEML6075) - feature6 |= 0x00000800; -#endif -#if defined(USE_I2C) && defined(USE_VEML7700) - feature6 |= 0x00001000; -#endif -#if defined(USE_I2C) && defined(USE_MCP9808) - feature6 |= 0x00002000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_BL0940) - feature6 |= 0x00004000; -#endif -#ifdef USE_TELEGRAM - feature6 |= 0x00008000; -#endif -#if defined(USE_I2C) && defined(USE_HP303B) - feature6 |= 0x00010000; -#endif -#ifdef USE_TCP_BRIDGE - feature6 |= 0x00020000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_TELEINFO) - feature6 |= 0x00040000; -#endif -#ifdef USE_LMT01 - feature6 |= 0x00080000; -#endif -#ifdef USE_PROMETHEUS - feature6 |= 0x00100000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_IEM3000) - feature6 |= 0x00200000; -#endif -#ifdef USE_DYP - feature6 |= 0x00400000; -#endif -#ifdef USE_I2S_AUDIO - feature6 |= 0x00800000; -#endif -#ifdef USE_MLX90640 - feature6 |= 0x01000000; -#endif -#if defined(USE_I2C) && defined(USE_VL53L1X) - feature6 |= 0x02000000; -#endif -#ifdef USE_MIEL_HVAC - feature6 |= 0x04000000; -#endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_WE517) - feature6 |= 0x08000000; -#endif -#if defined(USE_I2C) && defined(USE_EZOPH) - feature6 |= 0x10000000; -#endif -#if defined(ESP32) && defined(USE_TTGO_WATCH) - feature6 |= 0x20000000; -#endif -#if defined(ESP32) && defined(USE_ETHERNET) - feature6 |= 0x40000000; -#endif -#if defined(ESP32) && defined(USE_WEBCAM) - feature6 |= 0x80000000; -#endif - - - - feature7 = 0x00000000; - -#if defined(USE_I2C) && defined(USE_EZOORP) - feature7 |= 0x00000001; -#endif -#if defined(USE_I2C) && defined(USE_EZORTD) - feature7 |= 0x00000002; -#endif -#if defined(USE_I2C) && defined(USE_EZOHUM) - feature7 |= 0x00000004; -#endif -#if defined(USE_I2C) && defined(USE_EZOEC) - feature7 |= 0x00000008; -#endif -#if defined(USE_I2C) && defined(USE_EZOCO2) - feature7 |= 0x00000010; -#endif -# 683 "/workspace/Tasmota/tasmota/support_features.ino" -} -# 1 "/workspace/Tasmota/tasmota/support_flash_log.ino" -# 39 "/workspace/Tasmota/tasmota/support_flash_log.ino" -#ifdef USE_FLOG -#ifdef ESP8266 - -class FLOG - -#define MAGIC_WORD_FL 0x464c - -{ - -struct header_t{ - uint16_t magic_word; - uint16_t padding; - uint32_t physical_start_sector:10; - uint32_t number:10; - uint32_t buf_pointer:12; - }; - -private: -void _readSector(uint8_t one_sector); -void _eraseSector(uint8_t one_sector); -void _writeSector(uint8_t one_sector); -void _clearBuffer(void); -void _searchSaves(void); -void _findFirstErasedSector(void); -void _showBuffer(void); -void _initBuffer(void); -void _saveBufferToSector(void); -header_t _saved_header; - -public: - uint32_t size; - uint32_t start; - uint32_t end; - uint16_t num_sectors; - - uint16_t first_erased_sector; - uint16_t current_sector; - - uint16_t bytes_left; - uint16_t sectors_left; - - uint8_t mode = 0; - bool found_saved_data = false; - bool ready = false; - bool running_download = false; - bool recording = false; - - union sector_t{ - uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; - uint8_t byte_buffer[FLASH_SECTOR_SIZE]; - header_t header; - } sector; - - void init(void); - void addToBuffer(uint8_t src[], uint32_t size); - void startRecording(bool append); - void stopRecording(void); - - typedef void (*CallbackNoArgs) (); - typedef void (*CallbackWithArgs) (uint8_t *_record); - - void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); -}; - -extern "C" uint32_t _SPIFFS_start; -extern "C" uint32_t _FS_start; - - - - -void FLOG::init(void) -{ -DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); -size = ESP.getSketchSize(); - -start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); -end = (uint32_t)&_FS_start - 0x40200000; -num_sectors = (end - start)/FLASH_SECTOR_SIZE; -DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); -_findFirstErasedSector(); -if(first_erased_sector == 0xffff){ - _eraseSector(0); - first_erased_sector = 0; -} -_searchSaves(); -_initBuffer(); -ready = true; -} -# 139 "/workspace/Tasmota/tasmota/support_flash_log.ino" -void FLOG::_readSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); - ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - - -void FLOG::_eraseSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); - ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); -} - - - - - -void FLOG::_writeSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); - ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - -void FLOG::_clearBuffer(){ - for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ - sector.dword_buffer[i] = 0; - } - sector.header.buf_pointer = sizeof(sector.header); - -} - - - - -void FLOG::_saveBufferToSector(){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); - _writeSector(current_sector); - if(current_sector == num_sectors){ - current_sector = 0; - } - else{ - current_sector++; - } - _eraseSector(current_sector); - _clearBuffer(); - sector.header.number++; - DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); -} - - - - - -void FLOG::_findFirstErasedSector(){ - for (uint32_t i = 0; i3){ - break; - } - } -} - - - - - - - -void FLOG::addToBuffer(uint8_t src[], uint32_t size){ - if(mode == 0){ - if(sector.header.number == num_sectors && !ready){ - return; - } - } - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - - - - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - - } - else{ - DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); - DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); - _saveBufferToSector(); - sectors_left++; - - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - } - } -} - - - - - - -void FLOG::startRecording(bool append){ - if(recording){ - DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); - return; - } - recording = true; - DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); - _initBuffer(); - if(!found_saved_data) { - append = false; - } - if(append){ - sector.header.number = _saved_header.number+1; - sector.header.physical_start_sector = _saved_header.physical_start_sector; - } - else{ - sector.header.physical_start_sector = (uint16_t)first_erased_sector; - found_saved_data = false; - sectors_left = 0; - } - } - - - - - -void FLOG::stopRecording(void){ - _saveBufferToSector(); - _findFirstErasedSector(); - _searchSaves(); - _initBuffer(); - recording = false; - found_saved_data = true; - } -# 378 "/workspace/Tasmota/tasmota/support_flash_log.ino" - void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ - - _readSector(sector.header.physical_start_sector); - uint32_t next_sector = sector.header.physical_start_sector; - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); - running_download = true; - - sendHeader(); - - while(sectors_left){ - DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); - - uint32_t k = sizeof(sector.header); - while(bytes_left){ - - uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; - - sendRecord(_record_start); - if(k%128 == 0){ - - OsWatchLoop(); - delay(ssleep); - } - k+=size; - if(bytes_left>7){ - bytes_left-=size; - } - else{ - bytes_left = 0; - DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); - } - } - next_sector++; - if(next_sector>num_sectors){ - next_sector = 0; - } - sectors_left--; - _readSector(next_sector); - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - OsWatchLoop(); - delay(ssleep); - } - running_download = false; - - sendFooter(); - - _searchSaves(); - _initBuffer(); - } - - #endif - #endif -# 1 "/workspace/Tasmota/tasmota/support_float.ino" -# 20 "/workspace/Tasmota/tasmota/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; } - if (x == 1.0) { return 0; } - double z = (x + 1) / (x - 1); - double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); - double totalValue = 0; - double powe = 1; - for (uint32_t count = 0; count < 10; count++) { - z *= step; - double y = (1 / powe) * z; - totalValue = totalValue + y; - powe = powe + 2; - } - totalValue *= 2; -# 141 "/workspace/Tasmota/tasmota/support_float.ino" - return totalValue; -} -# 151 "/workspace/Tasmota/tasmota/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); -float const f_180pi = 180 / f_pi; -# 191 "/workspace/Tasmota/tasmota/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); - } - return 0.0; -} - - - - -float sin_52(float x) -{ - return cos_52((float)f_halfpi - x); -} -# 245 "/workspace/Tasmota/tasmota/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)); -} -# 265 "/workspace/Tasmota/tasmota/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); - } - return 0.0; -} -# 295 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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 (ifrom_min >= ifrom_max) { - if (ito_min > ito_max) { - return ito_max; - } else { - 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)); - - - if (to_min > to_max) { - - num = (from_max - num) + from_min; - to_min = ito_max; - to_max = ito_min; - } - - 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)); -} - - -float ModulusRangef(float f, float a, float b) { - if (b <= a) { return a; } - float range = b - a; - float x = f - a; - x = fmodf(x, range); - if (x < 0.0f) { x += range; } - return x + a; -} - - - - - - -float Polynomialf(const float *factors, uint32_t degree, float x) { - float r = 0.0f; - for (uint32_t i = degree - 1; i >= 0; i--) { - r = r * x + factors[i]; - } - return r; -} -# 1 "/workspace/Tasmota/tasmota/support_jpeg.ino" -# 21 "/workspace/Tasmota/tasmota/support_jpeg.ino" -#ifdef ESP32 -#ifdef JPEG_PICTS - -#include "img_converters.h" -#include "esp_jpg_decode.h" - -void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len) { -uint8_t red, grn, blu; -uint16_t b , g, r; - - for (uint32_t cnt=0; cnt> 3) & 0x1f; - g = ((grn >> 2) & 0x3f) << 5; - r = ((red >> 3) & 0x1f) << 11; - *out++ = (r | g | b); - } -} - -typedef struct { - uint16_t width; - uint16_t height; - uint16_t data_offset; - const uint8_t *input; - uint8_t *output; -} rgb_jpg_decoder; - - -static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len) -{ - rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; - if(buf) { - memcpy(buf, jpeg->input + index, len); - } - return len; -} - - -static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data) -{ - rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; - if(!data){ - if(x == 0 && y == 0){ - - jpeg->width = w; - jpeg->height = h; - - if(!jpeg->output){ - jpeg->output = (uint8_t *)malloc((w*h*3)+jpeg->data_offset); - if(!jpeg->output){ - return false; - } - } - } else { - - } - return true; - } - - size_t jw = jpeg->width*3; - size_t t = y * jw; - size_t b = t + (h * jw); - size_t l = x * 3; - uint8_t *out = jpeg->output+jpeg->data_offset; - uint8_t *o = out; - size_t iy, ix; - - w = w * 3; - - for(iy=t; iy= data_size) return false; - if(data[i] != 0xFF) return false; - if(data[i+1] == 0xC0) { - - *height = data[i+5]*256 + data[i+6]; - *width = data[i+7]*256 + data[i+8]; - return true; - } - else - { - i+=2; - block_length = data[i] * 256 + data[i+1]; - } - } - return false; - }else{ return false; } - - }else{ return false; } -} - - -#endif -#endif - -#ifdef USE_DISPLAY_DUMP -#define bytesPerPixel 3 -#define fileHeaderSize 14 -#define infoHeaderSize 40 - -void createBitmapFileHeader(uint32_t height, uint32_t width, uint8_t *fileHeader) { - int paddingSize = (4 - (width*bytesPerPixel) % 4) % 4; - - int fileSize = fileHeaderSize + infoHeaderSize + (bytesPerPixel*width+paddingSize) * height; - memset(fileHeader,0,fileHeaderSize); - fileHeader[ 0] = (unsigned char)('B'); - fileHeader[ 1] = (unsigned char)('M'); - fileHeader[ 2] = (unsigned char)(fileSize ); - fileHeader[ 3] = (unsigned char)(fileSize>> 8); - fileHeader[ 4] = (unsigned char)(fileSize>>16); - fileHeader[ 5] = (unsigned char)(fileSize>>24); - fileHeader[10] = (unsigned char)(fileHeaderSize + infoHeaderSize); - -} - -void createBitmapInfoHeader(uint32_t height, uint32_t width, uint8_t *infoHeader ) { - memset(infoHeader,0,infoHeaderSize); - - infoHeader[ 0] = (unsigned char)(infoHeaderSize); - infoHeader[ 4] = (unsigned char)(width ); - infoHeader[ 5] = (unsigned char)(width>> 8); - infoHeader[ 6] = (unsigned char)(width>>16); - infoHeader[ 7] = (unsigned char)(width>>24); - infoHeader[ 8] = (unsigned char)(height ); - infoHeader[ 9] = (unsigned char)(height>> 8); - infoHeader[10] = (unsigned char)(height>>16); - infoHeader[11] = (unsigned char)(height>>24); - infoHeader[12] = (unsigned char)(1); - infoHeader[14] = (unsigned char)(bytesPerPixel*8); - infoHeader[24] = (unsigned char)0x13; - infoHeader[25] = (unsigned char)0x0b; - infoHeader[28] = (unsigned char)0x13; - infoHeader[29] = (unsigned char)0x0b; - -} -#endif -# 1 "/workspace/Tasmota/tasmota/support_light_list.ino" -# 25 "/workspace/Tasmota/tasmota/support_light_list.ino" -template -class LList; - -template -class LList_elt { -public: - - LList_elt() : _next(nullptr), _val() {} - - inline T & val(void) { return _val; } - inline LList_elt * next(void) { return _next; } - inline void next(LList_elt * next) { _next = next; } - - friend class LList; - -protected: - LList_elt * _next; - T _val; -}; - - - - - - -template -class LList { -public: - LList() : _head(nullptr) {} - ~LList() { reset(); } - - - void removeHead(void); - void reset(void); - void remove(const T * val); - - - inline bool isEmpty(void) const { return (_head == nullptr) ? true : false; } - size_t length(void) const; - inline T * head(void) { return _head ? &_head->_val : nullptr; } - inline const T * head(void) const { return _head ? &_head->_val : nullptr; } - const T * at(size_t index) const ; - - - inline T * at(size_t index) { return (T*) ((const LList*)this)->at(index); } - - - T & addHead(void); - T & addHead(const T &val); - T & addToLast(void); - - - T & addHead(LList_elt * elt); - T & addToLast(LList_elt * elt); - - - - class iterator { - public: - iterator(LList_elt *_cur): cur(_cur), next(nullptr) { if (cur) { next = cur->_next; } } - iterator operator++() { cur = next; if (cur) { next = cur->_next;} return *this; } - bool operator!=(const iterator & other) const { return cur != other.cur; } - T & operator*() const { return cur->_val; } - private: - LList_elt *cur; - LList_elt *next; - }; - iterator begin() { return iterator(this->_head); } - iterator end() { return iterator(nullptr); } - - - class const_iterator { - public: - const_iterator(const LList_elt *_cur): cur(_cur), next(nullptr) { if (cur) { next = cur->_next; } } - const_iterator operator++() { cur = next; if (cur) { next = cur->_next;} return *this; } - bool operator!=(const_iterator & other) const { return cur != other.cur; } - const T & operator*() const { return cur->_val; } - private: - const LList_elt *cur; - const LList_elt *next; - }; - const_iterator begin() const { return const_iterator(this->_head); } - const_iterator end() const { return const_iterator(nullptr); } - -protected: - LList_elt * _head; -}; - -template -size_t LList::length(void) const { - size_t count = 0; - for (auto & elt : *this) {count++; } - return count; -} - - -template -const T * LList::at(size_t index) const { - size_t count = 0; - for (const auto & elt : *this) { - if (index == count++) { return &elt; } - } - return nullptr; -} - -template -void LList::reset(void) { - while (_head) { - LList_elt * next = _head->next(); - delete _head; - _head = next; - } -} - -template -void LList::removeHead(void) { - if (_head) { - LList_elt * next = _head->next(); - delete _head; - _head = next; - } -} - -template -void LList::remove(const T * val) { - if (nullptr == val) { return; } - - LList_elt **curr_ptr = &_head; - while (*curr_ptr) { - LList_elt * curr_elt = *curr_ptr; - if ( &(curr_elt->_val) == val) { - *curr_ptr = curr_elt->_next; - delete curr_elt; - break; - } - curr_ptr = &((*curr_ptr)->_next); - } -} - -template -T & LList::addHead(void) { - LList_elt * elt = new LList_elt(); - elt->next(_head); - _head = elt; - return elt->_val; -} - -template -T & LList::addHead(const T &val) { - LList_elt * elt = new LList_elt(); - elt->next(_head); - elt->_val = val; - _head = elt; - return elt->_val; -} - -template -T & LList::addHead(LList_elt * elt) { - elt->next(_head); - _head = elt; - return elt->_val; -} - -template -T & LList::addToLast(void) { - LList_elt **curr_ptr = &_head; - while (*curr_ptr) { - curr_ptr = &((*curr_ptr)->_next); - } - LList_elt * elt = new LList_elt(); - *curr_ptr = elt; - return elt->_val; -} - -template -T & LList::addToLast(LList_elt * elt) { - LList_elt **curr_ptr = &_head; - while (*curr_ptr) { - curr_ptr = &((*curr_ptr)->_next); - } - *curr_ptr = elt; - elt->_next = nullptr; - return elt->_val; -} -# 1 "/workspace/Tasmota/tasmota/support_network.ino" -# 24 "/workspace/Tasmota/tasmota/support_network.ino" -struct { - uint8_t begun = 0; -} Mdns; - -#ifdef USE_DISCOVERY -void StartMdns(void) { - if (Settings.flag3.mdns_enabled) { - if (!Mdns.begun) { - - - - - - Mdns.begun = (uint8_t)MDNS.begin(my_hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED); - - } - } -} - -#ifdef MQTT_HOST_DISCOVERY -void MqttDiscoverServer(void) -{ - if (!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 - SettingsUpdateText(SET_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(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port); - } -} -#endif - -#ifdef WEBSERVER_ADVERTISE -void MdnsAddServiceHttp(void) { - if (1 == Mdns.begun) { - Mdns.begun = 2; - MDNS.addService("http", "tcp", WEB_PORT); - } -} - -void MdnsUpdate(void) { - if (2 == Mdns.begun) { - MDNS.update(); - AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); - } -} -#endif -#endif - - - - - -char* NetworkHostname(void) { -#ifdef ESP32 -#ifdef USE_ETHERNET - if (!global_state.eth_down) { - return EthernetHostname(); - } -#endif -#endif - return my_hostname; -} - -IPAddress NetworkAddress(void) { -#ifdef ESP32 -#ifdef USE_ETHERNET - if (!global_state.eth_down) { - return EthernetLocalIP(); - } -#endif -#endif - return WiFi.localIP(); -} - -String NetworkMacAddress(void) { -#ifdef ESP32 -#ifdef USE_ETHERNET - if (!global_state.eth_down) { - return EthernetMacAddress(); - } -#endif -#endif - return WiFi.macAddress(); -} -# 1 "/workspace/Tasmota/tasmota/support_rotary.ino" -# 20 "/workspace/Tasmota/tasmota/support_rotary.ino" -#ifdef ROTARY_V1 -# 36 "/workspace/Tasmota/tasmota/support_rotary.ino" -#ifndef ROTARY_MAX_STEPS -#define ROTARY_MAX_STEPS 10 -#endif -#ifndef ROTARY_START_DIM -#define ROTARY_START_DIM 1 -#endif -#ifndef ROTARY_TIMEOUT -#define ROTARY_TIMEOUT 2 -#endif -#ifndef ROTARY_DEBOUNCE -#define ROTARY_DEBOUNCE 10 -#endif - - - -const uint8_t rotary_dimmer_increment[2] = { 100 / (ROTARY_MAX_STEPS * 3), 100 / ROTARY_MAX_STEPS }; -const uint8_t rotary_ct_increment[2] = { 350 / (ROTARY_MAX_STEPS * 3), 350 / ROTARY_MAX_STEPS }; -const uint8_t rotary_color_increment[2] = { 360 / (ROTARY_MAX_STEPS * 3), 360 / ROTARY_MAX_STEPS }; -const uint8_t rotary_offset = 128; -const int8_t rotary_state_pos[16] = { 0, 1, -1, 2, -1, 0, -2, 1, 1, -2, 0, -1, 2, -1, 1, 0 }; - -struct ROTARY { - uint8_t model; - bool present; -} Rotary; - -struct tEncoder { - volatile uint32_t debounce = 0; - volatile uint8_t state = 0; - volatile uint8_t position; - volatile int8_t direction = 0; - volatile int8_t pina; - volatile int8_t pinb; - uint8_t timeout = 0; - int8_t abs_position[2] = { 0 }; - bool changed = false; -}; -tEncoder Encoder[MAX_ROTARIES]; - - - -bool RotaryButtonPressed(uint32_t button_index) { - if (!Rotary.present) { return false; } - - for (uint32_t index = 0; index < MAX_ROTARIES; index++) { - if (-1 == Encoder[index].pinb) { continue; } - if (index != button_index) { continue; } - - bool powered_on = (power); -#ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { - powered_on = LightPower(); - } -#endif - if (Encoder[index].changed && powered_on) { - Encoder[index].changed = false; - return true; - } - return false; - } - return false; -} - -void ICACHE_RAM_ATTR RotaryIsrArgMiDesk(void *arg) { - tEncoder* encoder = static_cast(arg); - - - uint32_t state = encoder->state & 3; - if (digitalRead(encoder->pina)) { state |= 4; } - if (digitalRead(encoder->pinb)) { state |= 8; } - encoder->position += rotary_state_pos[state]; - encoder->state = (state >> 2); -} - -void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) { - tEncoder* encoder = static_cast(arg); - - - uint32_t time = millis(); - if ((encoder->debounce < time) || (encoder->debounce > time + ROTARY_DEBOUNCE)) { - int direction = (digitalRead(encoder->pinb)) ? -1 : 1; - if ((0 == encoder->direction) || (direction == encoder->direction)) { - encoder->position += direction; - encoder->direction = direction; - } - encoder->debounce = time + ROTARY_DEBOUNCE; - } -} - -void RotaryInit(void) { - Rotary.present = false; - Rotary.model = 1; -#ifdef ESP8266 - if (MI_DESK_LAMP == my_module_type) { - Rotary.model = 0; - } -#endif - for (uint32_t index = 0; index < MAX_ROTARIES; index++) { - Encoder[index].pinb = -1; - if (PinUsed(GPIO_ROT1A, index) && PinUsed(GPIO_ROT1B, index)) { - Encoder[index].position = rotary_offset; - Encoder[index].pina = Pin(GPIO_ROT1A, index); - Encoder[index].pinb = Pin(GPIO_ROT1B, index); - pinMode(Encoder[index].pina, INPUT_PULLUP); - pinMode(Encoder[index].pinb, INPUT_PULLUP); - if (0 == Rotary.model) { - attachInterruptArg(Encoder[index].pina, RotaryIsrArgMiDesk, &Encoder[index], CHANGE); - attachInterruptArg(Encoder[index].pinb, RotaryIsrArgMiDesk, &Encoder[index], CHANGE); - } else { - attachInterruptArg(Encoder[index].pina, RotaryIsrArg, &Encoder[index], FALLING); - } - } - Rotary.present |= (Encoder[index].pinb > -1); - } -} - - - - - -void RotaryHandler(void) { - if (!Rotary.present) { return; } - - for (uint32_t index = 0; index < MAX_ROTARIES; index++) { - if (-1 == Encoder[index].pinb) { continue; } - - if (Encoder[index].timeout) { - Encoder[index].timeout--; - if (!Encoder[index].timeout) { -#ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { - ResponseLightState(0); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_STATE)); - } -#endif - Encoder[index].direction = 0; - } - } - if (rotary_offset == Encoder[index].position) { continue; } - - Encoder[index].timeout = ROTARY_TIMEOUT; - - noInterrupts(); - int rotary_position = Encoder[index].position - rotary_offset; - Encoder[index].position = rotary_offset; - interrupts(); - - if (Settings.save_data && (save_data_counter < 2)) { - save_data_counter = 3; - } - - bool button_pressed = (Button.hold_timer[index]); - if (button_pressed) { Encoder[index].changed = true; } - - -#ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { - bool second_rotary = (Encoder[1].pinb > -1); - if (0 == index) { - if (button_pressed) { - if (second_rotary) { - LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); - } else { - if (!LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model])) { - LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); - } - } - } else { - uint32_t dimmer_index = second_rotary ? 1 : 0; - if (!Settings.flag4.rotary_poweron_dimlow || power) { - LightDimmerOffset(dimmer_index, rotary_position * rotary_dimmer_increment[Rotary.model]); - } else { - if (rotary_position > 0) { - LightDimmerOffset(dimmer_index, -LightGetDimmer(dimmer_index) + ROTARY_START_DIM); - } - } - } - } else { - if (button_pressed) { - LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model]); - } else { - LightDimmerOffset(2, rotary_position * rotary_dimmer_increment[Rotary.model]); - } - } - } else { -#endif - Encoder[index].abs_position[button_pressed] += rotary_position; - if (Encoder[index].abs_position[button_pressed] < 0) { - Encoder[index].abs_position[button_pressed] = 0; - } - if (Encoder[index].abs_position[button_pressed] > ROTARY_MAX_STEPS) { - Encoder[index].abs_position[button_pressed] = ROTARY_MAX_STEPS; - } - Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position[0], Encoder[index].abs_position[1]); - XdrvRulesProcess(); -#ifdef USE_LIGHT - } -#endif - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_rtc.ino" -# 25 "/workspace/Tasmota/tasmota/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; - uint32_t millis = 0; - uint32_t last_sync = 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; -} - -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 GetMinuteTime(uint32_t minutes) -{ - char tm[6]; - snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); - - return String(tm); -} - -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); -} -# 177 "/workspace/Tasmota/tasmota/support_rtc.ino" -String GetDateAndTime(uint8_t time_type) -{ - - uint32_t time = Rtc.local_time; - - switch (time_type) { - case DT_UTC: - time = Rtc.utc_time; - break; - - - - case DT_DST: - time = Rtc.daylight_saving_time; - break; - case DT_STD: - time = Rtc.standard_time; - break; - case DT_RESTART: - if (Rtc.restart_time == 0) { - return ""; - } - time = Rtc.restart_time; - break; - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; - case DT_BOOTCOUNT: - time = Settings.bootcount_reset_time; - break; - } - String dt = GetDT(time); - - if (DT_LOCAL_MILLIS == time_type) { - char ms[10]; - snprintf_P(ms, sizeof(ms), PSTR(".%03d"), RtcMillis()); - dt += ms; - time_type = DT_LOCAL; - } - - if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { - dt += GetTimeZone(); - } - return dt; -} - -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; -} - -uint32_t RtcMillis(void) { - return (millis() - Rtc.millis) % 1000; -} - -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; - - 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; - - Rtc.millis = millis(); - - if (!Rtc.user_time_entry) { - if (!global_state.network_down) { - uint8_t uptime_minute = (uptime / 60) % 60; - if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { - Rtc.ntp_sync_minute = 1; - } - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP_getChipId() & 0xF) * 3) + 3) ; - if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || - (Rtc.ntp_sync_minute == uptime_minute))) || - ntp_force_sync ) ) { - Rtc.ntp_time = sntp_get_current_timestamp(); - if (Rtc.ntp_time > START_VALID_TIME) { - ntp_force_sync = false; - Rtc.utc_time = Rtc.ntp_time; - Rtc.last_sync = 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); - - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } else { - Rtc.ntp_sync_minute++; - } - } - } - if ((Rtc.utc_time > (2 * 60 * 60)) && (Rtc.last_sync < Rtc.utc_time - (2 * 60 * 60))) { - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Not synced")); - Rtc.last_sync = Rtc.utc_time; - } - } - - 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; - } - if (Settings.bootcount_reset_time < START_VALID_TIME) { - Settings.bootcount_reset_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; - sntp_init(); - } else { - sntp_stop(); - Rtc.user_time_entry = true; - Rtc.utc_time = epoch -1; - } -} - -void RtcInit(void) -{ - sntp_setservername(0, SettingsText(SET_NTPSERVER1)); - sntp_setservername(1, SettingsText(SET_NTPSERVER2)); - sntp_setservername(2, SettingsText(SET_NTPSERVER3)); - sntp_stop(); - sntp_set_timezone(0); - sntp_init(); - Rtc.utc_time = 0; - BreakTime(Rtc.utc_time, RtcTime); - TickerRtc.attach(1, RtcSecond); -} -# 1 "/workspace/Tasmota/tasmota/support_static_buffer.ino" -# 20 "/workspace/Tasmota/tasmota/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 add16BigEndian(const uint16_t data) { - if (_buf->len < _buf->size - 1) { - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data; - } - 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 add32BigEndian(const uint32_t data) { - if (_buf->len < _buf->size - 3) { - _buf->buf[_buf->len++] = data >> 24; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data; - } - return _buf->len; - } - size_t add64(const uint64_t data) { - if (_buf->len < _buf->size - 7) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - _buf->buf[_buf->len++] = data >> 32; - _buf->buf[_buf->len++] = data >> 40; - _buf->buf[_buf->len++] = data >> 48; - _buf->buf[_buf->len++] = data >> 56; - } - 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 uint8_t *buf2, size_t len2) { - if ((buf2) && (len() + len2 <= size())) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - size_t addBuffer(const char *buf2, size_t len2) { - if ((buf2) && (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; - } - uint16_t get16BigEndian(const size_t offset) const { - if (offset < len() - 1) { - return _buf->buf[offset+1] | (_buf->buf[offset] << 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; - } - int32_t get32IBigEndian(const size_t offset) const { - if (offset < len() - 3) { - return _buf->buf[offset+3] | (_buf->buf[offset+2] << 8) | - (_buf->buf[offset+1] << 16) | (_buf->buf[offset] << 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; - } - - - inline size_t strlen(const size_t offset) const { - return strnlen((const char*) &_buf->buf[offset], len() - offset); - } - - size_t strlen_s(const size_t offset) const { - size_t slen = this->strlen(offset); - if (slen == len() - offset) { - return 0; - } else { - return slen; - } - } - - 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; - - -bool equalsSBuffer(const class SBuffer * buf1, const class SBuffer * buf2) { - if (buf1 == buf2) { return true; } - if (!buf1 && (buf2->len() == 0)) { return true; } - if (!buf2 && (buf1->len() == 0)) { return true; } - if (!buf1 || !buf2) { return false; } - - if (buf1->len() != buf2->len()) { return false; } - size_t len = buf1->len(); - for (uint32_t i=0; iget8(i) != buf2->get8(i)) { return false; } - } - return true; -} -# 1 "/workspace/Tasmota/tasmota/support_statistics.ino" -# 20 "/workspace/Tasmota/tasmota/support_statistics.ino" -#define USE_STATS_CODE - -#ifdef USE_STATS_CODE - - - - -String GetStatistics(void) -{ - char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); - return String(data); -} - -#else - -String GetStatistics(void) -{ - return String(""); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_switch.ino" -# 20 "/workspace/Tasmota/tasmota/support_switch.ino" -#define SWITCH_V3 -#ifdef SWITCH_V3 - - - - - - -const uint8_t SWITCH_PROBE_INTERVAL = 10; -const uint8_t SWITCH_FAST_PROBE_INTERVAL =2; -const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PROBE_INTERVAL; - - -#define SM_TIMER_MASK 0x3F -#define SM_NO_TIMER_MASK 0xFF -#define SM_FIRST_PRESS 0x40 -#define SM_SECOND_PRESS 0x80 - -#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 first_change = 0; - uint8_t present = 0; -} Switch; - - - -void SwitchPullupFlag(uint16 switch_bit) -{ - bitSet(Switch.no_pullup_mask, switch_bit); -} - -void SwitchSetVirtual(uint32_t index, uint8_t state) -{ - Switch.virtual_state[index] = state; -} - -uint8_t SwitchGetVirtual(uint32_t index) -{ - return Switch.virtual_state[index]; -} - -uint8_t SwitchLastState(uint32_t index) -{ - return Switch.last_state[index]; -} - -bool SwitchState(uint32_t index) -{ - uint32_t switchmode = Settings.switchmode[index]; - return ((FOLLOW_INV == switchmode) || - (PUSHBUTTON_INV == switchmode) || - (PUSHBUTTONHOLD_INV == switchmode) || - (FOLLOWMULTI_INV == switchmode) || - (PUSHHOLDMULTI_INV == switchmode) || - (PUSHON_INV == switchmode) - ) ^ Switch.last_state[index]; -} - - - -void SwitchProbe(void) -{ - if (uptime < 4) { return; } - - uint8_t state_filter; - uint8_t debounce_flags = Settings.switch_debounce % 10; - uint8_t force_high = debounce_flags &1; - uint8_t force_low = debounce_flags &2; - uint8_t ac_detect = debounce_flags == 9; - uint8_t switch_probe_interval; - uint8_t first_change = Switch.first_change; - - if (ac_detect) { - switch_probe_interval = SWITCH_FAST_PROBE_INTERVAL; - if (Settings.switch_debounce < 2 * AC_PERIOD * SWITCH_FAST_PROBE_INTERVAL + 9) { - state_filter = 2 * AC_PERIOD; - } else if (Settings.switch_debounce > (0x7f - 2 * AC_PERIOD) * SWITCH_FAST_PROBE_INTERVAL) { - state_filter = 0x7f; - } else { - state_filter = (Settings.switch_debounce - 9) / SWITCH_FAST_PROBE_INTERVAL; - } - } else { - switch_probe_interval = SWITCH_PROBE_INTERVAL; - state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; - } - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (PinUsed(GPIO_SWT1, i)) { - - if (1 == digitalRead(Pin(GPIO_SWT1, i))) { - - if (ac_detect) { - Switch.state[i] |= 0x80; - if (Switch.state[i] > 0x80) { - Switch.state[i]--; - if (0x80 == Switch.state[i]) { - Switch.virtual_state[i] = 0; - Switch.first_change = false; - } - } - } else { - - 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 (ac_detect) { - - - - - - - - if (Switch.state[i] & 0x80) { - Switch.state[i] &= 0x7f; - if (Switch.state[i] < state_filter - 2 * AC_PERIOD) { - Switch.state[i] += 2 * AC_PERIOD; - } else { - Switch.state[i] = state_filter; - Switch.virtual_state[i] = 1; - if (first_change) { - Switch.last_state[i] = 1; - Switch.first_change = false; - } - } - } else { - if (Switch.state[i] > 0x00) { - Switch.state[i]--; - if (0x00 == Switch.state[i]) { - Switch.virtual_state[i] = 0; - Switch.first_change = false; - } - } - } - } 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) -{ - uint8_t ac_detect = Settings.switch_debounce % 10 == 9; - - Switch.present = 0; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - Switch.last_state[i] = 1; - if (PinUsed(GPIO_SWT1, i)) { - Switch.present++; -#ifdef ESP8266 - pinMode(Pin(GPIO_SWT1, i), bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_SWT1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); -#else - pinMode(Pin(GPIO_SWT1, i), bitRead(Switch.no_pullup_mask, i) ? INPUT : INPUT_PULLUP); -#endif - if (ac_detect) { - Switch.state[i] = 0x80 + 2 * AC_PERIOD; - Switch.last_state[i] = 0; - } else { - Switch.last_state[i] = digitalRead(Pin(GPIO_SWT1, i)); - } - } - Switch.virtual_state[i] = Switch.last_state[i]; - } - if (Switch.present) { - if (ac_detect) { - TickerSwitch.attach_ms(SWITCH_FAST_PROBE_INTERVAL, SwitchProbe); - Switch.first_change = true; - } else { - TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); - } - } -} - - - - - -void SwitchHandler(uint8_t mode) -{ - if (uptime < 4) { return; } - - uint16_t loops_per_second = 1000 / Settings.switch_debounce; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (PinUsed(GPIO_SWT1, i) || (mode)) { - uint8_t button = Switch.virtual_state[i]; - uint8_t switchflag = POWER_TOGGLE +1; - - if (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) { - Switch.hold_timer[i]--; - if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings.param[P_HOLD_TIME] / 25) { - if ((Settings.switchmode[i] == PUSHHOLDMULTI) & (NOT_PRESSED == Switch.last_state[i])) { - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - if ((Settings.switchmode[i] == PUSHHOLDMULTI_INV) & (PRESSED == Switch.last_state[i])) { - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - } - if (0 == (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK))) { - switch (Settings.switchmode[i]) { - case TOGGLEMULTI: - switchflag = POWER_TOGGLE; - break; - case FOLLOWMULTI: - switchflag = button &1; - break; - case FOLLOWMULTI_INV: - switchflag = ~button &1; - break; - case PUSHHOLDMULTI: - if (NOT_PRESSED == button) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } else { - Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - } - break; - case PUSHHOLDMULTI_INV: - if (PRESSED == button) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } else { - Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - } - break; - default: - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - break; - } - } - } - - if (button != Switch.last_state[i]) { - switch (Settings.switchmode[i]) { - case TOGGLE: - case PUSHBUTTON_TOGGLE: - switchflag = POWER_TOGGLE; - break; - case FOLLOW: - switchflag = button &1; - break; - case FOLLOW_INV: - switchflag = ~button &1; - break; - case PUSHBUTTON: - if (PRESSED == button) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTON_INV: - if (NOT_PRESSED == button) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD: - if (PRESSED == button) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD_INV: - if (NOT_PRESSED == button) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case TOGGLEMULTI: - case FOLLOWMULTI: - case FOLLOWMULTI_INV: - if (Switch.hold_timer[i]) { - Switch.hold_timer[i] = 0; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - } else { - Switch.hold_timer[i] = loops_per_second / 2; - } - break; - case PUSHHOLDMULTI: - if (NOT_PRESSED == button) { - if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { - Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; - SendKey(KEY_SWITCH, i +1, POWER_INV); - } - } else { - if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) { - if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { - Switch.hold_timer[i]= SM_FIRST_PRESS; - switchflag = POWER_TOGGLE; - } - else{ - SendKey(KEY_SWITCH, i +1, POWER_100); - Switch.hold_timer[i]= 0; - } - } else { - Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_RELEASE); - } - } - Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; - break; - case PUSHHOLDMULTI_INV: - if (PRESSED == button) { - if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { - Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; - SendKey(KEY_SWITCH, i +1, POWER_INV); - } - } else { - if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) { - if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { - Switch.hold_timer[i]= SM_FIRST_PRESS; - switchflag = POWER_TOGGLE; - } - else{ - SendKey(KEY_SWITCH, i +1, POWER_100); - Switch.hold_timer[i]= 0; - } - } else { - Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_RELEASE); - } - } - Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; - break; - case PUSHON: - if (PRESSED == button) { - switchflag = POWER_ON; - } - break; - case PUSHON_INV: - if (NOT_PRESSED == button) { - switchflag = POWER_ON; - } - break; - case PUSH_IGNORE: - MqttPublishSensor(); - break; - } - Switch.last_state[i] = button; - } - if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); - } - } - } - } -} - -void SwitchLoop(void) -{ - if (Switch.present) { - if (TimeReached(Switch.debounce)) { - SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); - SwitchHandler(0); - } - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_tasmota.ino" -# 20 "/workspace/Tasmota/tasmota/support_tasmota.ino" -const char kSleepMode[] PROGMEM = "Dynamic|Normal"; -const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; - -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 { - String mac_address = WiFi.macAddress(); - mac_address.replace(":", ""); - if (digits > 12) { digits = 12; } - String mac_part = mac_address.substring(12 - digits); - snprintf_P(output, size, PSTR("%s%s"), output, mac_part.c_str()); - } - } 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(SettingsText(SET_OTAURL), "%04d") != nullptr) { - snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP_getChipId() & 0x1fff); - } - else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { - snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP_getChipId()); - } - else { - strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); - } - - return otaurl; -} - -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) -{ -# 91 "/workspace/Tasmota/tasmota/support_tasmota.ino" - char romram[CMDSZ]; - String fulltopic; - - snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { - bool fallback = (prefix < 8); - prefix &= 3; - char stemp[11]; - fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); - fulltopic += F("/"); - if (fallback) { - fulltopic += mqtt_client; - fulltopic += F("_fb"); - } else { - fulltopic += topic; - } - } else { - fulltopic = SettingsText(SET_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 < MAX_MQTT_PREFIXES; i++) { - if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { - char temp[TOPSZ]; - SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); - } - } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + 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* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic) -{ - - - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(itopic), subtopic); -} - -char* GetFallbackTopic_P(char *stopic, const char* subtopic) -{ - return GetTopic_P(stopic, CMND +4, nullptr, subtopic); -} - -char* GetStateText(uint32_t state) -{ - if (state >= MAX_STATE_TEXT) { - state = 1; - } - return SettingsText(SET_STATE_TXT1 + 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); - DigitalWrite(GPIO_REL1, port, bitRead(rel_inverted, port) ? !state : state); - } -} - -void SetDevicePower(power_t rpower, uint32_t source) -{ - ShowSource(source); - last_source = 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); - XsnsCall(FUNC_SET_POWER); - - XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_DEVICE_POWER)) { - - } -#ifdef ESP8266 - 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); - } -#endif - else - { - for (uint32_t i = 0; i < devices_present; i++) { - power_t state = rpower &1; - if (i < MAX_RELAYS) { - DigitalWrite(GPIO_REL1, i, bitRead(rel_inverted, i) ? !state : state); - } - rpower >>= 1; - } - } -} - -void RestorePower(bool publish_power, uint32_t source) -{ - if (power != last_power) { - power = last_power; - SetDevicePower(power, source); - if (publish_power) { - MqttPublishAllPowerState(); - } - } -} - -void SetAllPower(uint32_t state, uint32_t source) -{ -# 263 "/workspace/Tasmota/tasmota/support_tasmota.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 SetPowerOnState(void) -{ -#ifdef ESP8266 - if (MOTOR == my_module_type) { - Settings.poweronstate = POWER_ALL_ON; - } -#endif - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - SetDevicePower(1, SRC_RESTART); - } else { - if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == 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) && PinUsed(GPIO_REL1, i)) { - bitWrite(power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(rel_inverted, i)); - } - } - if (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate)) { - SetPulseTimer(i % MAX_PULSETIMERS, Settings.pulse_timer[i % MAX_PULSETIMERS]); - } - } - blink_powersave = power; -} - -void UpdateLedPowerAll() -{ - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, bitRead(led_power, i)); - } -} - -void SetLedPowerIdx(uint32_t led, uint32_t state) -{ - if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { - if (PinUsed(GPIO_LED1, 1)) { - led = 1; - } - } - if (PinUsed(GPIO_LED1, led)) { - uint32_t mask = 1 << led; - if (state) { - state = 1; - led_power |= mask; - } else { - led_power &= (0xFF ^ mask); - } - uint16_t pwm = 0; - if (bitRead(Settings.ledpwm_mask, led)) { -#ifdef USE_LIGHT - pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); -#else - pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); -#endif - analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); - } else { - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); - } - } -#ifdef USE_BUZZER - if (led == 0) { - BuzzerSetStateToLed(state); - } -#endif -} - -void SetLedPower(uint32_t state) -{ - if (!PinUsed(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) { - SetLedPowerIdx(0, state); - } - else if (led_pin < 99) { - if (state) { state = 1; } - digitalWrite(led_pin, (led_inv) ? !state : state); - } -#ifdef USE_BUZZER - BuzzerSetStateToLed(state); -#endif -} - -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) -{ -# 452 "/workspace/Tasmota/tasmota/support_tasmota.ino" - char stopic[TOPSZ]; - char scommand[CMDSZ]; - char key_topic[TOPSZ]; - bool result = false; - uint32_t device_save = device; - - char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_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(SettingsText(SET_MQTT_GRP_TOPIC), 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)))) { -#endif - MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain - : Settings.flag.mqtt_button_retain) && - (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); -#ifdef USE_DOMOTICZ - } -#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_PWM_DIMMER - if (PWM_DIMMER == my_module_type && !result) { -#endif - int32_t payload_save = XdrvMailbox.payload; - XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device; - XdrvCall(FUNC_ANY_KEY); - XdrvMailbox.payload = payload_save; -#ifdef USE_PWM_DIMMER - result = true; - } -#endif - return result; -} - -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) -{ -# 520 "/workspace/Tasmota/tasmota/support_tasmota.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; - - SetPulseTimer((device -1) % MAX_PULSETIMERS, 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; - } -#ifdef USE_DEVICE_GROUPS - if (SRC_REMOTE != source && SRC_RETRY != source) { - if (Settings.flag4.multiple_device_groups) - SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (power >> (device - 1)) & 1 | 0x01000000); - else - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); - } -#endif - 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(); - } - - - SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1) % MAX_PULSETIMERS] : 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 (PinUsed(GPIO_PWM1, i)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - ResponseJsonEnd(); -} - -void MqttShowState(void) -{ - char stemp1[TOPSZ]; - - ResponseAppendTime(); - ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); - -#ifdef ESP8266 -#ifdef USE_ADC_VCC - dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); -#endif -#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), - ssleep, loop_load_avg, MqttConnectCount()); - - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_LIGHT - if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { ResponseLightState(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(); - } - - if (!global_state.wifi_down) { - int32_t rssi = WiFi.RSSI(); - 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_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}"), - Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(), - WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); - } - - ResponseJsonEnd(); -} - -void MqttPublishTeleState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif -} - -void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperature, float f_humidity) -{ - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{"), types); - ResponseAppendTHD(f_temperature, f_humidity); - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (pass_on) { - DomoticzTempHumPressureSensor(f_temperature, f_humidity); - } -#endif -#ifdef USE_KNX - if (pass_on) { - KnxSensor(KNX_TEMPERATURE, f_temperature); - KnxSensor(KNX_HUMIDITY, f_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_THD(types, f_temperature, f_humidity); -#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 (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) { -#else - if (PinUsed(GPIO_SWT1, i)) { -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); - } - } - XsnsCall(FUNC_JSON_APPEND); - XdrvCall(FUNC_JSON_APPEND); - - 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()); - } - if ((strstr_P(mqtt_data, PSTR(D_JSON_SPEED)) != nullptr) && Settings.flag2.speed_conversion) { - ResponseAppend_P(PSTR(",\"" D_JSON_SPEED_UNIT "\":\"%s\""), SpeedUnit().c_str()); - } - ResponseJsonEnd(); - - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } - return json_data_available; -} - -void MqttPublishSensor(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishTeleSensor(); - } -} -# 788 "/workspace/Tasmota/tasmota/support_tasmota.ino" -void PerformEverySecond(void) -{ - uptime++; - - if (POWER_CYCLE_TIME == uptime) { - UpdateQuickPowerCycle(false); - } - - if (BOOT_LOOP_TIME == uptime) { - RtcRebootReset(); - -#ifdef USE_DEEPSLEEP - if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { -#endif - Settings.bootcount++; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); -#ifdef USE_DEEPSLEEP - } -#endif - } - - if (mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked_reset--; - if (!mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked = 0; - } - } - - 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) { - if (tele_period >= 9999) { - if (!global_state.network_down) { - tele_period = 0; - } - } else { - tele_period++; - 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 - } - - XsnsCall(FUNC_AFTER_TELEPERIOD); - XdrvCall(FUNC_AFTER_TELEPERIOD); - } - } - } - - - wifiKeepAlive(); - -#ifdef ESP32 - if (11 == uptime) { - ESP_getSketchSize(); - } -#endif -} - - - - - -void Every100mSeconds(void) -{ - - power_t power_now; - - if (prepped_loglevel) { - AddLog(prepped_loglevel); - } - - 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; - for (uint32_t j = 0; j < devices_present; j = j +MAX_PULSETIMERS) { - ExecuteCommandPower(i + j +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); - } - } - } -} - - - - - -void Every250mSeconds(void) -{ - - - uint32_t blinkinterval = 1; - - state_250mS++; - state_250mS &= 0x3; - - global_state.network_down = (global_state.wifi_down && global_state.eth_down) ? 1 : 0; - - if (!Settings.flag.global_state) { - if (global_state.data &0x03) { - if (global_state.mqtt_down) { blinkinterval = 7; } - if (global_state.network_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 && (PinUsed(GPIO_LEDLNK) || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; -#ifdef ESP8266 - 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; - } -#endif - SetLedPower(tstate); - } - - - - - - switch (state_250mS) { - case 0: - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { - RtcSettings.ota_loader = 0; - ota_retry_counter = OTA_ATTEMPTS; - ESPhttpUpdate.rebootOnUpdate(false); - SettingsSave(1); - } - if (ota_state_flag <= 0) { -#ifdef USE_COUNTER - CounterInterruptDisable(true); -#endif -#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) { -# 1015 "/workspace/Tasmota/tasmota/support_tasmota.ino" - char *bch = strrchr(mqtt_data, '/'); - if (bch == nullptr) { bch = mqtt_data; } - char *ech = strchr(bch, '.'); - if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } - - - - char ota_url_type[strlen(ech) +1]; - strncpy(ota_url_type, ech, sizeof(ota_url_type)); - - char *pch = strrchr(bch, '-'); - if (pch == nullptr) { pch = ech; } - *pch = '\0'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); - } -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); - WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); - 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; - Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); - if (ota_result) { - - if (!VersionCompatible()) { - ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); - } else { - ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - restart_flag = 2; - } - } else { - ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); - } - ResponseAppend_P(PSTR("\"}")); - - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); -#ifdef USE_COUNTER - CounterInterruptDisable(false); -#endif - } - } - 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 < devices_present; i++) { - if ((Settings.pulse_timer[i % MAX_PULSETIMERS] > 0) && (Settings.pulse_timer[i % MAX_PULSETIMERS] < 30)) { - mask &= ~(1 << i); - } - } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; - } - } else { - Settings.power = 0; - } - if (!restart_flag) { 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_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; - strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); - char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; - strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); - char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; - strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); - char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; - strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); - - char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; - strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); - char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; - strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); - char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; - strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); - char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; - strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); - uint16_t mqtt_port = Settings.mqtt_port; - - - - - if ((215 == restart_flag) || (216 == restart_flag)) { - SettingsErase(0); - } - SettingsDefault(); - - SettingsUpdateText(SET_STASSID1, storage_ssid1); - SettingsUpdateText(SET_STASSID2, storage_ssid2); - SettingsUpdateText(SET_STAPWD1, storage_pass1); - SettingsUpdateText(SET_STAPWD2, storage_pass2); - if (216 == restart_flag) { - - SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); - SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); - SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); - SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); - Settings.mqtt_port = mqtt_port; - } - 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_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (restart_halt) ? "Halted" : D_RESTARTING); - EspRestart(); - } - } - break; - case 2: - if (Settings.flag4.network_wifi) { - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; - } - break; - case 3: - if (!global_state.network_down) { -#ifdef FIRMWARE_MINIMAL - if (1 == RtcSettings.ota_loader) { - RtcSettings.ota_loader = 0; - ota_state_flag = 3; - } -#endif - -#ifdef USE_DISCOVERY - StartMdns(); -#endif - -#ifdef USE_WEBSERVER - if (Settings.webserver) { - -#ifdef ESP8266 - StartWebserver(Settings.webserver, WiFi.localIP()); -#else -#ifdef USE_ETHERNET - StartWebserver(Settings.webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP()); -#else - StartWebserver(Settings.webserver, WiFi.localIP()); -#endif -#endif - -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - MdnsAddServiceHttp(); -#endif -#endif - } else { - StopWebserver(); - } -#ifdef USE_EMULATION - if (Settings.flag2.emulation) { UdpConnect(); } -#endif -#endif - -#ifdef USE_DEVICE_GROUPS - DeviceGroupsStart(); -#endif - -#ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { - KNXStart(); - knx_started = true; - } -#endif - - MqttCheck(); - } else { -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - -#ifdef USE_DEVICE_GROUPS - DeviceGroupsStop(); -#endif - -#ifdef USE_KNX - knx_started = false; -#endif - } - 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(NetworkHostname()); - if (strlen(SettingsText(SET_WEBPWD))) { - ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); - } - - 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")); -} - -void ArduinoOtaLoop(void) -{ - MDNS.update(); - ArduinoOTA.handle(); - - while (arduino_ota_triggered) { ArduinoOTA.handle(); } -} -#endif - - - -void SerialInput(void) -{ - while (Serial.available()) { - - delay(0); - serial_in_byte = Serial.read(); - - if (0 == serial_in_byte_counter) { - serial_buffer_overrun = false; - } - else if ((serial_in_byte_counter == INPUT_BUFFER_SIZE) -#ifdef ESP8266 - || Serial.hasOverrun() -#endif - ) { - serial_buffer_overrun = true; - } - -#ifdef ESP8266 - - - - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); - } -#endif - - - 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_buffer_overrun = true; - } - } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - bool in_byte_is_delimiter = - (((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || - ((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && - !Settings.flag.mqtt_serial_raw; - - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - !in_byte_is_delimiter) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - - if ((serial_in_byte_counter >= INPUT_BUFFER_SIZE -1) || - in_byte_is_delimiter) { - serial_polling_window = 0; - break; - } - - serial_polling_window = millis(); - } - } - -#ifdef USE_SONOFF_SC - - - - 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 -#endif - - - 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; - if (serial_buffer_overrun) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "Serial buffer overrun")); - } else { - 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; - bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); - - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":")); - if (assume_json) { - ResponseAppend_P(serial_in_buffer); - } else { - ResponseAppend_P(PSTR("\"")); - if (Settings.flag.mqtt_serial_raw) { - char hex_char[(serial_in_byte_counter * 2) + 2]; - ResponseAppend_P(ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char))); - } else { - ResponseAppend_P(EscapeJSONString(serial_in_buffer).c_str()); - } - ResponseAppend_P(PSTR("\"")); - } - ResponseJsonEnd(); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - serial_in_byte_counter = 0; - } -} - - - -void ResetPwm(void) -{ - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (PinUsed(GPIO_PWM1, i)) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); - - } - } -} - - - -void GpioInit(void) -{ - if (!ValidModule(Settings.module)) { - uint32_t module = MODULE; - if (!ValidModule(MODULE)) { -#ifdef ESP8266 - module = SONOFF_BASIC; -#endif -#ifdef ESP32 - module = WEMOS; -#endif - } - - Settings.module = module; - Settings.last_module = module; - } - SetModuleType(); - - if (Settings.module != Settings.last_module) { - Settings.baudrate = APP_BAUDRATE / 300; - Settings.serial_config = TS_SERIAL_8N1; - SetSerialBegin(); - } - - - -#ifdef ESP8266 - ConvertGpios(); -#endif - - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { - if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) { - Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); - } - } - - myio def_gp; - ModuleGpios(&def_gp); - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { - if ((Settings.my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.my_gp.io[i] < AGPIO(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] < AGPIO(GPIO_USER))) { - my_module.io[i] = def_gp.io[i]; - } - } - - for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { - uint32_t 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 >= AGPIO(GPIO_SWT1_NP)) && (mpin < (AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES))) { - SwitchPullupFlag(mpin - AGPIO(GPIO_SWT1_NP)); - mpin -= (AGPIO(GPIO_SWT1_NP) - AGPIO(GPIO_SWT1)); - } - else if ((mpin >= AGPIO(GPIO_KEY1_NP)) && (mpin < (AGPIO(GPIO_KEY1_NP) + MAX_KEYS))) { - ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_NP)); - mpin -= (AGPIO(GPIO_KEY1_NP) - AGPIO(GPIO_KEY1)); - } - else if ((mpin >= AGPIO(GPIO_KEY1_INV)) && (mpin < (AGPIO(GPIO_KEY1_INV) + MAX_KEYS))) { - ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV)); - mpin -= (AGPIO(GPIO_KEY1_INV) - AGPIO(GPIO_KEY1)); - } - else if ((mpin >= AGPIO(GPIO_KEY1_INV_NP)) && (mpin < (AGPIO(GPIO_KEY1_INV_NP) + MAX_KEYS))) { - ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); - ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); - mpin -= (AGPIO(GPIO_KEY1_INV_NP) - AGPIO(GPIO_KEY1)); - } -#ifdef ESP32 - else if ((mpin >= AGPIO(GPIO_KEY1_TC)) && (mpin < (AGPIO(GPIO_KEY1_TC) + MAX_KEYS))) { - ButtonTouchFlag(mpin - AGPIO(GPIO_KEY1_TC)); - mpin -= (AGPIO(GPIO_KEY1_TC) - AGPIO(GPIO_KEY1)); - } -#endif - else if ((mpin >= AGPIO(GPIO_REL1_INV)) && (mpin < (AGPIO(GPIO_REL1_INV) + MAX_RELAYS))) { - bitSet(rel_inverted, mpin - AGPIO(GPIO_REL1_INV)); - mpin -= (AGPIO(GPIO_REL1_INV) - AGPIO(GPIO_REL1)); - } - else if ((mpin >= AGPIO(GPIO_LED1_INV)) && (mpin < (AGPIO(GPIO_LED1_INV) + MAX_LEDS))) { - bitSet(led_inverted, mpin - AGPIO(GPIO_LED1_INV)); - mpin -= (AGPIO(GPIO_LED1_INV) - AGPIO(GPIO_LED1)); - } - else if (mpin == AGPIO(GPIO_LEDLNK_INV)) { - ledlnk_inverted = 1; - mpin -= (AGPIO(GPIO_LEDLNK_INV) - AGPIO(GPIO_LEDLNK)); - } - else if ((mpin >= AGPIO(GPIO_PWM1_INV)) && (mpin < (AGPIO(GPIO_PWM1_INV) + MAX_PWMS))) { - bitSet(pwm_inverted, mpin - AGPIO(GPIO_PWM1_INV)); - mpin -= (AGPIO(GPIO_PWM1_INV) - AGPIO(GPIO_PWM1)); - } - else if (XdrvCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - } - else if (XsnsCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - }; - } - if (mpin) { SetPin(i, mpin); } - } - - - - analogWriteRange(Settings.pwm_range); - analogWriteFreq(Settings.pwm_frequency); - -#ifdef ESP8266 - if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); } - -#ifdef USE_SPI - spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12))); - if (spi_flg) { - my_module.io[12] = GPIO_SPI_MISO; - SetPin(12, GPIO_SPI_MISO); - my_module.io[13] = GPIO_SPI_MOSI; - SetPin(13, GPIO_SPI_MOSI); - my_module.io[14] = GPIO_SPI_CLK; - SetPin(14, GPIO_SPI_CLK); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK)")); - } -#endif -#else -#ifdef USE_SPI - if (PinUsed(GPIO_SPI_CS) || PinUsed(GPIO_SPI_DC)) { - if ((15 == Pin(GPIO_SPI_CS)) && (!GetPin(12) && !GetPin(13) && !GetPin(14))) { - my_module.io[12] = AGPIO(GPIO_SPI_MISO); - SetPin(12, AGPIO(GPIO_SPI_MISO)); - my_module.io[13] = AGPIO(GPIO_SPI_MOSI); - SetPin(13, AGPIO(GPIO_SPI_MOSI)); - my_module.io[14] = AGPIO(GPIO_SPI_CLK); - SetPin(14, AGPIO(GPIO_SPI_CLK)); - } - else if ((5 == Pin(GPIO_SPI_CS)) && (!GetPin(19) && !GetPin(23) && !GetPin(18))) { - my_module.io[19] = AGPIO(GPIO_SPI_MISO); - SetPin(19, AGPIO(GPIO_SPI_MISO)); - my_module.io[23] = AGPIO(GPIO_SPI_MOSI); - SetPin(23, AGPIO(GPIO_SPI_MOSI)); - my_module.io[18] = AGPIO(GPIO_SPI_CLK); - SetPin(18, AGPIO(GPIO_SPI_CLK)); - } - else if ((12 == Pin(GPIO_SPI_MISO)) || (13 == Pin(GPIO_SPI_MOSI)) || (14 == Pin(GPIO_SPI_CLK))) { - my_module.io[12] = AGPIO(GPIO_SPI_MISO); - SetPin(12, AGPIO(GPIO_SPI_MISO)); - my_module.io[13] = AGPIO(GPIO_SPI_MOSI); - SetPin(13, AGPIO(GPIO_SPI_MOSI)); - my_module.io[14] = AGPIO(GPIO_SPI_CLK); - SetPin(14, AGPIO(GPIO_SPI_CLK)); - } - else if ((19 == Pin(GPIO_SPI_MISO)) || (23 == Pin(GPIO_SPI_MOSI)) || (18 == Pin(GPIO_SPI_CLK))) { - my_module.io[19] = AGPIO(GPIO_SPI_MISO); - SetPin(19, AGPIO(GPIO_SPI_MISO)); - my_module.io[23] = AGPIO(GPIO_SPI_MOSI); - SetPin(23, AGPIO(GPIO_SPI_MOSI)); - my_module.io[18] = AGPIO(GPIO_SPI_CLK); - SetPin(18, AGPIO(GPIO_SPI_CLK)); - } - spi_flg = (PinUsed(GPIO_SPI_CLK) && (PinUsed(GPIO_SPI_MOSI) || PinUsed(GPIO_SPI_MISO))); - if (spi_flg) { - if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MISO), GPIO%02d(MOSI) and GPIO%02d(CLK)"), - Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); - } - else if (PinUsed(GPIO_SPI_MOSI)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MOSI) and GPIO%02d(CLK)"), - Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); - } - else if (PinUsed(GPIO_SPI_MISO)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MISO) and GPIO%02d(CLK)"), - Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK)); - } - } - } -#endif -#endif - soft_spi_flg = (PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO))); - - for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { - uint32_t mpin = ValidPin(i, my_module.io[i]); - - if (AGPIO(GPIO_OUTPUT_HI) == mpin) { - pinMode(i, OUTPUT); - digitalWrite(i, 1); - } - else if (AGPIO(GPIO_OUTPUT_LO) == mpin) { - pinMode(i, OUTPUT); - digitalWrite(i, 0); - } - - - else if (((i < 6) || (i > 11)) && (GPIO_NONE == mpin)) { - if (!((1 == i) || (3 == i))) { - pinMode(i, INPUT); - } - } - } - -#ifdef USE_I2C - i2c_flg = (PinUsed(GPIO_I2C_SCL) && PinUsed(GPIO_I2C_SDA)); - if (i2c_flg) { - Wire.begin(Pin(GPIO_I2C_SDA), Pin(GPIO_I2C_SCL)); - } -#endif - - devices_present = 0; - light_type = LT_BASIC; - - XsnsCall(FUNC_MODULE_INIT); - - if (XdrvCall(FUNC_MODULE_INIT)) { - - } -#ifdef ESP8266 - else if (YTF_IR_BRIDGE == my_module_type) { - ClaimSerial(); - - } - else if (SONOFF_DUAL == my_module_type) { - devices_present = 2; - SetSerial(19200, TS_SERIAL_8N1); - } - else if (CH4 == my_module_type) { - devices_present = 4; - SetSerial(19200, TS_SERIAL_8N1); - } -#ifdef USE_SONOFF_SC - else if (SONOFF_SC == my_module_type) { - SetSerial(19200, TS_SERIAL_8N1); - } -#endif -#endif - - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (PinUsed(GPIO_PWM1, i)) { -#ifdef ESP8266 - pinMode(Pin(GPIO_PWM1, i), OUTPUT); -#else - analogAttach(Pin(GPIO_PWM1, i), i); -#endif - if (light_type) { - - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); - } else { - pwm_present = true; - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); - } - } - } - - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (PinUsed(GPIO_REL1, i)) { - pinMode(Pin(GPIO_REL1, i), OUTPUT); - devices_present++; -#ifdef ESP8266 - if (EXS_RELAY == my_module_type) { - digitalWrite(Pin(GPIO_REL1, i), bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } - } -#endif - } - } - - for (uint32_t i = 0; i < MAX_LEDS; i++) { - if (PinUsed(GPIO_LED1, i)) { -#ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) { - SetPin(Pin(GPIO_LED1, i), AGPIO(GPIO_ARIRFSEL)); - } 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 (PinUsed(GPIO_LEDLNK)) { - pinMode(Pin(GPIO_LEDLNK), OUTPUT); - digitalWrite(Pin(GPIO_LEDLNK), ledlnk_inverted); - } - -#ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type && PinUsed(GPIO_REL1)) { devices_present--; } -#endif - - ButtonInit(); - SwitchInit(); -#ifdef ROTARY_V1 - RotaryInit(); -#endif - - SetLedPower(Settings.ledstate &8); - SetLedLink(Settings.ledstate &8); - - XdrvCall(FUNC_PRE_INIT); - XsnsCall(FUNC_PRE_INIT); -} -# 1 "/workspace/Tasmota/tasmota/support_udp.ino" -# 20 "/workspace/Tasmota/tasmota/support_udp.ino" -#ifdef USE_EMULATION - -#ifndef UDP_BUFFER_SIZE -#define UDP_BUFFER_SIZE 120 -#endif -#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; - -#ifdef ESP8266 -#ifndef UDP_MAX_PACKETS -#define UDP_MAX_PACKETS 3 -#endif - -#include "UdpListener.h" -UdpListener UdpCtx(UDP_MAX_PACKETS); -#endif - - - - - -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(); -#ifdef ESP8266 - UdpCtx.disconnect(); -#endif -#ifdef USE_DEVICE_GROUPS - - PortUdp.stop(); -#else - - WiFiUDP::stopAll(); -#endif - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); - udp_connected = false; - } - return udp_connected; -} - -bool UdpConnect(void) -{ - if (!udp_connected && !restart_flag) { - -#ifdef ESP8266 - UdpCtx.reset(); - if (igmp_joingroup(WiFi.localIP(), IPAddress(239,255,255,250)) == ERR_OK) { - ip_addr_t addr = IPADDR4_INIT(INADDR_ANY); - if (UdpCtx.listen(&addr, 1900)) { - - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; - udp_connected = true; - } -#else - 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; -#endif - } - if (!udp_connected) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); - } - } - return udp_connected; -} - -void PollUdp(void) -{ - if (udp_connected) { -#ifdef ESP8266 - while (UdpCtx.next()) { - UdpPacket *packet; - packet = UdpCtx.read(); - if (packet->len >= UDP_BUFFER_SIZE) { - packet->len--; - } - packet->buf[packet->len] = 0; - char * packet_buffer = (char*) &packet->buf; - int32_t len = packet->len; -#else - while (PortUdp.parsePacket()) { - char packet_buffer[UDP_BUFFER_SIZE]; - - int32_t len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - packet_buffer[len] = 0; -#endif - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); - - - - if (Settings.flag2.emulation) { -#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) - 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; - -#ifdef ESP8266 - udp_remote_ip = packet->srcaddr; - udp_remote_port = packet->srcport; -#else - udp_remote_ip = PortUdp.remoteIP(); - udp_remote_port = PortUdp.remotePort(); -#endif - - - - - 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; - continue; - } - } - } - optimistic_yield(100); - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/support_wifi.ino" -# 29 "/workspace/Tasmota/tasmota/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 = 12; - -#include -#if LWIP_IPV6 -#include -#endif - -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 config_type = 0; - uint8_t config_counter = 0; - uint8_t scan_state; - uint8_t bssid[6]; - int8_t best_network_db; -} 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); -} - -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_WEBSERVER - if (WIFI_MANAGER == 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_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 WifiSetMode(WiFiMode_t wifi_mode) -{ - if (WiFi.getMode() == wifi_mode) { return; } - - if (wifi_mode != WIFI_OFF) { - - WiFi.forceSleepWake(); - delay(100); - } - - uint32_t retry = 2; - while (!WiFi.mode(wifi_mode) && retry--) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); - delay(100); - } - - if (wifi_mode == WIFI_OFF) { - delay(1000); - WiFi.forceSleepBegin(); - delay(1); - } else { - delay(30); - } -} - -void WiFiSetSleepMode(void) -{ -# 156 "/workspace/Tasmota/tasmota/support_wifi.ino" - if (ssleep && Settings.flag3.sleep_normal) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); - } - WifiSetOutputPower(); -} - -void WifiBegin(uint8_t flag, uint8_t channel) -{ - const char kWifiPhyMode[] = " BGN"; - -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - - WiFi.persistent(false); - WiFi.disconnect(true); - delay(200); - - WifiSetMode(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 (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { - 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); - - char stemp[40] = { 0 }; - if (channel) { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); - - char hex_char[18]; - snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); - } else { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - -#if LWIP_IPV6 - for (bool configured = false; !configured;) { - uint16_t cfgcnt = 0; - for (auto addr : addrList) { - if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str()); - break; - } - delay(500); - cfgcnt++; - } - } -#endif -} - -void WifiBeginAfterScan(void) -{ - - if (0 == Wifi.scan_state) { return; } - - if (1 == Wifi.scan_state) { - memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); - Wifi.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)); - Wifi.best_network_db = WiFi.RSSI(); - if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { - Wifi.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 < MAX_SSIDS; j++) { - if (ssid_scan == SettingsText(SET_STASSID1 + j)) { - known = true; - if (rssi_scan > Wifi.best_network_db) { - if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { - Wifi.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(void) -{ - return Wifi.link_count; -} - -String WifiDowntime(void) -{ - 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; - if (!global_state.wifi_down) { - global_state.network_down = 0; - } -} - -#if LWIP_IPV6 -bool WifiCheckIPv6(void) -{ - bool ipv6_global=false; - - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) ipv6_global=true; - } - return ipv6_global; -} - -String WifiGetIPv6(void) -{ - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) return a.toString(); - } - return ""; -} - -bool WifiCheckIPAddrStatus(void) -{ - bool ip_global=false; - - for (auto a : addrList) { - if(!a.isLocal()) ip_global=true; - } - return ip_global; -} -#endif - -void WifiCheckIp(void) -{ -#if LWIP_IPV6 - if(WifiCheckIPAddrStatus()) { - Wifi.status = WL_CONNECTED; -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { -#endif - WifiSetState(1); - Wifi.counter = WIFI_CHECK_SEC; - Wifi.retry = Wifi.retry_init; - if (Wifi.status != WL_CONNECTED) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_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(); - - - Settings.wifi_channel = WiFi.channel(); - uint8_t *bssid = WiFi.BSSID(); - memcpy((void*) &Settings.wifi_bssid, (void*) bssid, sizeof(Settings.wifi_bssid)); - } - Wifi.status = WL_CONNECTED; -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - MdnsUpdate(); -#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)); - Settings.wifi_channel = 0; - 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)); - Settings.wifi_channel = 0; - 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)); - Settings.wifi_channel = 0; - } else { - if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { - Settings.wifi_channel = 0; - wifi_config_tool = WIFI_MANAGER; - 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, Settings.wifi_channel); - } - 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_MANAGER: - WifiConfig(param); - break; - default: - if (Wifi.config_counter) { - Wifi.config_counter--; - Wifi.counter = Wifi.config_counter +5; - if (Wifi.config_counter) { - if (!Wifi.config_counter) { - if (strlen(WiFi.SSID().c_str())) { - SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); - } - if (strlen(WiFi.psk().c_str())) { - SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); - } - Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); - } - } - if (!Wifi.config_counter) { - - 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 LWIP_IPV6 - if (WifiCheckIPAddrStatus()) { -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { -#endif - WifiSetState(1); - if (Settings.flag3.use_wifi_rescan) { - if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { - Wifi.scan_state = 2; - } - } - } else { - WifiSetState(0); - Mdns.begun = 0; - } - } - } -} - -int WifiState(void) -{ - int state = -1; - - if (!global_state.wifi_down) { state = WIFI_RESTART; } - if (Wifi.config_type) { state = Wifi.config_type; } - return state; -} - -String WifiGetOutputPower(void) -{ - char stemp1[TOPSZ]; - dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); - return String(stemp1); -} - -void WifiSetOutputPower(void) -{ - WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); -} -# 563 "/workspace/Tasmota/tasmota/support_wifi.ino" -#ifdef WIFI_RF_MODE_RF_CAL -#ifndef USE_DEEPSLEEP -RF_MODE(RF_CAL); -#endif -#endif - -#ifdef WIFI_RF_PRE_INIT -bool rf_pre_init_flag = false; -RF_PRE_INIT() -{ -#ifndef USE_DEEPSLEEP - system_deep_sleep_set_option(1); - system_phy_set_rfoption(RF_CAL); -#endif - system_phy_set_powerup_option(3); - rf_pre_init_flag = true; -} -#endif - -void WifiConnect(void) -{ - if (!Settings.flag4.network_wifi) { return; } - - WifiSetState(0); - WifiSetOutputPower(); - WiFi.persistent(false); - Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP_getChipId() & 0xF); - Wifi.retry = Wifi.retry_init; - Wifi.counter = 1; - - memcpy((void*) &Wifi.bssid, (void*) Settings.wifi_bssid, sizeof(Wifi.bssid)); - -#ifdef WIFI_RF_PRE_INIT - if (rf_pre_init_flag) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Pre-init done")); - } -#endif -} - -void WifiShutdown(bool option = false) -{ - - - delay(100); - -#ifdef USE_EMULATION - UdpDisconnect(); - delay(100); -#endif - - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); - delay(100); - } - -#ifdef WIFI_FORCE_RF_CAL_ERASE - if (option) { - WiFi.disconnect(false); - SettingsErase(4); - } else -#endif - { - - - - - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - - } - delay(100); -} - -void EspRestart(void) -{ - ResetPwm(); - WifiShutdown(true); - CrashDumpClear(); - - if (restart_halt) { - while (1) { - OsWatchLoop(); - SetLedLink(1); - delay(200); - SetLedLink(0); - delay(800); - } - } else { - ESP_Restart(); - } -} - - - - -extern "C" { -#if LWIP_VERSION_MAJOR == 1 -#include "netif/wlan_lwip_if.h" -#include "netif/etharp.h" -#else -#include "lwip/etharp.h" -#endif -} - -unsigned long wifiTimer = 0; - -void stationKeepAliveNow(void) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI "Sending Gratuitous ARP")); - for (netif* interface = netif_list; interface != nullptr; interface = interface->next) - if ( - (interface->flags & NETIF_FLAG_LINK_UP) - && (interface->flags & NETIF_FLAG_UP) -#if LWIP_VERSION_MAJOR == 1 - && interface == eagle_lwip_getif(STATION_IF) - && (!ip_addr_isany(&interface->ip_addr)) -#else - && interface->num == STATION_IF - && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) -#endif - ) - { - etharp_gratuitous(interface); - break; - } -} - -void wifiKeepAlive(void) { - uint32_t wifiTimerSec = Settings.param[P_ARP_GRATUITOUS]; - - if ((WL_CONNECTED != Wifi.status) || (0 == wifiTimerSec)) { return; } - - if (TimeReached(wifiTimer)) { - stationKeepAliveNow(); - if (wifiTimerSec > 100) { - wifiTimerSec = (wifiTimerSec - 100) * 60; - } - SetNextTimeInterval(wifiTimer, wifiTimerSec * 1000); - } -} -# 1 "/workspace/Tasmota/tasmota/tasmota_ca.ino" -# 24 "/workspace/Tasmota/tasmota/tasmota_ca.ino" -#if defined(USE_TLS) && defined(USE_MQTT_TLS_CA_CERT) -# 37 "/workspace/Tasmota/tasmota/tasmota_ca.ino" -static const unsigned char PROGMEM LetsEncrypt_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 LetsEncrypt_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 LetsEncrypt_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { - { (unsigned char *)LetsEncrypt_DN, sizeof LetsEncrypt_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)LetsEncrypt_RSA_N, sizeof LetsEncrypt_RSA_N, - (unsigned char *)LetsEncrypt_RSA_E, sizeof LetsEncrypt_RSA_E, - } } - } -}; -# 100 "/workspace/Tasmota/tasmota/tasmota_ca.ino" -const unsigned char PROGMEM AmazonRootCA1_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 AmazonRootCA1_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 AmazonRootCA1_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { - { (unsigned char *)AmazonRootCA1_DN, sizeof AmazonRootCA1_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)AmazonRootCA1_RSA_N, sizeof AmazonRootCA1_RSA_N, - (unsigned char *)AmazonRootCA1_RSA_E, sizeof AmazonRootCA1_RSA_E, - } } - } -}; - - -const br_x509_trust_anchor PROGMEM Tasmota_TA[] = { - { - { (unsigned char *)LetsEncrypt_DN, sizeof LetsEncrypt_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)LetsEncrypt_RSA_N, sizeof LetsEncrypt_RSA_N, - (unsigned char *)LetsEncrypt_RSA_E, sizeof LetsEncrypt_RSA_E, - } } - } - } - , - { - { (unsigned char *)AmazonRootCA1_DN, sizeof AmazonRootCA1_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)AmazonRootCA1_RSA_N, sizeof AmazonRootCA1_RSA_N, - (unsigned char *)AmazonRootCA1_RSA_E, sizeof AmazonRootCA1_RSA_E, - } } - } - } -}; - -const size_t Tasmota_TA_size = ARRAY_SIZE(Tasmota_TA); -# 187 "/workspace/Tasmota/tasmota/tasmota_ca.ino" -const unsigned char GoDaddyCAG2_DN[] PROGMEM = { - 0x30, 0x3E, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, - 0x18, 0x44, 0x6F, 0x6D, 0x61, 0x69, 0x6E, 0x20, 0x43, 0x6F, 0x6E, 0x74, - 0x72, 0x6F, 0x6C, 0x20, 0x56, 0x61, 0x6C, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, - 0x61, 0x70, 0x69, 0x2E, 0x74, 0x65, 0x6C, 0x65, 0x67, 0x72, 0x61, 0x6D, - 0x2E, 0x6F, 0x72, 0x67 -}; - -const unsigned char GoDaddyCAG2_RSA_N[] PROGMEM = { - 0xB4, 0xA3, 0x16, 0x9E, 0x5C, 0x57, 0xC9, 0x89, 0x65, 0xED, 0xEA, 0x78, - 0x0B, 0xAE, 0x8A, 0x58, 0x2F, 0xAE, 0x5A, 0xC8, 0x6E, 0x49, 0x8D, 0xFC, - 0x57, 0xA5, 0x98, 0x88, 0x78, 0x2E, 0x0B, 0x3C, 0x40, 0x3C, 0x21, 0x2E, - 0x9A, 0x94, 0x98, 0x33, 0xA7, 0xE3, 0x42, 0xA7, 0x85, 0xFA, 0xD0, 0x73, - 0x84, 0x01, 0x1C, 0x72, 0x39, 0x37, 0x23, 0xB5, 0x56, 0x1D, 0x43, 0xA5, - 0x71, 0x14, 0x08, 0x24, 0xA5, 0x39, 0xCC, 0xDE, 0x58, 0x53, 0x94, 0x8E, - 0x2A, 0x42, 0xA7, 0x4E, 0x2D, 0x07, 0x32, 0x9E, 0xBA, 0x8B, 0xD3, 0x2A, - 0xA9, 0x9E, 0xC0, 0xE3, 0xCE, 0x9A, 0x10, 0x96, 0x45, 0x58, 0x7A, 0xC7, - 0x1E, 0x45, 0x14, 0x23, 0x92, 0xBB, 0x54, 0x82, 0x88, 0x94, 0x49, 0xB6, - 0xBE, 0x81, 0x21, 0x00, 0x29, 0x6D, 0xC9, 0xCE, 0x8B, 0x39, 0x3A, 0xDC, - 0x35, 0x15, 0xD9, 0xEB, 0x47, 0x9C, 0xEF, 0xBA, 0x09, 0x0E, 0x16, 0xE4, - 0xD9, 0xEB, 0x72, 0x30, 0xFA, 0x49, 0xAB, 0x98, 0x31, 0x7C, 0xB3, 0xAC, - 0x2B, 0x29, 0x91, 0x87, 0x08, 0x41, 0x72, 0x5E, 0x35, 0xC7, 0x87, 0x04, - 0x22, 0xF5, 0x48, 0x76, 0x30, 0x6D, 0x88, 0xDF, 0xF2, 0xA5, 0x29, 0x13, - 0x70, 0xB3, 0x87, 0x02, 0xD5, 0x6B, 0x58, 0xB1, 0xE8, 0x73, 0xC7, 0xE4, - 0xEF, 0x79, 0x86, 0xA4, 0x07, 0x5F, 0x67, 0xB4, 0x79, 0x8D, 0xA4, 0x25, - 0x01, 0x82, 0x8C, 0xE0, 0x30, 0x17, 0xCB, 0x4B, 0x5C, 0xFB, 0xEB, 0x4C, - 0x12, 0x51, 0xB9, 0xC9, 0x04, 0x1F, 0x7E, 0xD2, 0xF8, 0xBA, 0xF5, 0x35, - 0x8D, 0x8A, 0x1C, 0x37, 0x82, 0xF0, 0x15, 0x73, 0x00, 0x6E, 0x3D, 0x1C, - 0x76, 0x8B, 0x01, 0x74, 0x81, 0x3D, 0xE4, 0x2C, 0xA7, 0xCC, 0x2F, 0x66, - 0xDC, 0x44, 0xA8, 0x27, 0x3F, 0xEA, 0xD0, 0xA7, 0xA8, 0xF1, 0xCB, 0xEA, - 0xDA, 0x07, 0x38, 0xBD -}; - -const unsigned char GoDaddyCAG2_RSA_E[] PROGMEM = { - 0x01, 0x00, 0x01 -}; - -const br_x509_trust_anchor GoDaddyCAG2_TA PROGMEM = { - { (unsigned char *)GoDaddyCAG2_DN, sizeof GoDaddyCAG2_DN }, - 0, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)GoDaddyCAG2_RSA_N, sizeof GoDaddyCAG2_RSA_N, - (unsigned char *)GoDaddyCAG2_RSA_E, sizeof GoDaddyCAG2_RSA_E, - } } - } -}; - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_01_webserver.ino" -# 20 "/workspace/Tasmota/tasmota/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 = (MESSZ / 2) - 100; - -const uint16_t HTTP_REFRESH_TIME = 2345; -const uint16_t HTTP_RESTART_RECONNECT_TIME = 9000; -const uint16_t 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, UPL_TASMOTACLIENT, UPL_EFR32 }; - -#ifdef USE_UNISHOX_COMPRESSION -#ifdef USE_JAVASCRIPT_ES6 - -const size_t HTTP_HEADER1_SIZE = 377; -const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" - "\x3C\x7C\x3F\xB2\xEC\xD7\xE6\x86\x7D\x78\xFE\xCB\xB3\x5F\x9A\x1A\x0C\x2B\xF7\x8F" - "\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6" - "\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E" - "\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1" - "\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61" - "\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3" - "\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50" - "\x54\x75\x56\x1D\x54\x30\xEA\x18\x19\xF0\xFB\x3E\xCF\x0C\x71\xF3\xC7\xC3\xF0\x4C" - "\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35\xF5\x10\xE3\x22\xD1\x0E\xEF\x8E\xF1\xE0" - "\xD5\xE0\x48\xBA\x6A\x16\xFE\x64\x5E\x61\x30\xEB\x3E\x77\x7C\x77\x8F\x1E\x18\x7C" - "\xD3\xE1\xF8\xC7\x1D\xDD\x3B\xC7\x4A\x32\x18\xCF\x87\x74\x11\xA4\x1F\x0F\x87\xDD" - "\x33\x65\x1F\x67\x68\xFB\x19\x7E\xF0\xFE\x7C\x43\xEC\xF3\x04\x19\xC7\x78\xF0\x3E" - "\x11\xF0\xC1\xF0\xFC\x1F\xDE\x13\x07\xCE\x96\x20\x84\xCC\xDF\x51\x05\xBE\xA7\xCF" - "\xE7\x74\xFB\x0B\x2C\x43\xEC\xEA\x30\x77\x8F\x06"; -#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() -#else -const size_t HTTP_HEADER1_SIZE = 431; -const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" - "\x3C\x7C\x3F\xB2\xEC\xD7\xE6\x86\x7D\x78\xFE\xCB\xB3\x5F\x9A\x1A\x0C\x2B\xF7\x8F" - "\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6" - "\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E" - "\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1" - "\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61" - "\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3" - "\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50" - "\x54\x75\x56\x1D\x54\x30\xEA\x18\x19\xF0\xFB\x3E\xCF\x06\x05\xF0\x75\xB9\xC9\x8E" - "\x3B\xBE\x3B\xC7\xB7\xEE\x85\xFF\x90\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B" - "\xEA\x21\xC6\x45\xA2\x1D\xDF\x1D\xE3\xC1\xEE\x04\x4C\x38\xD5\xE0\x4F\xC3\x8D\x42" - "\xDF\xCC\x8B\xCC\x26\x1D\x67\xC1\x27\x0D\xF0\xC3\xBB\xA7\x78\xF6\xB1\xC7\x77\x4E" - "\xF1\xD2\x8C\x86\x33\xE1\xDD\x04\x69\x07\xC3\xE1\xF7\x4C\xD9\x47\xD9\xDA\x3E\xC6" - "\x5F\xBC\x3F\x9F\x10\xFB\x3C\xC1\x06\x70\x23\xE3\xE3\xE1\x1D\xD3\x07\x78\xF6\x8F" - "\xEF\x09\x83\xE7\x4B\x10\x42\x66\x6F\xA8\x82\xDF\x53\xE7\xF3\xBA\x7D\x85\x96\x21" - "\xF6\x75\x18\x3B\xC7\x83\xDC"; -#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() -#endif -#else -const char HTTP_HEADER1[] PROGMEM = - "" - "" - "" - "" - "%s - %s" - - ""; -#endif - -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_HEAD_STYLE1_SIZE = 591; -const char HTTP_HEAD_STYLE1_COMPRESSED[] PROGMEM = "\x3D\x3D\x46\x41\x33\xF0\x4D\x33\x3A\x8C\x6B\x08\x4F\x3A\x3A\xB7\x86\x0B\xA3\xAB" - "\xCC\x26\x1D\x1E\xD1\x96\x20\x9B\xC3\xC7\x99\xCD\x21\x86\xC3\xC1\x8C\xEA\x3A\xFD" - "\xA6\xD6\x79\x9C\x84\xC6\x9E\x0F\x70\x21\xE1\xA7\xB4\x75\x86\x68\x3D\xFC\x17\xC2" - "\x1E\x67\x91\xF4\x71\xF1\x1B\x0F\x07\xB8\x61\xED\x1B\x7F\x1E\xDE\x3C\xCE\x33\xA6" - "\x93\x1A\x8E\x33\xC1\xEE\x2D\xE1\x82\xE8\xF6\x8F\xE8\x94\x28\xF3\x39\x1B\x3E\x8F" - "\xA3\xC1\x0E\xC3\x61\xD7\xED\x36\xEF\x0F\x1E\x63\xB3\xE2\x3F\x9D\x63\xB0\xD8\x78" - "\x3A\xC7\xD8\xE3\x4D\xA3\xAC\x14\xAD\x0D\xC3\x68\x29\x57\x04\xCD\x84\x3C\x0B\x3E" - "\x08\x7B\x6E\xF0\xC1\x74\x7B\xD4\x64\x31\x9F\x03\x14\xC3\x34\x1D\x86\xC3\xDF\x04" - "\x1E\x11\x41\x06\x8F\xEC\x4D\xC3\xDF\x04\x3D\xF1\x8D\x3C\x02\x0F\x03\x87\x5F\xF4" - "\x78\x55\x1E\x67\x38\x86\x1B\x0F\x06\x6F\xF5\xA1\xD8\x47\x5D\x85\xA3\xDC\x79\x9D" - "\x67\x21\x0C\x04\x9C\xCF\xF7\xC3\xCC\x10\xF1\xE3\x89\x1F\x47\xD1\xE0\xF7\x10\x21" - "\x71\x3E\x09\x1C\x28\x82\xC7\x2A\x01\x54\xCD\x95\x7F\x76\x7B\x7E\xFD\xA6\xD6\x79" - "\x82\x1E\xA0\x78\x04\x2C\xC8\xE7\xCF\xA3\xE8\xF0\x42\x9E\x8F\x0A\xA3\xCC\xE5\xCF" - "\x90\xC3\x61\xE0\x11\xF8\xFA\xC3\x37\xF3\x01\x60\xF9\xE7\x62\xEB\x01\x6B\x45\x1D" - "\x82\x19\x1E\xDA\x66\xCA\x04\x2E\x0A\x83\x7D\x4F\xE0\x83\xC9\xE9\x8B\x1B\xA1\x19" - "\x1E\x66\x6F\xE2\x5F\x59\xD5\xEB\xEF\x1D\x7E\x7F\xD3\x2A\x01\x9B\x98\x1E\xEA\x10" - "\x11\x39\x7D\x38\xC8\x61\xB0\xF0\x7B\x8D"; -#define HTTP_HEAD_STYLE1 Decompress(HTTP_HEAD_STYLE1_COMPRESSED,HTTP_HEAD_STYLE1_SIZE).c_str() -#else -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_SLIDER_GRADIENT[] PROGMEM = - "
" - "" - "
"; -const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = - "
" D_CLOSE "" D_OPEN "
" - "
"; - -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_AP2_SSID " (" STA_SSID2 ")

" - "


" - "

" D_HOSTNAME " (%s)

" - "

" D_CORS_DOMAIN "

"; - -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 " " - "

" - "

" - "
" - "
" - "

" - "
" - "
" - "
" - "

" - "
"; - -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_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; - -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 - "|" D_UPLOAD_ERR_14 - ; - -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); - last_source = source; - ExecuteCommand(svalue, SRC_IGNORE); -} - - -typedef struct WebServerDispatch_t { - char uri[3]; - uint8_t method; - void (*handler)(void); -} WebServerDispatch_t; - -const WebServerDispatch_t WebServerDispatch[] PROGMEM = { - { "", HTTP_ANY, HandleRoot }, - { "up", HTTP_ANY, HandleUpgradeFirmware }, - { "u1", HTTP_ANY, HandleUpgradeFirmwareStart }, - { "u2", HTTP_OPTIONS, HandlePreflightRequest }, - { "u3", HTTP_ANY, HandleUploadDone }, - { "cs", HTTP_GET, HandleConsole }, - { "cs", HTTP_OPTIONS, HandlePreflightRequest }, - { "cm", HTTP_ANY, HandleHttpCommand }, -#ifndef FIRMWARE_MINIMAL - { "cn", HTTP_ANY, HandleConfiguration }, - { "md", HTTP_ANY, HandleModuleConfiguration }, - { "wi", HTTP_ANY, HandleWifiConfiguration }, - { "lg", HTTP_ANY, HandleLoggingConfiguration }, - { "tp", HTTP_ANY, HandleTemplateConfiguration }, - { "co", HTTP_ANY, HandleOtherConfiguration }, - { "dl", HTTP_ANY, HandleBackupConfiguration }, - { "rs", HTTP_ANY, HandleRestoreConfiguration }, - { "rt", HTTP_ANY, HandleResetConfiguration }, - { "in", HTTP_ANY, HandleInformation }, -#endif -}; - -void WebServer_on(const char * prefix, void (*func)(void), uint8_t method = HTTP_ANY) { - Webserver->on((const __FlashStringHelper *) prefix, (HTTPMethod) method, func); -} - -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); - - for (uint32_t i=0; ionNotFound(HandleNotFound); - Webserver->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); -#ifndef FIRMWARE_MINIMAL - XdrvCall(FUNC_WEB_ADD_HANDLER); - XsnsCall(FUNC_WEB_ADD_HANDLER); -#endif - } - Web.reset_web_log_flag = false; - - Webserver->begin(); - } - if (Web.state != type) { -#if LWIP_IPV6 - String ipv6_addr = WifiGetIPv6(); - if (ipv6_addr!="") { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str(), ipv6_addr.c_str()); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); - } -#else - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); -#endif - 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) { - - WifiSetMode(WIFI_AP_STA); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION)); - } else { - - WifiSetMode(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, WIFI_AP_PASSPHRASE, channel, 0, 1); - 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 (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) { - return Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); - } 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 HttpHeaderCors(void) -{ - if (strlen(SettingsText(SET_CORS))) { - Webserver->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); - } -} - -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")); - HttpHeaderCors(); -} - - - - - -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(); - Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); - WSSend(code, ctype, ""); - Web.chunk_buffer = ""; -} - -void _WSContentSend(const String& content) -{ - size_t len = content.length(); - Webserver->sendContent(content); - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("WSContentSend")); -#endif - DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d/%d"), len, sizeof(mqtt_data)); -} - -void WSContentFlush(void) -{ - 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); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); - -#ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); - } -#endif - - _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); - -#ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_PD size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); - } -#endif - - 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 && strlen(SettingsText(SET_WEBPWD)) && !Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) { - return Webserver->requestAuthentication(); - } - - WSContentBegin(200, CT_HTML); - - if (title != nullptr) { -#ifdef USE_UNISHOX_COMPRESSION - WSContentSend_P(HTTP_HEADER1, D_HTML_LANGUAGE, SettingsText(SET_DEVICENAME), title); -#else - WSContentSend_P(HTTP_HEADER1, SettingsText(SET_DEVICENAME), title); -#endif - } -} - -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), - WebColor(COL_BUTTON)); -#ifdef USE_ZIGBEE - WSContentSend_P(HTTP_HEAD_STYLE_ZIGBEE); -#endif - if (formatP != nullptr) { - - va_list arg; - va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); - -#ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSendStyle_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); - } -#endif - - _WSContentSendBuffer(); - } - WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT), -#ifdef FIRMWARE_MINIMAL - WebColor(COL_TEXT_WARNING), -#endif - WebColor(COL_TITLE), - ModuleName().c_str(), SettingsText(SET_DEVICENAME)); - 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)

"), - NetworkHostname(), - (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 WSContentSend_THD(const char *types, float f_temperature, float f_humidity) -{ - char parameter[FLOATSZ]; - dtostrfd(f_temperature, Settings.flag2.temperature_resolution, parameter); - WSContentSend_PD(HTTP_SNS_TEMP, types, parameter, TempUnit()); - dtostrfd(f_humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_PD(HTTP_SNS_HUM, types, parameter); - dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings.flag2.temperature_resolution, parameter); - WSContentSend_PD(HTTP_SNS_DEW, types, parameter, TempUnit()); -} - -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_TIME, HTTP_RESTART_RECONNECT_TIME); - 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(); -} - -#ifdef USE_LIGHT -void WebSliderColdWarm(void) -{ - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "a", - "#eff", "#f81", - 1, - 153, 500, - LightGetColorTemp(), - 't', 0); -} -#endif - -void HandleRoot(void) -{ - if (CaptivePortal()) { return; } - - if (Webserver->hasArg("rst")) { - WebRestart(0); - return; - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg("USER1")) && !(Webserver->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { - HandleWifiLogin(); - } else { - if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg("USER1") == WEB_USERNAME ) && (Webserver->arg("PASS1") == SettingsText(SET_WEBPWD) )) || 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[33]; - - 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 - WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); - - WSContentSendStyle(); - - WSContentSend_P(PSTR("
")); - if (devices_present) { -#ifdef USE_LIGHT - if (light_type) { - uint8_t light_subtype = light_type &7; - if (!Settings.flag3.pwm_multi_channels) { - bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); - - if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { - WebSliderColdWarm(); - } - - if (light_subtype > 2) { - uint16_t hue; - uint8_t sat; - LightGetHSB(&hue, &sat, nullptr); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "b", - "#800", PSTR("#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800"), - 2, - 1, 359, - hue, - 'h', 0); - - uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); - char scolor[8]; - snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); - uint8_t red, green, blue; - LightHsToRgb(hue, 255, &red, &green, &blue); - snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "s", - scolor, stemp, - 3, - 0, 100, - changeUIntScale(sat, 0, 255, 0, 100), - 'n', 0); - } - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "c", - "#000", "#fff", - 4, - Settings.flag3.slider_dimmer_stay_on, 100, - Settings.light_dimmer, - 'd', 0); - - if (split_white) { - if (LST_RGBCW == light_subtype) { - WebSliderColdWarm(); - } - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "f", - "#000", "#fff", - 5, - Settings.flag3.slider_dimmer_stay_on, 100, - LightGetDimmer(2), - 'w', 0); - } - } else { - uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; - stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; - for (uint32_t i = 0; i < pwm_channels; i++) { - stemp[1]++; - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - stemp, - "#000", "#fff", - i+1, - 1, 100, - changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), - 'e', i+1); - } - } - } -#endif -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); - } - } -#endif - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, - (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : 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, - (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, - ""); - } - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(idx)) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), - ""); - continue; - } -#endif - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", - (set_button) ? "" : (devices_present > 1) ? stemp : ""); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("
%s
")); - } -#ifdef USE_TUYA_MCU - if (IsModuleTuya()) { - uint8_t modeset = 0; - if (AsModuleTuyaMS()) { - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); - snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); - WSContentSend_P(HTTP_DEVICE_CONTROL, 26, devices_present + 1, - (strlen(SettingsText(SET_BUTTON1 + devices_present))) ? SettingsText(SET_BUTTON1 + devices_present) : stemp, ""); - WSContentSend_P(PSTR("")); - modeset = 1; - } - if (IsTuyaFanCtrl()) { - uint8_t device = devices_present + modeset; - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); - for (uint32_t i = device + 1; i <= (TuyaFanSpeeds() + device) + 1; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i - (device + 1)); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i, - (strlen(SettingsText(SET_BUTTON1 + i))) ? SettingsText(SET_BUTTON1 + i) : stemp, ""); - } - WSContentSend_P(PSTR("")); - } - } -#endif -#ifdef USE_SONOFF_RF - 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++; - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); - WSContentSend_P(PSTR(""), idx, - (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); - } - } - WSContentSend_P(PSTR("")); - } -#endif - -#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]; - char webindex[5]; - - 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 -#ifdef USE_TUYA_MCU - if (IsModuleTuya()) { - uint8_t FuncIdx = 0; - if (device <= devices_present) { - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); - } else { - if (AsModuleTuyaMS() && device == devices_present + 1) { - uint8_t dpId = TuyaGetDpId(TUYA_MCU_FUNC_MODESET); - snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend4 %d,%d"), dpId, !TuyaModeSet()); - ExecuteCommand(svalue, SRC_WEBGUI); - } - if (IsTuyaFanCtrl()) { - uint8_t dpId = 0; - for (uint32_t i = 0; i <= 3; i++) { - if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { - dpId = TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i); - } - } - if ((AsModuleTuyaMS() && device != devices_present + 1) || !AsModuleTuyaMS()) { - if (AsModuleTuyaMS()) {FuncIdx = 1;} - snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend2 %d,%d"), dpId, (device - (devices_present + FuncIdx) - 1)); - ExecuteCommand(svalue, SRC_WEBGUI); - } - } - } - } else { -#endif -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(device)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_STOPOPEN) : PSTR(D_CMND_SHUTTER_STOPCLOSE)); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } else { -#endif - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); -#ifdef USE_SHUTTER - } -#endif -#ifdef USE_SONOFF_IFAN - } -#endif -#ifdef USE_TUYA_MCU - } -#endif - } -#ifdef USE_LIGHT - WebGetArg("d0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("w0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - uint32_t light_device = LightDevice(); - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - for (uint32_t j = 0; j < pwm_channels; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j +1); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j +light_device, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } - WebGetArg("t0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("h0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("n0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#endif -#ifdef USE_SHUTTER - for (uint32_t j = 1; j <= shutters_present; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } -#endif -#ifdef USE_SONOFF_RF - WebGetArg("k", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#endif - WSContentBegin(200, CT_HTML); - WSContentSend_P(PSTR("{t}")); - XsnsCall(FUNC_WEB_SENSOR); - XdrvCall(FUNC_WEB_SENSOR); - - 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("")); - } -#ifdef USE_TUYA_MCU - if (IsModuleTuya()) { - uint32_t fanspeed = TuyaFanState(); - uint32_t modeset = TuyaModeSet(); - if (IsTuyaFanCtrl() && !AsModuleTuyaMS()) { - WSContentSend_P(PSTR("
" D_JSON_IRHVAC_FANSPEED ": %d
"), fanspeed); - } else if (!IsTuyaFanCtrl() && AsModuleTuyaMS()) { - WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d
"), modeset); - } else if (IsTuyaFanCtrl() && AsModuleTuyaMS()) { - WSContentSend_P(PSTR("
" D_JSON_IRHVAC_MODE ": %d - " D_JSON_IRHVAC_FANSPEED ": %d
"), modeset, fanspeed); - } - } -#endif - WSContentEnd(); - - return true; -} - -#ifdef USE_SHUTTER -int32_t IsShutterWebButton(uint32_t idx) { - - int32_t ShutterWebButton = 0; - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { - ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); - break; - } - } - } - return ShutterWebButton; -} -#endif - - - -#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 WSContentSendNiceLists(uint32_t option) { - char stemp[30]; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { - if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); - } - uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); - } - WSContentSend_P(PSTR("\";")); - - WSContentSend_P(PSTR("hs=[")); - uint32_t midx; - bool first_done = false; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { - midx = pgm_read_word(kGpioNiceList + i); - if (midx & 0x001F) { - if (first_done) { WSContentSend_P(PSTR(",")); } - WSContentSend_P(PSTR("%d"), midx); - first_done = true; - } - } -#ifdef ESP8266 -#ifdef USE_ADC - for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { - midx = pgm_read_word(kAdcNiceList + i); - if (midx & 0x001F) { - if (first_done) { WSContentSend_P(PSTR(",")); } - WSContentSend_P(PSTR("%d"), midx); - first_done = true; - } - } -#endif -#endif - WSContentSend_P(PSTR("];")); -} - -#ifdef ESP8266 -#ifdef USE_ADC -void WSContentSendAdcNiceList(uint32_t option) { - char stemp[30]; - WSContentSend_P(PSTR("os=\"")); - for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { - if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); - } - uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); - } -} -#endif -#endif - - - -void HandleTemplateConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg("save")) { - TemplateSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - - 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 < ARRAY_SIZE(cmodule.io); i++) { - if (!FlashPin(i)) { - 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); - - WSContentSendNiceLists(1); - - WSContentSend_P(HTTP_SCRIPT_TEMPLATE2); - -#ifdef ESP8266 -#ifdef USE_ADC - WSContentSendAdcNiceList(1); - WSContentSend_P(HTTP_SCRIPT_TEMPLATE3); -#endif -#endif - - WSContentSend_P(HTTP_SCRIPT_TEMPLATE4); - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - uint32_t midx = pgm_read_byte(kModuleNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), midx +1); - } - WSContentSend_P(HTTP_SCRIPT_TEMPLATE5); - - 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 < MAX_GPIO_PIN; i++) { - if (!FlashPin(i)) { - WSContentSend_P(PSTR("" D_GPIO "%d"), - ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:150px'" : "", i, i); - WSContentSend_P(PSTR(""), i); - } - } - WSContentSend_P(PSTR("")); - - gpio_flag flag = ModuleFlag(); - if (flag.data) { - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); - } - - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -uint16_t WebGetGpioArg(uint32_t i) { - char webindex[5]; - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); - char tmp[8]; - WebGetArg(webindex, tmp, sizeof(tmp)); - uint32_t gpio = (!strlen(tmp)) ? 0 : atoi(tmp); - char webindex2[5]; - snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), i); - char tmp2[8]; - WebGetArg(webindex2, tmp2, sizeof(tmp2)); - uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1; - gpio += value2; - return gpio; -} - -void TemplateSaveSettings(void) -{ - char tmp[TOPSZ]; - char svalue[300]; - - 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 < ARRAY_SIZE(Settings.user_template.gp.io); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", WebGetGpioArg(j)); - j++; - } - - uint32_t flag = 0; - char webindex[5]; - 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; - 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; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - - char stemp[30]; - uint32_t midx; - myio cmodule; - ModuleGpios(&cmodule); - - WSContentStart_P(S_CONFIGURE_MODULE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - - WSContentSend_P(PSTR("function sl(){os=\"")); - 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_INDEX, midx, AnyModuleName(midx).c_str(), vidx); - } - WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings.module); - - WSContentSendNiceLists(0); - - for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); - } - } - -#ifdef ESP8266 -#ifdef USE_ADC - WSContentSendAdcNiceList(0); - WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_gp.io[(sizeof(myio) / 2) -1]); -#endif -#endif - - WSContentSend_P(PSTR("}wl(sl);")); - - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); - WSContentSend_P(PSTR("%s " D_GPIO "%d"), - (WEMOS==my_module_type)?stemp:"", i, i, i); - WSContentSend_P(PSTR(""), i); - } - } - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void ModuleSaveSettings(void) -{ - char tmp[8]; - - 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 < ARRAY_SIZE(cmodule.io); i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = GPIO_NONE; - } else { - if (ValidGPIO(i, cmodule.io[i])) { - Settings.my_gp.io[i] = WebGetGpioArg(i); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } - - 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]); - uint32_t cschn = WiFi.channel(indices[i]); - for (uint32_t j = i + 1; j < n; j++) { - if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(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; } - int32_t rssi = WiFi.RSSI(indices[i]); - 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]), rssi); - int quality = WifiGetRssiAsQuality(rssi); - int auth = WiFi.encryptionType(indices[i]); - char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), - HtmlEscape(WiFi.SSID(indices[i])).c_str(), - WiFi.channel(indices[i]), - GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, rssi - ); - delay(0); - - } - WSContentSend_P(PSTR("
")); - } - } else { - WSContentSend_P(PSTR("
")); - } - - - WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); - WSContentSend_P(HTTP_FORM_END); - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESTORE); - WSContentButton(BUTTON_RESET_CONFIGURATION); -#endif - WSContentSpaceButton(BUTTON_RESTART); - } else { - WSContentSpaceButton(BUTTON_CONFIGURATION); - } - WSContentStop(); -} - -void WifiSaveSettings(void) -{ - char tmp[TOPSZ]; - - WebGetArg("h", tmp, sizeof(tmp)); - SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - WebGetArg("c", tmp, sizeof(tmp)); - SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); - WebGetArg("s1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); - WebGetArg("s2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); - WebGetArg("p1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); - WebGetArg("p2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), - SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); -} - - - -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[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)

")); - } - WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void LoggingSaveSettings(void) -{ - char tmp[TOPSZ]; - - 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)); - Settings.mqttlog_level = (!strlen(tmp)) ? MQTT_LOG_LEVEL : atoi(tmp); - WebGetArg("l3", tmp, sizeof(tmp)); - SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); - WebGetArg("lh", tmp, sizeof(tmp)); - SettingsUpdateText(SET_SYSLOG_HOST, (!strlen(tmp)) ? SYS_LOG_HOST : tmp); - 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_MQTTLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), - Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, SettingsText(SET_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" : "", - SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); - - 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 : "", - SettingsText(SET_FRIENDLYNAME1 + i)); - } - -#ifdef USE_EMULATION -#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) - 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 -#endif - - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void OtherSaveSettings(void) -{ - char tmp[300]; - char webindex[5]; - char friendlyname[TOPSZ]; - char message[LOGSZ]; - - WebGetArg("dn", tmp, sizeof(tmp)); - SettingsUpdateText(SET_DEVICENAME, (!strlen(tmp)) ? "" : (!strcmp(tmp,"1")) ? SettingsText(SET_FRIENDLYNAME1) : tmp); - WebGetArg("wp", tmp, sizeof(tmp)); - SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); - Settings.flag.mqtt_enabled = Webserver->hasArg("b1"); -#ifdef USE_EMULATION - UdpDisconnect(); -#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) - WebGetArg("b2", tmp, sizeof(tmp)); - Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); -#endif -#endif - - snprintf_P(message, sizeof(message), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_DEVICENAME " %s, " D_CMND_FRIENDLYNAME), - GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation, SettingsText(SET_DEVICENAME)); - 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); - SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); - snprintf_P(message, sizeof(message), PSTR("%s%s %s"), message, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); - } - AddLog_P(LOG_LEVEL_INFO, message); - - WebGetArg("t1", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); - ExecuteWebCommand(message, 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[TOPSZ]; - - - - - 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); - } - } - - myClient.write((const char*)settings_buffer, sizeof(Settings)); - - 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); - if (WifiIsInManagerMode()) { - WSContentSpaceButton(BUTTON_MAIN); - } else { - 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_CORE_RELEASE "/%s"), ESP.getSdkVersion()); - WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); -#ifdef ESP8266 - WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); -#else - WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d"), Settings.save_flag); -#endif - 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, SettingsText(SET_FRIENDLYNAME1 +i)); - } - WSContentSend_P(PSTR("}1}2 ")); -#ifdef ESP32 -#ifdef USE_ETHERNET - if (static_cast(EthernetLocalIP()) != 0) { - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? ".local" : ""); - WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str()); - WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (eth)}2%s"), EthernetLocalIP().toString().c_str()); - WSContentSend_P(PSTR("}1
}2
")); - } -#endif -#endif - if (Settings.flag4.network_wifi) { - int32_t rssi = WiFi.RSSI(); - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi); - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : ""); -#if LWIP_IPV6 - String ipv6_addr = WifiGetIPv6(); - if (ipv6_addr != "") { - WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str()); - } -#endif - if (static_cast(WiFi.localIP()) != 0) { - WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); - WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (wifi)}2%s"), WiFi.localIP().toString().c_str()); - WSContentSend_P(PSTR("}1
}2
")); - } - } - if (!global_state.network_down) { - 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()); - } - if ((WiFi.getMode() >= WIFI_AP) && (static_cast(WiFi.softAPIP()) != 0)) { - WSContentSend_P(PSTR("}1
}2
")); - WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); - WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (AP)}2%s"), WiFi.softAPIP().toString().c_str()); - WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); - } - WSContentSend_P(PSTR("}1}2 ")); - if (Settings.flag.mqtt_enabled) { - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST)); - WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); -#ifdef USE_MQTT_TLS - WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings.flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); -#endif - WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); - WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); - WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); - uint32_t real_index = SET_MQTT_GRP_TOPIC; - for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { - if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - if (strlen(SettingsText(real_index +i))) { - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 1 +i, GetGroupTopic_P(stopic, "", real_index +i)); - } - } - 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, "")); - WSContentSend_P(PSTR("}1" D_MQTT_NO_RETAIN "}2%s"), Settings.flag4.mqtt_no_retain ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); - } 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()); -#ifdef ESP8266 - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); -#endif - 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); -#ifdef ESP32 - if (psramFound()) { - WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%dkB"), ESP.getPsramSize() / 1024); - WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%dkB"), ESP.getFreePsram() / 1024); - } -#endif - 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, SettingsText(SET_OTAURL)); - 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[TOPSZ + 10]; - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); - WifiConfigCounter(); - - char otaurl[TOPSZ]; - 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_TIME, HTTP_OTA_RESTART_RECONNECT_TIME); - 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; } - -#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) - if (!Web.upload_error) { - - if (ZigbeeUploadOtaReady()) { - HandleZigbeeXfer(); - return; - } - } -#endif - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); - - char error[100]; - - WifiConfigCounter(); - restart_flag = 0; - MqttRetryCounter(0); -#ifdef USE_COUNTER - CounterInterruptDisable(false); -#endif - - WSContentStart_P(S_INFORMATION); - if (!Web.upload_error) { - uint32_t javascript_settimeout = HTTP_OTA_RESTART_RECONNECT_TIME; -#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) - if (ZigbeeUploadFinish()) { - javascript_settimeout = 10000; - } -#endif - WSContentSend_P(HTTP_SCRIPT_RELOAD_TIME, javascript_settimeout); - } - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

"), WebColor(COL_TEXT_WARNING)); -#ifdef USE_RF_FLASH - if (Web.upload_error < 15) { -#else - if ((Web.upload_error < 10) || (14 == Web.upload_error)) { - if (14 == Web.upload_error) { 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)); - restart_flag = 2; -#ifdef USE_TASMOTA_CLIENT - if (TasmotaClient_GetFlagFlashing()) { - WSContentSend_P(PSTR("
" D_TRANSFER_STARTED " ...
")); - restart_flag = 0; - } -#endif - if (restart_flag) { - WSContentSend_P(HTTP_MSG_RSTRT); - ShowWebSource(SRC_WEBGUI); - } - } - SettingsBufferFree(); - WSContentSend_P(PSTR("

")); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); - -#ifdef USE_TASMOTA_CLIENT - if (TasmotaClient_GetFlagFlashing()) { - TasmotaClient_Flash(); - } -#endif -} - -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_COUNTER - CounterInterruptDisable(true); -#endif -#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 { -#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) -#ifdef ESP8266 - if ((SONOFF_ZB_BRIDGE == my_module_type) && (upload.buf[0] == 0xEB)) { -#else - if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX) && (upload.buf[0] == 0xEB)) { -#endif - Update.end(); - Web.upload_file_type = UPL_EFR32; - - Web.upload_error = ZigbeeUploadInit(); - if (Web.upload_error != 0) { return; } - } else -#endif -#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 -#ifdef USE_TASMOTA_CLIENT - if (TasmotaClient_Available() && (upload.buf[0] == ':')) { - Update.end(); - Web.upload_file_type = UPL_TASMOTACLIENT; - - Web.upload_error = TasmotaClient_UpdateInit(); - if (Web.upload_error != 0) { return; } - } else -#endif - { - if ((upload.buf[0] != 0xE9) && (upload.buf[0] != 0x1F)) { - Web.upload_error = 3; - return; - } - if (0xE9 == upload.buf[0]) { - uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); - if (bin_flash_size > ESP.getFlashChipRealSize()) { - Web.upload_error = 4; - return; - } - - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "File type %d"), Web.upload_file_type); - } - } - 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++; - } - } -#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) - else if (UPL_EFR32 == Web.upload_file_type) { - - if (!ZigbeeUploadWriteBuffer(upload.buf, upload.currentSize)) { - Web.upload_error = 9; - return; - } - } -#endif -#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 -#ifdef USE_TASMOTA_CLIENT - else if (UPL_TASMOTACLIENT == Web.upload_file_type) { - TasmotaClient_WriteBuffer(upload.buf, upload.currentSize); - } -#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) { -#ifdef ESP8266 - valid_settings = (0 == settings_buffer[0xF36]); -#endif -#ifdef ESP32 - valid_settings = (1 == settings_buffer[0xF36]); -#endif - } - - 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; - } - } -#if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) - else if (UPL_EFR32 == Web.upload_file_type) { - - ZigbeeUploadDone(); - Web.upload_file_type = UPL_TASMOTA; - } -#endif -#ifdef USE_RF_FLASH - else if (UPL_EFM8BB1 == Web.upload_file_type) { - - Web.upload_file_type = UPL_TASMOTA; - } -#endif -#ifdef USE_TASMOTA_CLIENT - else if (UPL_TASMOTACLIENT == Web.upload_file_type) { - - TasmotaClient_SetFlagFlashing(true); - Web.upload_file_type = UPL_TASMOTA; - } -#endif - else { - if (!Update.end(true)) { - if (_serialoutput) { Update.printError(Serial); } - Web.upload_error = 6; - return; - } - if (!VersionCompatible()) { - Web.upload_error = 14; - return; - } - } - if (!Web.upload_error) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes"), upload.totalSize); - } - } - - - else if (UPLOAD_FILE_ABORTED == upload.status) { - restart_flag = 0; - MqttRetryCounter(0); -#ifdef USE_COUNTER - CounterInterruptDisable(false); -#endif - Web.upload_error = 7; - if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } - } - delay(0); -} - - - -void HandlePreflightRequest(void) -{ - HttpHeaderCors(); - 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)); - - if (strlen(SettingsText(SET_WEBPWD))) { - char tmp1[33]; - WebGetArg("user", tmp1, sizeof(tmp1)); - char tmp2[strlen(SettingsText(SET_WEBPWD)) +1]; - WebGetArg("password", tmp2, sizeof(tmp2)); - if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { - WSContentBegin(401, CT_JSON); - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); - WSContentEnd(); - return; - } - } - - WSContentBegin(200, CT_JSON); - 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=\"}")); - } - 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++); -# 3202 "/workspace/Tasmota/tasmota/xdrv_01_webserver.ino" - if ((' ' == decodedChar) || ('+' == decodedChar)) { - encoded += '%'; - encoded += hex[decodedChar >> 4]; - encoded += hex[decodedChar & 0xF]; - } else { - encoded += decodedChar; - } - - } - return encoded; -} - -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[200]; - 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()); - - WiFiClient http_client; - HTTPClient http; - if (http.begin(http_client, UrlEncode(url))) { - 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) -{ - - - - - - JsonParser parser((char*) dataBuf); - JsonParserObject root = parser.getRootObject(); - JsonParserArray arr = root[PSTR(D_CMND_WEBCOLOR)].getArray(); - if (arr) { - uint32_t i = 0; - for (auto color : arr) { - if (i < COL_LAST) { - WebHexCode(i, color.getStr()); - } else { - break; - } - i++; - } - } - 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 "|" D_CMND_WEBBUTTON "|" D_CMND_CORS; - -void (* const WebCommand[])(void) PROGMEM = { -#ifdef USE_EMULATION - &CmndEmulation, -#endif -#ifdef USE_SENDMAIL - &CmndSendmail, -#endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, - &CmndWebSensor, &CmndWebButton, &CmndCors }; - - - - - -#ifdef USE_EMULATION -void CmndEmulation(void) -{ -#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) -#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; - } -#endif - 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, NetworkHostname(), NetworkAddress().toString().c_str()); - } else { - ResponseCmndStateText(0); - } -} - -void CmndWebPassword(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); - ResponseCmndChar(SettingsText(SET_WEBPWD)); - } else { - Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); - } -} - -void CmndWeblog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - 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(); -} - -void CmndWebButton(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_BUTTON_TEXT)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_BUTTON1, MAX_BUTTON_TEXT); - } else { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_BUTTON1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); - } - ResponseCmndIdxChar(SettingsText(SET_BUTTON1 + XdrvMailbox.index -1)); - } - } -} - -void CmndCors(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_CORS, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_CORS)); -} - - - - - -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 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" -#define XDRV_02 2 - - - -#ifdef USE_MQTT_TLS - #include "WiFiClientSecureLightBearSSL.h" - BearSSL::WiFiClientSecure_light *tlsClient; -#endif -WiFiClient EspClient; - -const char kMqttCommands[] PROGMEM = "|" -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - D_CMND_MQTTFINGERPRINT "|" -#endif - D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" -#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_MQTTLOG "|" - 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 - &CmndMqttUser, &CmndMqttPassword, -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - &CmndTlsKey, -#endif - &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, - &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, &CmndMqttlog, - &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; - bool mqtt_tls = 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 - - - - -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; -} -#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++; - } -} -# 136 "/workspace/Tasmota/tasmota/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 1200" -#endif - -PubSubClient MqttClient; - -void MqttInit(void) -{ -#ifdef USE_MQTT_TLS - if ((8883 == Settings.mqtt_port) || (8884 == Settings.mqtt_port)) { - - Settings.flag4.mqtt_tls = true; - } - Mqtt.mqtt_tls = Settings.flag4.mqtt_tls; - - - String host = String(SettingsText(SET_MQTT_HOST)); - if (host.indexOf(".iot.") && host.endsWith(".amazonaws.com")) { - Settings.flag4.mqtt_no_retain = true; - } - - if (Mqtt.mqtt_tls) { - tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); - -#ifdef USE_MQTT_AWS_IOT - loadTlsDir(); - if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF , 0); - } -#endif - -#ifdef USE_MQTT_TLS_CA_CERT - tlsClient->setTrustAnchor(Tasmota_TA, ARRAY_SIZE(Tasmota_TA)); -#endif - - MqttClient.setClient(*tlsClient); - } else { - MqttClient.setClient(EspClient); - } -#else - MqttClient.setClient(EspClient); -#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) -{ - - if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { - char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); - if (str == topic) { - mqtt_cmnd_blocked_reset = 4; - mqtt_cmnd_blocked++; - } - } - - bool result = MqttClient.publish(topic, mqtt_data, retained); - yield(); - return result; -} - -void MqttDumpData(char* topic, char* data, uint32_t data_len) { - char dump_data[data_len +1]; - memcpy(dump_data, data, sizeof(dump_data)); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_DATA_SIZE " %d, \"%s %s\""), data_len, topic, RemoveControlCharacter(dump_data)); -} - -void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("MqttDataHandler")); -#endif - - - if (data_len >= MQTT_MAX_PACKET_SIZE) { return; } - - - if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { - char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1)); - if ((str == mqtt_topic) && mqtt_cmnd_blocked) { - mqtt_cmnd_blocked--; - return; - } - } - - - 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)); - - - - MqttDumpData(topic, data, data_len); - - - 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); - - 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 MqttPublishLogging(const char *mxtime) -{ - char saved_mqtt_data[strlen(mqtt_data) +1]; - memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); - - - Response_P(PSTR("%s%s"), mxtime, log_data); - char stopic[TOPSZ]; - GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); - MqttPublishLib(stopic, false); - - memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); -} - -void MqttPublish(const char* topic, bool retained) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("MqttPublish")); -#endif - - if (Settings.flag4.mqtt_no_retain) { - retained = false; - } - - char sretained[CMDSZ]; - sretained[0] = '\0'; - char slog_type[20]; - snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); - - if (Settings.flag.mqtt_enabled) { - 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) -{ - MqttPublish(topic, false); -} - -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) -{ - - - - - - - - char romram[64]; - 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); - -#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) - if ((prefix > 0) && (Settings.flag4.awsiot_shadow) && (Mqtt.connected)) { - - char *topic = SettingsText(SET_MQTT_TOPIC); - char topic2[strlen(topic)+1]; - strcpy(topic2, topic); - - char *s = topic2; - while (*s) { - if ('/' == *s) { - *s = '_'; - } - s++; - } - - snprintf_P(romram, sizeof(romram), PSTR("$aws/things/%s/shadow/update"), topic2); - - - char *mqtt_save = (char*) malloc(strlen(mqtt_data)+1); - if (!mqtt_save) { return; } - strcpy(mqtt_save, mqtt_data); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"state\":{\"reported\":%s}}"), mqtt_save); - free(mqtt_save); - - bool result = MqttClient.publish(romram, mqtt_data, false); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); - yield(); - } -#endif -} - -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) -{ - MqttPublishPrefixTopic_P(prefix, subtopic, false); -} - -void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) -{ - MqttPublishPrefixTopic_P(prefix, subtopic, retained); - XdrvRulesProcess(); -} - -void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic) -{ - MqttPublishPrefixTopicRulesProcess_P(prefix, subtopic, false); -} - -void MqttPublishTeleSensor(void) -{ - MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -} - -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); - - if (!Settings.flag4.only_json_message) { - 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(void) -{ - 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(void) -{ - return Mqtt.connect_count; -} - -void MqttDisconnected(int state) -{ - Mqtt.connected = false; - Mqtt.retry_counter = Settings.mqtt_retry; - - MqttClient.disconnect(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter); - 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(MQTT_LWT_ONLINE)); - MqttPublish(stopic, true); - - if (!Settings.flag4.only_json_message) { - - mqtt_data[0] = '\0'; - MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); - } - - GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); - MqttSubscribe(stopic); - if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { - uint32_t real_index = SET_MQTT_GRP_TOPIC; - for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { - if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - if (strlen(SettingsText(real_index +i))) { - GetGroupTopic_P(stopic, PSTR("#"), real_index +i); - MqttSubscribe(stopic); - } - } - GetFallbackTopic_P(stopic, PSTR("#")); - MqttSubscribe(stopic); - } - - XdrvCall(FUNC_MQTT_SUBSCRIBE); - } - - if (Mqtt.initial_connection_state) { - if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) { - char stopic2[TOPSZ]; - 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, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); -#ifdef USE_WEBSERVER - if (Settings.webserver) { -#if LWIP_IPV6 - Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str()); -#else - Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, NetworkHostname(), NetworkAddress().toString().c_str()); -#endif - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); - } -#endif - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); - if (CrashFlag()) { - CrashDump(); - } else { - ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); - } - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); - } - - MqttPublishAllPowerState(); - if (Settings.tele_period) { - tele_period = Settings.tele_period -5; - } - 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(SettingsText(SET_MQTT_HOST)) || !Settings.mqtt_port) { - Mqtt.allowed = false; - } -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - - if (Mqtt.mqtt_tls) { - if (0 == strlen(SettingsText(SET_MQTT_PWD))) { - 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(SettingsText(SET_MQTT_USER))) { - mqtt_user = SettingsText(SET_MQTT_USER); - } - if (strlen(SettingsText(SET_MQTT_PWD))) { - mqtt_pwd = SettingsText(SET_MQTT_PWD); - } - - GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - Response_P(S_LWT_OFFLINE); - - if (MqttClient.connected()) { MqttClient.disconnect(); } -#ifdef USE_MQTT_TLS - if (Mqtt.mqtt_tls) { - tlsClient->stop(); - } else { - EspClient = WiFiClient(); - MqttClient.setClient(EspClient); - } -#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) - - if (Mqtt.mqtt_tls) { - if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF , 0); - } - } -#endif - MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port); - - uint32_t mqtt_connect_time = millis(); -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - bool allow_all_fingerprints; - bool learn_fingerprint1; - bool learn_fingerprint2; - if (Mqtt.mqtt_tls) { - allow_all_fingerprints = false; - learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); - 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 - bool lwt_retain = Settings.flag4.mqtt_no_retain ? false : true; -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (Mqtt.mqtt_tls) { - if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) { - - mqtt_user = nullptr; - mqtt_pwd = nullptr; - } - } -#endif - - if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, mqtt_data, MQTT_CLEAN_SESSION)) { -#ifdef USE_MQTT_TLS - if (Mqtt.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 -# 721 "/workspace/Tasmota/tasmota/xdrv_02_mqtt.ino" - const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); - - char buf_fingerprint[64]; - ToHex_P(recv_fingerprint, 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); - - bool learned = false; - - - - - - if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20))) { - memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20); - learned = true; - } - - if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20))) { - memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); - learned = true; - } - - if (learned) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); - - SettingsSaveAll(); - } - -#endif - } -#endif - MqttConnected(); - } else { -#ifdef USE_MQTT_TLS - if (Mqtt.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) { - MqttReconnect(); - } else { - Mqtt.retry_counter--; - } - } else { - global_state.mqtt_down = 0; - } - } else { - global_state.mqtt_down = 0; - if (Mqtt.initial_connection_state) { - MqttReconnect(); - } - } -} - -bool KeyTopicActive(uint32_t key) -{ - - - key &= 1; - char key_topic[TOPSZ]; - Format(key_topic, SettingsText(SET_MQTT_BUTTON_TOPIC + key), sizeof(key_topic)); - return ((strlen(key_topic) != 0) && strcmp(key_topic, "0")); -} - - - - - -#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))) { - if (SC_DEFAULT == Shortcut()) { - memcpy_P(Settings.mqtt_fingerprint[XdrvMailbox.index -1], (1 == XdrvMailbox.index) ? default_fingerprint1 : default_fingerprint2, sizeof(default_fingerprint1)); - } else { - strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : 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 - -void CmndMqttUser(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_MQTT_USER)); -} - -void CmndMqttPassword(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data); - ResponseCmndChar(SettingsText(SET_MQTT_PWD)); - restart_flag = 2; - } else { - Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); - } -} - -void CmndMqttlog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - Settings.mqttlog_level = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.mqttlog_level); -} - -void CmndMqttHost(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_MQTT_HOST)); -} - -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 <= MAX_STATE_TEXT)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_STATE_TXT1, MAX_STATE_TEXT); - } else { - if (XdrvMailbox.data_len > 0) { - for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { - if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; - } - SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data); - } - ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); - } - } -} - -void CmndMqttClient(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); -} - -void CmndFullTopic(void) -{ - if (XdrvMailbox.data_len > 0) { - 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, SettingsText(SET_MQTT_FULLTOPIC))) { - Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1); - restart_flag = 2; - } - } - ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC)); -} - -void CmndPrefix(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_MQTT_PREFIXES)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_MQTTPREFIX1, MAX_MQTT_PREFIXES); - } else { - if (XdrvMailbox.data_len > 0) { - MakeValidMqtt(0, XdrvMailbox.data); - SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, - (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); - } - } -} - -void CmndPublish(void) -{ - if (XdrvMailbox.data_len > 0) { - char *payload_part; - char *mqtt_part = strtok_r(XdrvMailbox.data, " ", &payload_part); - if (mqtt_part) { - char stemp1[TOPSZ]; - strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - if ((payload_part != nullptr) && strlen(payload_part)) { - strlcpy(mqtt_data, payload_part, sizeof(mqtt_data)); - } else { - mqtt_data[0] = '\0'; - } - MqttPublish(stemp1, (XdrvMailbox.index == 2)); - - mqtt_data[0] = '\0'; - } - } -} - -void CmndGroupTopic(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_GROUP_TOPICS)) { - if (XdrvMailbox.data_len > 0) { - uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); - - - char stemp[MAX_GROUP_TOPICS][TOPSZ]; - uint32_t read_index = 0; - uint32_t real_index = SET_MQTT_GRP_TOPIC; - for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { - if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - if (strlen(SettingsText(real_index +i))) { - bool not_equal = true; - for (uint32_t j = 0; j < read_index; j++) { - if (!strcmp(SettingsText(real_index +i), stemp[j])) { - not_equal = false; - } - } - if (not_equal) { - strncpy(stemp[read_index], SettingsText(real_index +i), sizeof(stemp[read_index])); - read_index++; - } - } - } - if (0 == read_index) { - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); - } else { - uint32_t write_index = 0; - uint32_t real_index = SET_MQTT_GRP_TOPIC; - for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { - if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } - if (write_index < read_index) { - SettingsUpdateText(real_index +i, stemp[write_index]); - write_index++; - } else { - SettingsUpdateText(real_index +i, ""); - } - } - } - - restart_flag = 2; - } - ResponseCmndAll(SET_MQTT_GRP_TOPIC, MAX_GROUP_TOPICS); - } -} - -void CmndTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - 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, SettingsText(SET_MQTT_TOPIC))) { - Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - SettingsUpdateText(SET_MQTT_TOPIC, stemp1); - restart_flag = 2; - } - } - ResponseCmndChar(SettingsText(SET_MQTT_TOPIC)); -} - -void CmndButtonTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - switch (Shortcut()) { - case SC_CLEAR: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, ""); break; - case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, mqtt_topic); break; - case SC_USER: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); break; - default: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, XdrvMailbox.data); - } - } - ResponseCmndChar(SettingsText(SET_MQTT_BUTTON_TOPIC)); -} - -void CmndSwitchTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - switch (Shortcut()) { - case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break; - case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, mqtt_topic); break; - case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break; - default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data); - } - } - ResponseCmndChar(SettingsText(SET_MQTT_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; - if (Settings.flag.mqtt_power_retain) { - Settings.flag4.only_json_message = 0; - } - } - 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 = 0xFF; -const static uint8_t* tls_spi_start = (uint8_t*) 0x402FF000; -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); - - - RemoveSpace(XdrvMailbox.data); - - - 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); - } - - if (ESP.flashEraseSector(tls_spi_start_sector)) { - ESP.flashWrite(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - 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); - } -} - -#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) ")

" -#ifdef USE_MQTT_TLS - "


" -#endif - "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" - "


" - "

" 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[TOPSZ]; - - WSContentStart_P(S_CONFIGURE_MQTT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MQTT1, - SettingsText(SET_MQTT_HOST), - Settings.mqtt_port, -#ifdef USE_MQTT_TLS - Mqtt.mqtt_tls ? " checked" : "", -#endif - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); - WSContentSend_P(HTTP_FORM_MQTT2, - (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), - MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void MqttSaveSettings(void) -{ - char tmp[TOPSZ]; - 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, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { - Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - } - SettingsUpdateText(SET_MQTT_TOPIC, stemp); - SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); - WebGetArg("mh", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); -#ifdef USE_MQTT_TLS - Mqtt.mqtt_tls = Webserver->hasArg("b3"); -#endif - WebGetArg("mc", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); -#if defined(USE_MQTT_TLS) && (defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT)) - 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"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); -#else - WebGetArg("mu", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("mp", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); - 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"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_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(PSTR("/" WEB_HANDLE_MQTT), HandleMqttConfiguration); - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kMqttCommands, MqttCommand); - break; - } - } - return result; -} -# 1 "/workspace/Tasmota/tasmota/xdrv_03_energy.ino" -# 20 "/workspace/Tasmota/tasmota/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 }; - -#ifdef SDM630_IMPORT - float import_active[3] = { NAN, NAN, NAN }; -#endif - float export_active[3] = { NAN, NAN, NAN }; - - float start_energy = 0; - float daily = 0; - float total = 0; - - 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 frequency_common = false; - bool kWhtoday_offset_init = false; - - bool voltage_available = true; - bool current_available = true; - - bool type_dc = false; - bool power_on = true; - -#ifdef USE_ENERGY_MARGIN_DETECTION - uint16_t power_history[3][3] = {{ 0 }, { 0 }, { 0 }}; - uint8_t power_steady_counter = 8; - 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; - - - -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); -} - - - -bool EnergyTariff1Active() -{ - uint8_t dst = 0; - if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { - 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(); - if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { - - return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); - } else { - - return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); - } - } 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[0])) { - - - - float export_active = 0.0; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (!isnan(Energy.export_active[i])) { - export_active += Energy.export_active[i]; - } - } - return_diff = (uint32_t)(export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; - RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(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)) && - Settings.flag3.hardware_energy_total) { - 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(); - - } - 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 (!Energy.kWhtoday_offset_init && (RtcTime.day_of_year == Settings.energy_kWhdoy)) { - Energy.kWhtoday_offset = Settings.energy_kWhtoday; - Energy.kWhtoday_offset_init = true; - } - - if (LocalTime() == Midnight()) { - Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; - - RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Energy.period -= RtcSettings.energy_kWhtoday; - Energy.kWhtoday = 0; - Energy.kWhtoday_offset = 0; - RtcSettings.energy_kWhtoday = 0; - Energy.start_energy = 0; - - - 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) -{ - if (Energy.power_steady_counter) { - Energy.power_steady_counter--; - return; - } - - bool jsonflg = false; - Response_P(PSTR("{\"" D_RSLT_MARGINS "\":{")); - - int16_t power_diff[3] = { 0 }; - for (uint32_t phase = 0; phase < Energy.phase_count; phase++) { - uint16_t active_power = (uint16_t)(Energy.active_power[phase]); - - if (Settings.energy_power_delta[phase]) { - power_diff[phase] = active_power - Energy.power_history[phase][0]; - uint16_t delta = abs(power_diff[phase]); - bool threshold_met = false; - if (delta > 0) { - if (Settings.energy_power_delta[phase] < 101) { - uint16_t min_power = (Energy.power_history[phase][0] > active_power) ? active_power : Energy.power_history[phase][0]; - if (0 == min_power) { min_power++; } - delta = (delta * 100) / min_power; - if (delta > Settings.energy_power_delta[phase]) { - threshold_met = true; - } - } else { - if (delta > (Settings.energy_power_delta[phase] -100)) { - threshold_met = true; - } - } - } - if (threshold_met) { - Energy.power_history[phase][1] = active_power; - Energy.power_history[phase][2] = active_power; - jsonflg = true; - } else { - power_diff[phase] = 0; - } - } - Energy.power_history[phase][0] = Energy.power_history[phase][1]; - Energy.power_history[phase][1] = Energy.power_history[phase][2]; - Energy.power_history[phase][2] = active_power; - } - if (jsonflg) { - char power_diff_chr[Energy.phase_count][FLOATSZ]; - for (uint32_t phase = 0; phase < Energy.phase_count; phase++) { - dtostrfd(power_diff[phase], 0, power_diff_chr[phase]); - } - char value_chr[FLOATSZ *3]; - ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_chr[0], 1)); - } - - uint16_t energy_power_u = (uint16_t)(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)) { - 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); - - bool flag; - 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\"" 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\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - } - if (jsonflg) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopicRulesProcess_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}"), energy_power_u); - 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(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - } - } - } - } - } - - - if (Settings.energy_max_energy) { - 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)); - 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; - 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); - } - } -#endif -} - -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(); - MqttPublishTeleSensor(); -} -#endif - -void EnergyEverySecond(void) -{ - - if (global_update) { - if (power && !isnan(global_temperature_celsius) && (global_temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { - - char temperature[33]; - dtostrfd(global_temperature_celsius, 1, temperature); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: GlobTemp %s"), temperature); - - 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; } - if (!isnan(Energy.export_active[i])) { Energy.export_active[i] = 0; } - - data_valid--; - } - } - } - if (!data_valid) { - Energy.start_energy = 0; - - XnrgCall(FUNC_ENERGY_RESET); - } - -#ifdef USE_ENERGY_MARGIN_DETECTION - EnergyMarginCheck(); -#endif -} - - - - - -void EnergyCommandCalResponse(uint32_t nvalue) -{ - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); - ResponseCmndNumber(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.start_energy = 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; - - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); - break; - } - } - } - else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { - uint32_t values[2] = { 0 }; - uint32_t position = ParseParameters(2, values); - values[0] *= 100; - values[1] *= 100; - - switch (XdrvMailbox.index) - { - case 4: - - if (position > 0) { - RtcSettings.energy_usage.usage1_kWhtotal = values[0]; - } - if (position > 1) { - 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 > 0) { - RtcSettings.energy_usage.return1_kWhtotal = values[0]; - } - if (position > 1) { - 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; - } - } - - 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]; - 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)) { - uint32_t tariff = XdrvMailbox.index -1; - uint32_t time_type = 0; - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - while ((str != nullptr) && (time_type < 2)) { - char *q; - uint32_t value = strtol(str, &q, 10); - Settings.tariff[tariff][time_type] = value; - if (value < 24) { - Settings.tariff[tariff][time_type] *= 60; - char *minute = strtok_r(nullptr, ":", &q); - if (minute) { - value = strtol(minute, nullptr, 10); - if (value > 59) { - value = 59; - } - Settings.tariff[tariff][time_type] += value; - } - } - if (Settings.tariff[tariff][time_type] > 1439) { - Settings.tariff[tariff][time_type] = 1439; - } - str = strtok_r(nullptr, ", ", &p); - time_type++; - } - } - else if (XdrvMailbox.index == 9) { - Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; - } - Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), - XdrvMailbox.command, - 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)); -} - -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; - } - ResponseCmndNumber(Settings.energy_power_calibration); - } -} - -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; - } - ResponseCmndNumber(Settings.energy_voltage_calibration); - } -} - -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; - } - ResponseCmndNumber(Settings.energy_current_calibration); - } -} - -void CmndPowerSet(void) -{ - Energy.command_code = CMND_POWERSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_power_calibration); - } -} - -void CmndVoltageSet(void) -{ - Energy.command_code = CMND_VOLTAGESET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_voltage_calibration); - } -} - -void CmndCurrentSet(void) -{ - Energy.command_code = CMND_CURRENTSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_current_calibration); - } -} - -void CmndFrequencySet(void) -{ - Energy.command_code = CMND_FREQUENCYSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_frequency_calibration); - } -} - -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.index > 0) && (XdrvMailbox.index <= 3)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { - Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.energy_power_delta[XdrvMailbox.index -1]); - } -} - -void CmndPowerLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_min_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_power); -} - -void CmndPowerHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power); -} - -void CmndVoltageLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_min_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_voltage); -} - -void CmndVoltageHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_max_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_voltage); -} - -void CmndCurrentLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_min_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_current); -} - -void CmndCurrentHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_max_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_current); -} - -#ifdef USE_ENERGY_POWER_LIMIT -void CmndMaxPower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit); -} - -void CmndMaxPowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_hold); -} - -void CmndMaxPowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_window); -} - -void CmndSafePower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit); -} - -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; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); -} - -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; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); -} - -void CmndMaxEnergy(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_energy = XdrvMailbox.payload; - Energy.max_energy_state = 3; - } - ResponseCmndNumber(Settings.energy_max_energy); -} - -void CmndMaxEnergyStart(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { - Settings.energy_max_energy_start = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_energy_start); -} -#endif -#endif - -void EnergySnsInit(void) -{ - XnrgCall(FUNC_INIT); - - if (energy_flg) { - Energy.kWhtoday_offset = 0; - - if ((ResetReason() != REASON_DEFAULT_RST) && RtcSettingsValid()) { - Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; - Energy.kWhtoday_offset_init = true; - } - 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}"; - -#ifdef SDM630_IMPORT -const char HTTP_ENERGY_SNS4[] PROGMEM = - "{s}" D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif -#endif - -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]; -#ifdef SDM630_IMPORT - char import_active_chr[Energy.phase_count][FLOATSZ]; -#endif - char export_active_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]); -#ifdef SDM630_IMPORT - dtostrfd(Energy.import_active[i], Settings.flag2.energy_resolution, import_active_chr[i]); -#endif - dtostrfd(Energy.export_active[i], Settings.flag2.energy_resolution, export_active_chr[i]); - } - - 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); - - - bool energy_tariff = false; - char energy_usage_chr[2][FLOATSZ]; - char energy_return_chr[2][FLOATSZ]; - if (Settings.tariff[0][0] != Settings.tariff[1][0]) { - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[0]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[0]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[1]); - energy_tariff = true; - } - - 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"), - GetDateAndTime(DT_ENERGY).c_str(), - energy_total_chr); - - if (energy_tariff) { - ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"), - EnergyFormatIndex(value_chr, energy_usage_chr[0], json, 2)); - } - - ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), - energy_yesterday_chr, - energy_daily_chr); - - #ifdef SDM630_IMPORT - if (!isnan(Energy.import_active[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s"), - EnergyFormat(value_chr, import_active_chr[0], json)); - if (energy_tariff) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT D_CMND_TARIFF "\":%s"), - EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); - } - } -#endif - - if (!isnan(Energy.export_active[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), - EnergyFormat(value_chr, export_active_chr[0], json)); - if (energy_tariff) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"), - EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); - } - } - - if (show_energy_period) { - float 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, Energy.frequency_common)); - } - } - 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); - DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr); - - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_usage_chr[0]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_usage_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, energy_return_chr[0]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, energy_return_chr[1]); - DomoticzSensorP1SmartMeter(energy_usage_chr[0], energy_usage_chr[1], energy_return_chr[0], energy_return_chr[1], (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(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); - } - WSContentSend_PD(HTTP_SNS_POWER, 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, Energy.frequency_common)); - } - } - WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr); - if (!isnan(Energy.export_active[0])) { - WSContentSend_PD(HTTP_ENERGY_SNS3, EnergyFormat(value_chr, export_active_chr[0], json)); - } -#ifdef SDM630_IMPORT - if (!isnan(Energy.import_active[0])) { - WSContentSend_PD(HTTP_ENERGY_SNS4, EnergyFormat(value_chr, import_active_chr[0], json)); - } -#endif - - XnrgCall(FUNC_WEB_SENSOR); -#endif - } -} - - - - - -bool Xdrv03(uint8_t function) -{ - bool result = false; - - if (FUNC_PRE_INIT == function) { - energy_flg = ENERGY_NONE; - XnrgCall(FUNC_PRE_INIT); - } - 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_EVERY_SECOND: - XnrgCall(FUNC_EVERY_SECOND); - 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 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" -#ifdef USE_LIGHT -# 124 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" -#define XDRV_04 4 - - -enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; - -const uint8_t LIGHT_COLOR_SIZE = 25; - -const char kLightCommands[] PROGMEM = "|" - D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" 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 -#ifdef USE_LIGHT_PALETTE - "|" D_CMND_PALETTE -#endif -#ifdef USE_DGR_LIGHT_SEQUENCE - "|" D_CMND_SEQUENCE_OFFSET -#endif - "|UNDOCA" ; - -void (* const LightCommand[])(void) PROGMEM = { - &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, - &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, - &CmndWhite, &CmndChannel, &CmndHsbColor, -#ifdef USE_LIGHT_PALETTE - &CmndPalette, -#endif -#ifdef USE_DGR_LIGHT_SEQUENCE - &CmndSequenceOffset, -#endif - &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 }; - - -const uint16_t CT_MIN = 153; -const uint16_t CT_MAX = 500; - -const uint16_t CT_MIN_ALEXA = 200; -const uint16_t CT_MAX_ALEXA = 380; - - - - - - -typedef struct gamma_table_t { - uint16_t to_src; - uint16_t to_gamma; -} gamma_table_t; - -const gamma_table_t gamma_table[] = { - { 1, 1 }, - { 4, 1 }, - { 209, 13 }, - { 312, 41 }, - { 457, 106 }, - { 626, 261 }, - { 762, 450 }, - { 895, 703 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; - - -const gamma_table_t gamma_table_fast[] = { - { 384, 192 }, - { 768, 576 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; -# 262 "/workspace/Tasmota/tasmota/xdrv_04_light.ino" -struct LIGHT { - uint32_t strip_timer_counter = 0; - power_t power = 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 random = 0; - uint8_t subtype = 0; - uint8_t device = 0; - uint8_t old_power = 1; - uint8_t wakeup_active = 0; - uint8_t fixed_color_index = 1; - uint8_t pwm_offset = 0; - uint8_t max_scheme = LS_MAX -1; - - uint32_t wakeup_start_time = 0; - - bool update = true; - bool pwm_multi_channels = false; - bool virtual_ct = false; - - bool fade_initialized = false; - bool fade_running = false; -#ifdef USE_DEVICE_GROUPS - uint8_t last_scheme = 0; - bool devgrp_no_channels_out = false; -#ifdef USE_DGR_LIGHT_SEQUENCE - uint8_t sequence_offset = 0; - uint8_t * channels_fifo; -#endif -#endif -#ifdef USE_LIGHT_PALETTE - uint8_t palette_count = 0; - uint8_t * palette; -#endif - uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; - uint16_t fade_cur_10[LST_MAX]; - uint16_t fade_end_10[LST_MAX]; - uint16_t fade_duration = 0; - uint32_t fade_start = 0; - - uint16_t pwm_min = 0; - uint16_t pwm_max = 1023; -} 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; -} -# 363 "/workspace/Tasmota/tasmota/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 = CT_MIN; - uint8_t _wc = 255; - uint8_t _ww = 0; - uint8_t _briCT = 255; - - uint8_t _color_mode = LCM_RGB; - - - - - - uint16_t _ct_min_range = CT_MIN; - uint16_t _ct_max_range = CT_MAX; - - public: - LightStateClass() { - - } - - void setSubType(uint8_t sub_type) { - _subtype = sub_type; - } -# 405 "/workspace/Tasmota/tasmota/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_RGBCW: - _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; } - } - - void getChannels(uint8_t *channels) { - getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); - } - - void getChannelsRaw(uint8_t *channels) { - channels[0] = _r; - channels[1] = _g; - channels[2] = _b; - channels[3] = _wc; - channels[4] = _ww; - } - - 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(uint32_t mode = 0) { - uint8_t bri; - switch (mode) { - case 1: - bri = getBriRGB(); - break; - case 2: - bri = getBriCT(); - break; - default: - bri = getBri(); - break; - } - return BriToDimmer(bri); - } - - inline uint16_t getCT() const { - return _ct; - } - - - uint16_t getCT10bits() const { - return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); - } - - inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { - _ct_min_range = ct_min_range; - _ct_max_range = ct_max_range; - } - - inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { - if (ct_min_range) { *ct_min_range = _ct_min_range; } - if (ct_max_range) { *ct_max_range = _ct_max_range; } - } - - - 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(); } -#ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); -#endif - return prev_bri; - } - - - uint8_t setBriCT(uint8_t bri_ct) { - uint8_t prev_bri = _briCT; - _briCT = bri_ct; - if (bri_ct > 0) { addCTMode(); } -#ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); -#endif - 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 < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); - _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 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 - } -# 629 "/workspace/Tasmota/tasmota/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 (sum <= 257) { free_range = false; } - - 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, CT_MIN, CT_MAX); - 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 setChannelsRaw(uint8_t *channels) { - _r = channels[0]; - _g = channels[1]; - _b = channels[2]; - _wc = channels[3]; - _ww = channels[4]; -} - - - - - 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); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels Actuals (%d %d %d %d %d)", - _r, _g, _b, _wc, _ww); -#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); - -}; -# 748 "/workspace/Tasmota/tasmota/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 mat3x3(const float *mat33, const float *vec3, float *res3) { - for (uint32_t i = 0; i < 3; i++) { - const float * v = vec3; - *res3 = 0.0f; - for (uint32_t j = 0; j < 3; j++) { - *res3 += *mat33++ * *v++; - } - res3++; - } -} - -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 rgb[3] = { (float)i_r, (float)i_g, (float)i_b }; - - - for (uint32_t i = 0; i < 3; i++) { - rgb[i] = rgb[i] / 255.0f; - rgb[i] = (rgb[i] > 0.04045f) ? POW((rgb[i] + 0.055f) / (1.0f + 0.055f), 2.4f) : (rgb[i] / 12.92f); - } - - - - float XYZ[3]; - static const float XYZ_factors[] = { 0.649926f, 0.103455f, 0.197109f, - 0.234327f, 0.743075f, 0.022598f, - 0.000000f, 0.053077f, 1.035763f }; - mat3x3(XYZ_factors, rgb, XYZ); - - float XYZ_sum = XYZ[0] + XYZ[1] + XYZ[2]; - x = XYZ[0] / XYZ_sum; - y = XYZ[1] / XYZ_sum; - - } - 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) -{ - float XYZ[3], rgb[3]; - 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; - XYZ[0] = x / y; - XYZ[1] = 1.0f; - XYZ[2] = z / y; - - static const float rgb_factors[] = { 3.2406f, -1.5372f, -0.4986f, - -0.9689f, 1.8758f, 0.0415f, - 0.0557f, -0.2040f, 1.0570f }; - mat3x3(rgb_factors, XYZ, rgb); - float max = (rgb[0] > rgb[1] && rgb[0] > rgb[2]) ? rgb[0] : (rgb[1] > rgb[2]) ? rgb[1] : rgb[2]; - - for (uint32_t i = 0; i < 3; i++) { - rgb[i] = rgb[i] / max; - rgb[i] = (rgb[i] <= 0.0031308f) ? 12.92f * rgb[i] : 1.055f * POW(rgb[i], (1.0f / 2.4f)) - 0.055f; - } - - int32_t irgb[3]; - for (uint32_t i = 0; i < 3; i++) { - irgb[i] = rgb[i] * 255.0f + 0.5f; - } - - if (rr) { *rr = (irgb[0] > 255 ? 255: (irgb[0] < 0 ? 0 : irgb[0])); } - if (rg) { *rg = (irgb[1] > 255 ? 255: (irgb[1] < 0 ? 0 : irgb[1])); } - if (rb) { *rb = (irgb[2] > 255 ? 255: (irgb[2] < 0 ? 0 : irgb[2])); } -} - -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; - } - - void setAlexaCTRange(bool alexa_ct_range) { - - if (alexa_ct_range) { - _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); - } else { - _state->setCTRange(CT_MIN, CT_MAX); - } - } - - 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 - if (_pwm_multi_channels) { - _state->setChannelsRaw(Settings.light_color); - } else { - - _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]); - - - - uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); - - - - if ((DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && - (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - _state->setCW(255, 0); - } - _state->setBriCT(bri); - _state->setBriRGB(bri); - _state->setColorMode(LCM_RGB); - } - - 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, uint32_t mode = 0) { - uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); - switch (mode) { - case 1: - changeBriRGB(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - break; - case 2: - changeBriCT(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - break; - default: - changeBri(bri); - break; - } - } - - void changeBri(uint8_t bri) { - _state->setBri(bri); - saveSettings(); - calcLevels(); - } - - void changeBriRGB(uint8_t bri) { - _state->setBriRGB(bri); - saveSettings(); - calcLevels(); - } - - void changeBriCT(uint8_t bri) { - _state->setBriCT(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 *current_color = nullptr) { - uint8_t r,g,b,c,w,briRGB,briCT; - if (current_color == nullptr) { current_color = Light.current_color; } - - if (_pwm_multi_channels) { - _state->getChannelsRaw(current_color); - return; - } - - _state->getActualRGBCW(&r,&g,&b,&c,&w); - briRGB = _state->getBriRGB(); - briCT = _state->getBriCT(); - - current_color[0] = current_color[1] = current_color[2] = 0; - current_color[3] = current_color[4] = 0; - switch (Light.subtype) { - case LST_NONE: - current_color[0] = 255; - break; - case LST_SINGLE: - current_color[0] = briRGB; - break; - case LST_COLDWARM: - current_color[0] = c; - current_color[1] = w; - break; - case LST_RGBW: - case LST_RGBCW: - if (LST_RGBCW == Light.subtype) { - current_color[3] = c; - current_color[4] = w; - } else { - current_color[3] = briCT; - } - - case LST_RGB: - current_color[0] = r; - current_color[1] = g; - 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->getChannelsRaw(Settings.light_color); - 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 (Light.pwm_multi_channels) { - _state->setChannelsRaw(channels); - } else 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 change8to10(uint8_t v) { - return changeUIntScale(v, 0, 255, 0, 1023); -} - -uint8_t change10to8(uint16_t v) { - return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); -} - - - - - -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (v <= to_src) { - return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (vg <= to_gamma) { - return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - - -uint16_t ledGamma10_10(uint16_t v) { - return ledGamma_internal(v, gamma_table); -} - -uint16_t ledGamma10(uint8_t v) { - return ledGamma10_10(change8to10(v)); -} - - -uint8_t ledGamma(uint8_t v) { - return change10to8(ledGamma10(v)); -} - - - -void LightPwmOffset(uint32_t offset) -{ - Light.pwm_offset = offset; -} - -bool LightModuleInit(void) -{ - light_type = LT_BASIC; - - if (Settings.flag.pwm_control) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (PinUsed(GPIO_PWM1, i)) { light_type++; } - } - } - - light_flg = 0; - if (XlgtCall(FUNC_MODULE_INIT)) { - - } -#ifdef ESP8266 - else if (SONOFF_BN == my_module_type) { - light_type = LT_PWM1; - } - else 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); - } - light_type = LT_PWM2; - } -#endif -#ifdef USE_PWM_DIMMER -#ifdef USE_DEVICE_GROUPS - else if (PWM_DIMMER == my_module_type) { - light_type = Settings.pwm_dimmer_cfg.pwm_count + 1; - } -#endif -#endif - - if (light_type > LT_BASIC) { - devices_present++; - } - - - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - if (Settings.flag3.pwm_multi_channels) { - if (0 == pwm_channels) { pwm_channels = 1; } - devices_present += pwm_channels - 1; - } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { - - devices_present++; - } else if ((Settings.flag4.virtual_ct) && (LST_RGBW == pwm_channels)) { - Light.virtual_ct = true; - light_type++; - } - - return (light_type > LT_BASIC); -} - - - -void LightCalcPWMRange(void) { - uint16_t pwm_min, pwm_max; - - pwm_min = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_min)); - pwm_max = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_max)); - if (Settings.light_correction) { - pwm_min = ledGamma10_10(pwm_min); - pwm_max = ledGamma10_10(pwm_max); - } - pwm_min = pwm_min > 0 ? changeUIntScale(pwm_min, 1, 1023, 1, Settings.pwm_range) : 0; - pwm_max = changeUIntScale(pwm_max, 1, 1023, 1, Settings.pwm_range); - - Light.pwm_min = pwm_min; - Light.pwm_max = pwm_max; - -} - -void LightInit(void) -{ - - if (0 == Settings.rgbwwTable[4]) { - Settings.flag4.white_blend_mode = true; - Settings.rgbwwTable[4] = 255; - } - - 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 (LST_RGBW <= Light.subtype) { - - - bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); - light_controller.setCTRGBLinked(ct_rgb_linked); - } - - if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { - - light_controller.setPWMMultiChannel(true); - Light.device = devices_present - Light.subtype + 1; - } else if (!light_controller.isCTRGBLinked()) { - - Light.device--; - } - LightCalcPWMRange(); -#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(); - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - light_controller.calcLevels(); - - 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 (PinUsed(GPIO_PWM1, i)) { -#ifdef ESP8266 - pinMode(Pin(GPIO_PWM1, i), OUTPUT); -#else - analogAttach(Pin(GPIO_PWM1, i), i); -#endif - } - } - if (PinUsed(GPIO_ARIRFRCV)) { - if (PinUsed(GPIO_ARIRFSEL)) { - pinMode(Pin(GPIO_ARIRFSEL), OUTPUT); - digitalWrite(Pin(GPIO_ARIRFSEL), 1); - } - } - } - - uint32_t max_scheme = Light.max_scheme; - 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; - if (0 == Settings.light_wakeup) { - Settings.light_wakeup = 60; - } - if (Settings.flag4.fade_at_startup) { - Light.fade_initialized = true; - } - - 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]; - - Light.update = true; - -} - -uint8_t LightGetDimmer(uint8_t dimmer) { - return light_state.getDimmer(dimmer); -} - -void LightSetDimmer(uint8_t dimmer) { - light_controller.changeDimmer(dimmer); -} - -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - light_state.getHSB(hue, sat, bri); -} - -void LightGetXY(float *X, float *Y) { - light_state.getXY(X, Y); -} - -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - light_state.HsToRgb(hue, sat, r_r, r_g, r_b); -} - - -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 (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - bri = light_state.getBri(); - } - } else { - if (device == Light.device) { - bri = light_state.getBriRGB(); - } else if (device == Light.device + 1) { - bri = light_state.getBriCT(); - } - } - 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 (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - light_controller.changeBri(bri); - } - } else { - if (device == Light.device) { - light_controller.changeBriRGB(bri); - } else if (device == Light.device + 1) { - light_controller.changeBriCT(bri); - } - } -} - -void LightColorOffset(int32_t offset) { - uint16_t hue; - uint8_t sat; - light_state.getHSB(&hue, &sat, nullptr); - hue += offset; - if (hue < 0) { hue += 359; } - if (hue > 359) { hue -= 359; } - if (!Light.pwm_multi_channels) { - light_state.setHS(hue, sat); - } else { - light_state.setHS(hue, 255); - light_state.setBri(255); - } - light_controller.calcLevels(Light.new_color); -} - -bool LightColorTempOffset(int32_t offset) { - int32_t ct = LightGetColorTemp(); - if (0 == ct) { return false; } - ct += offset; - if (ct < CT_MIN) { ct = CT_MIN; } - else if (ct > CT_MAX) { ct = CT_MAX; } - - LightSetColorTemp(ct); - return true; -} - -void LightSetColorTemp(uint16_t ct) -{ - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - return; - } - light_controller.changeCTB(ct, light_state.getBriCT()); -} - -uint16_t LightGetColorTemp(void) -{ - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != 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) -{ - if ((0 == Settings.light_scheme) || (!Light.pwm_multi_channels)) { - 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 ResponseLightState(uint8_t append) -{ - char scolor[LIGHT_COLOR_SIZE]; - char scommand[33]; - bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); - - if (append) { - ResponseAppend_P(PSTR(",")); - } else { - Response_P(PSTR("{")); - } - if (!Light.pwm_multi_channels) { - if (unlinked) { - - ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "1\":%d" - ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "2\":%d"), - Light.device, GetStateText(Light.power & 1), light_state.getDimmer(1), - Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), light_state.getDimmer(2)); - } else { - GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), - light_state.getDimmer()); - } - - - if (Light.subtype > LST_SINGLE) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - if (LST_RGB <= Light.subtype) { - 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); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); - } - - 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 (append) { - if (Light.subtype >= LST_RGB) { - ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); - } - if (Light.max_scheme > LS_MAX) { - 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(power_t channels = 0xFFFFFFFF) { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); -#endif - - if (Light.pwm_multi_channels) { - for (uint32_t i = 0; i < Light.subtype; i++) { - if (bitRead(channels, i)) { - - if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else { - - if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { - ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - #ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device + i); - #endif - } - } - } else { - if (light_controller.isCTRGBLinked()) { - 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); - } - } else { - - if (channels & 1) { - if (light_state.getBriRGB() && !(Light.power & 1)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriRGB() && (Light.power & 1)) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - - if (channels & 2) { - if (light_state.getBriCT() && !(Light.power & 2)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriCT() && (Light.power & 2)) { - ExecuteCommandPower(Light.device + 1, 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); - ResponseLightState(0); -} - -#ifdef USE_LIGHT_PALETTE -void LightSetPaletteEntry(void) -{ - uint8_t bri = light_state.getBri(); - uint8_t * palette_entry = &Light.palette[Light.wheel * LST_MAX]; - for (int i = 0; i < LST_MAX; i++) { - Light.new_color[i] = changeUIntScale(palette_entry[i], 0, 255, 0, bri); - } - light_state.setChannelsRaw(Light.new_color); - if (!Light.pwm_multi_channels) { - light_state.setCW(Light.new_color[3], Light.new_color[4], true); - if (Light.new_color[0] || Light.new_color[1] || Light.new_color[2]) light_state.addRGBMode(); - } -} -#endif - -void LightCycleColor(int8_t direction) -{ - - if (Settings.light_speed > 3) { - if (Light.strip_timer_counter % (Settings.light_speed - 2)) { return; } - } - -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count) { - if (!Light.fade_running) { - if (0 == direction) { - Light.wheel = random(Light.palette_count); - } - else { - Light.wheel += direction; - if (Light.wheel >= Light.palette_count) { - Light.wheel = 0; - if (direction < 0) Light.wheel = Light.palette_count - 1; - } - } - LightSetPaletteEntry(); - } - return; - } -#endif - - if (0 == direction) { - if (Light.random == Light.wheel) { - Light.random = random(255); - - uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : - (Light.random < Light.wheel ) ? 0 : - (Light.random > Light.wheel +128) ? 0 : 1; - Light.random = (Light.random & 0xFE) | my_dir; - - - } - - direction = (Light.random &0x01) ? 1 : -1; - } - - - if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } - Light.wheel += direction; - uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); - - - - if (!Light.pwm_multi_channels) { - uint8_t sat; - light_state.getHSB(nullptr, &sat, nullptr); - light_state.setHS(hue, sat); - } else { - light_state.setHS(hue, 255); - light_state.setBri(255); - } - light_controller.calcLevels(Light.new_color); -} - -void LightSetPower(void) -{ - - Light.old_power = Light.power; - - uint32_t mask = 1; - if (Light.pwm_multi_channels) { - mask = (1 << Light.subtype) - 1; - } else if (!light_controller.isCTRGBLinked()) { - mask = 3; - } - 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) -{ - uint16_t light_still_on = 0; - bool power_off = false; - - - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - Light.strip_timer_counter++; - - - - if (Light.power || Light.fade_running) { - if (Settings.sleep > PWM_MAX_SLEEP) { - ssleep = PWM_MAX_SLEEP; - } else { - ssleep = Settings.sleep; - } - } else { - ssleep = Settings.sleep; - } - - if (!Light.power) { - Light.strip_timer_counter = 0; - if (Settings.light_scheme >= LS_MAX) { - power_off = true; - } - } else { - switch (Settings.light_scheme) { - case LS_POWER: - light_controller.calcLevels(Light.new_color); - 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_start_time = millis(); - } - - uint32_t step_10 = ((millis() - Light.wakeup_start_time) * 1023) / (Settings.light_wakeup * 1000); - if (step_10 > 1023) { step_10 = 1023; } - uint8_t wakeup_bri = changeUIntScale(step_10, 0, 1023, 0, LightStateClass::DimmerToBri(Settings.light_dimmer)); - - if (wakeup_bri != light_state.getBri()) { - light_state.setBri(wakeup_bri); - light_controller.calcLevels(); - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = Light.current_color[i]; - } - } - if (1023 == step_10) { - Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); - ResponseLightState(1); - ResponseJsonEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); - - Light.wakeup_active = 0; - Settings.light_scheme = LS_POWER; - } - } - break; - case LS_CYCLEUP: - case LS_CYCLEDN: - case LS_RANDOM: - if (LS_CYCLEUP == Settings.light_scheme) { - LightCycleColor(1); - } else if (LS_CYCLEDN == Settings.light_scheme) { - LightCycleColor(-1); - } else { - LightCycleColor(0); - } - if (Light.pwm_multi_channels) { - Light.new_color[0] = changeUIntScale(Light.new_color[0], 0, 255, 0, Settings.light_color[0]); - Light.new_color[1] = changeUIntScale(Light.new_color[1], 0, 255, 0, Settings.light_color[1]); - Light.new_color[2] = changeUIntScale(Light.new_color[2], 0, 255, 0, Settings.light_color[2]); - } - break; - default: - XlgtCall(FUNC_SET_SCHEME); - } - -#ifdef USE_DEVICE_GROUPS - if (Settings.light_scheme != Light.last_scheme) { - Light.last_scheme = Settings.light_scheme; - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); - Light.devgrp_no_channels_out = false; - } -#endif - } - - if ((Settings.light_scheme < LS_MAX) || power_off) { - - - LightApplyPower(Light.new_color, Light.power); - - - - - - - - if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { - Light.update = true; - } - if (Light.update) { -#ifdef USE_DEVICE_GROUPS - if (Light.power) LightSendDeviceGroupStatus(false); -#endif - - uint16_t cur_col_10[LST_MAX]; - Light.update = false; - bool rgbwwtable_applied = false; - - - for (uint32_t i = 0; i < LST_MAX; i++) { - Light.last_color[i] = Light.new_color[i]; - - cur_col_10[i] = change8to10(Light.new_color[i]); - } - - if (Light.pwm_multi_channels) { - calcGammaMultiChannels(cur_col_10); - } else { - calcGammaBulbs(cur_col_10); - - - - if ((LST_RGBW <= Light.subtype) && (Settings.flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) { - uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); - for (uint32_t i=0; i<3; i++) { - - uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); - } - - - uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); - if (LST_RGBW == Light.subtype) { - - cur_col_10[3] = white_10; - } else { - - uint32_t ct = light_state.getCT10bits(); - cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); - cur_col_10[3] = white_10 - cur_col_10[4]; - } - rgbwwtable_applied = true; - } else if ((Light.virtual_ct) && (0 == cur_col_10[0]+cur_col_10[1]+cur_col_10[2])) { - - uint16_t sw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[4] : cur_col_10[3]; - uint16_t hw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[3] : cur_col_10[4]; - uint32_t adjust_sw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[4] : Settings.rgbwwTable[3]); - uint32_t adjust_hw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[3] : Settings.rgbwwTable[4]); - - cur_col_10[3] = changeUIntScale(hw_white, 0, 1023, 0, adjust_hw); - cur_col_10[4] = 0; - sw_white = changeUIntScale(sw_white, 0, 1023, 0, adjust_sw); - for (uint32_t i=0; i<3; i++) { - uint32_t adjust = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(sw_white, 0, 1023, 0, adjust); - } - rgbwwtable_applied = true; - } - } - - - if (!rgbwwtable_applied) { - for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; - } - - - uint16_t orig_col_10bits[LST_MAX]; - memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; - } - - if (!Settings.light_fade || skip_light_fade || power_off || (!Light.fade_initialized)) { - - memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); - - LightSetOutputs(cur_col_10); - Light.fade_initialized = true; - } else { - if (Light.fade_running) { - - memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); - } - memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); - Light.fade_running = true; - Light.fade_duration = 0; - Light.fade_start = 0; - - } - } - if (Light.fade_running) { - if (LightApplyFade()) { - - - - LightSetOutputs(Light.fade_cur_10); - } - } -#ifdef USE_PWM_DIMMER - - if (PWM_DIMMER == my_module_type && !Light.power && !Light.fade_running) PWMDimmerSetPower(); -#endif - } -} - -bool isChannelGammaCorrected(uint32_t channel) { - if (!Settings.light_correction) { return false; } - if (channel >= Light.subtype) { return false; } -#ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { - if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } - if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } - } -#endif - return true; -} - - -bool isChannelCT(uint32_t channel) { -#ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { - if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } - if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } - } -#endif - return false; -} - - -uint16_t fadeGamma(uint32_t channel, uint16_t v) { - if (isChannelGammaCorrected(channel)) { - return ledGamma_internal(v, gamma_table_fast); - } else { - return v; - } -} -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { - if (isChannelGammaCorrected(channel)) { - return ledGammaReverse_internal(vg, gamma_table_fast); - } else { - return vg; - } -} - -bool LightApplyFade(void) { - static uint32_t last_millis = 0; - uint32_t now = millis(); - - if ((now - last_millis) <= 5) { - return false; - } - last_millis = now; - - - if (0 == Light.fade_duration) { - Light.fade_start = now; - - uint32_t distance = 0; - for (uint32_t i = 0; i < Light.subtype; i++) { - int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); - if (channel_distance < 0) { channel_distance = - channel_distance; } - if (channel_distance > distance) { distance = channel_distance; } - } - if (distance > 0) { - - - - Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; - if (Settings.save_data) { - - uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; - - if (save_data_counter < delay_seconds) { - save_data_counter = delay_seconds; - } - } - } else { - - Light.fade_running = false; - } - } - - uint16_t fade_current = now - Light.fade_start; - if (fade_current <= Light.fade_duration) { - - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.fade_cur_10[i] = fadeGamma(i, - changeUIntScale(fadeGammaReverse(i, fade_current), - 0, Light.fade_duration, - fadeGammaReverse(i, Light.fade_start_10[i]), - fadeGammaReverse(i, Light.fade_end_10[i]))); - - - - } - } else { - - - Light.fade_running = false; - Light.fade_start = 0; - Light.fade_duration = 0; - - memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); - - memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); - } - return true; -} - - - -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { - - if (Light.pwm_multi_channels) { - - for (uint32_t i = 0; i < LST_MAX; i++) { - if (0 == bitRead(power,i)) { - new_color[i] = 0; - } - } - - - - - - } else { - if (!light_controller.isCTRGBLinked()) { - - if (0 == (power & 1)) { - new_color[0] = new_color[1] = new_color[2] = 0; - } - if (0 == (power & 2)) { - new_color[3] = new_color[4] = 0; - } - } else if (!power) { - for (uint32_t i = 0; i < LST_MAX; i++) { - new_color[i] = 0; - } - } - } -} - -void LightSetOutputs(const uint16_t *cur_col_10) { - - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { - if (PinUsed(GPIO_PWM1, i)) { - - uint16_t cur_col = cur_col_10[i + Light.pwm_offset]; - if (!isChannelCT(i)) { - cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; - } - if (!Settings.flag4.zerocross_dimmer) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col); - } - } - } - } - - - - - uint8_t cur_col[LST_MAX]; - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = change10to8(cur_col_10[i]); - } - - - 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]; - 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]; - } - - char *tmp_data = XdrvMailbox.data; - char *tmp_topic = XdrvMailbox.topic; - XdrvMailbox.data = (char*)cur_col; - XdrvMailbox.topic = (char*)scale_col; - if (XlgtCall(FUNC_SET_CHANNELS)) { } - else if (XdrvCall(FUNC_SET_CHANNELS)) { } - XdrvMailbox.data = tmp_data; - XdrvMailbox.topic = tmp_topic; -} - - -void calcGammaMultiChannels(uint16_t cur_col_10[5]) { - - if (Settings.light_correction) { - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } -} - -void calcGammaBulbs(uint16_t cur_col_10[5]) { - - - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - - uint32_t cw1 = Light.subtype - 1; - uint32_t cw0 = Light.subtype - 2; - uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; - uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; - -#ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { - - cur_col_10[cw1] = light_state.getCT10bits(); - - if (Settings.light_correction) { - cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); - } else { - cur_col_10[cw0] = white_bri10_1023; - } - } else -#endif - if (Settings.light_correction) { - - if (white_bri10 <= 1031) { - - uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); - - cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); - cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); - } else { - cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); - cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); - } - } - } - - if (Settings.light_correction) { - - if (LST_RGB <= Light.subtype) { - for (uint32_t i = 0; i < 3; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } - - if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { - cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); - } - } -} - -#ifdef USE_DEVICE_GROUPS -void LightSendDeviceGroupStatus(bool status) -{ - static uint8_t last_bri; - uint8_t bri = light_state.getBri(); - bool send_bri_update = (status || bri != last_bri); - if (Light.subtype > LST_SINGLE && !Light.devgrp_no_channels_out) { - static uint8_t channels[LST_MAX + 1] = { 0, 0, 0, 0, 0, 0 }; - if (status) { - light_state.getChannels(channels); - } - else { - memcpy(channels, Light.new_color, LST_MAX); - channels[LST_MAX]++; - } - SendLocalDeviceGroupMessage((send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels); - } - if (send_bri_update) { - last_bri = bri; - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, light_state.getBri()); - } -} - -void LightHandleDevGroupItem(void) -{ - static bool send_state = false; - static bool restore_power = false; - -#ifdef USE_PWM_DIMMER_REMOTE - if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return; -#endif - bool more_to_come; - uint32_t value = XdrvMailbox.payload; - switch (XdrvMailbox.command_code) { - case DGR_ITEM_EOL: - more_to_come = (XdrvMailbox.index & DGR_FLAG_MORE_TO_COME); - if (restore_power && !more_to_come) { - restore_power = false; - Light.power = Light.old_power; - } - - LightAnimate(); - - if (send_state && !more_to_come) { - light_controller.saveSettings(); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - send_state = false; - } - break; - case DGR_ITEM_LIGHT_BRI: - if (light_state.getBri() != value) { - light_state.setBri(value); - send_state = true; - } - break; - case DGR_ITEM_LIGHT_SCHEME: - if (Settings.light_scheme != value) { - Light.last_scheme = Settings.light_scheme = value; - Light.devgrp_no_channels_out = (value != 0); - send_state = true; - } - break; - case DGR_ITEM_LIGHT_CHANNELS: -#ifdef USE_DGR_LIGHT_SEQUENCE - { - static uint8_t last_sequence = 0; - - - - if (Light.sequence_offset) { - light_controller.changeChannels(Light.channels_fifo); - - - - int last_entry = (Light.sequence_offset - 1) * LST_MAX; - for (uint8_t sequence = (uint8_t)XdrvMailbox.data[LST_MAX]; (uint8_t)(sequence - last_sequence) > 0; last_sequence++) { - memmove(Light.channels_fifo, &Light.channels_fifo[LST_MAX], last_entry); - memcpy(&Light.channels_fifo[last_entry], XdrvMailbox.data, LST_MAX); - } - } - else { -#endif - light_controller.changeChannels((uint8_t *)XdrvMailbox.data); -#ifdef USE_DGR_LIGHT_SEQUENCE - } - } -#endif - send_state = true; - break; - case DGR_ITEM_LIGHT_FIXED_COLOR: - if (Light.subtype >= LST_COLDWARM) { - send_state = true; -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count) { - Light.wheel = value % Light.palette_count; - LightSetPaletteEntry(); - break; - } -#endif - if (Light.subtype <= LST_COLDWARM) { - value = value % (MAX_FIXED_COLD_WARM - 1) + 201; - } - else { - uint32_t max = MAX_FIXED_COLOR; - if (Light.subtype >= LST_RGB) { - max++; - if (Light.subtype >= LST_RGBCW) max += (MAX_FIXED_COLD_WARM - 2); - } - value = value % max + 1; - if (value > MAX_FIXED_COLOR) value += 200 - MAX_FIXED_COLOR; - } - Light.fixed_color_index = value; - bool save_decimal_text = Settings.flag.decimal_text; - char str[16]; - LightColorEntry(str, sprintf_P(str, PSTR("%u"), value)); - Settings.flag.decimal_text = save_decimal_text; - uint32_t old_bri = light_state.getBri(); - light_controller.changeChannels(Light.entry_color); - light_controller.changeBri(old_bri); - Settings.light_scheme = 0; - Light.devgrp_no_channels_out = false; - if (!restore_power && !Light.power) { - Light.old_power = Light.power; - Light.power = 0xff; - restore_power = true; - } - } - break; - case DGR_ITEM_LIGHT_FADE: - if (Settings.light_fade != value) { - Settings.light_fade = value; - send_state = true; - } - break; - case DGR_ITEM_LIGHT_SPEED: - if (Settings.light_speed != value && value > 0 && value <= 40) { - Settings.light_speed = value; - send_state = true; - } - break; - case DGR_ITEM_STATUS: - SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, - DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); - LightSendDeviceGroupStatus(true); - break; - } -} -#endif - - - - - -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; -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count) value = Light.wheel; -#endif - - if (buffer[0] == '#') { - buffer++; - buffer_length--; - } - - if (Light.subtype >= LST_RGB) { - char option = (1 == buffer_length) ? buffer[0] : '\0'; - if ('+' == option) { -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count || Light.fixed_color_index < MAX_FIXED_COLOR) { -#else - if (Light.fixed_color_index < MAX_FIXED_COLOR) { -#endif - value++; - } - } - else if ('-' == option) { -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count || Light.fixed_color_index > 1) { -#else - if (Light.fixed_color_index > 1) { -#endif - value--; - } - } else { - value = atoi(buffer); - } -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count) value = value % Light.palette_count; -#endif - } - - memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); - - while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { - buffer_length--; - memcpy(&Light.entry_color, &Light.current_color, 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; - } -#ifdef USE_LIGHT_PALETTE - else if (Light.palette_count) { - value--; - Light.wheel = value; - memcpy_P(&Light.entry_color, &Light.palette[value * LST_MAX], LST_MAX); - entry_type = 1; - } -#endif - 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_RGBCW == 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) { -#ifdef USE_LIGHT_PALETTE - if (Light.palette_count && XdrvMailbox.index == 2) { - LightSetPaletteEntry(); - } - else { -#endif - uint32_t old_bri = light_state.getBri(); - - light_controller.changeChannels(Light.entry_color); - if (2 == XdrvMailbox.index) { - - light_controller.changeBri(old_bri); - } -#ifdef USE_LIGHT_PALETTE - } -#endif - 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.pwm_multi_channels) { return; } - if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(2); - } else { - ResponseCmndNumber(light_state.getDimmer(2)); - } - } -} - -void CmndChannel(void) -{ - - - - - if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { - uint32_t light_index = XdrvMailbox.index - Light.device; - power_t coldim = 0; - - - if (1 == XdrvMailbox.data_len) { - uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; - } else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; - } - } - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - if (Light.pwm_multi_channels) { - coldim = 1 << light_index; - } else { - if (light_controller.isCTRGBLinked()) { - - if ((light_index < 3) && (light_controller.isCTRGBLinked())) { - Light.current_color[3] = Light.current_color[4] = 0; - } else { - Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; - } - coldim = 1; - } else { - if (light_index < 3) { coldim = 1; } - else { coldim = 2; } - } - } - light_controller.changeChannels(Light.current_color); - } - ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); - if (coldim) { - LightPreparePower(coldim); - } - } -} - -void CmndHsbColor(void) -{ - - - - - - - - if (Light.subtype >= LST_RGB) { - if (XdrvMailbox.data_len > 0) { - uint16_t c_hue; - uint8_t c_sat; - light_state.getHSB(&c_hue, &c_sat, nullptr); - uint32_t HSB[3]; - HSB[0] = c_hue; - HSB[1] = c_sat; - HSB[2] = light_state.getBriRGB(); - if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { - if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } - HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); - } else { - uint32_t paramcount = ParseParameters(3, HSB); - if (HSB[0] > 360) { HSB[0] = 360; } - for (uint32_t i = 1; i < paramcount; i++) { - if (HSB[i] > 100) { HSB[i] == 100; } - HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); - } - } - light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(1); - } else { - ResponseLightState(0); - } - } -} - -void CmndScheme(void) -{ - - - - - - if (Light.subtype >= LST_RGB) { - uint32_t max_scheme = Light.max_scheme; - - 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)) { - uint32_t parm[2]; - if (ParseParameters(2, parm) > 1) { - Light.wheel = parm[1]; -#ifdef USE_LIGHT_PALETTE - Light.wheel--; -#endif - } - 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)) { - light_controller.changeDimmer(XdrvMailbox.payload); - } - Light.wakeup_active = 3; - Settings.light_scheme = LS_WAKEUP; - LightPowerOn(); - ResponseCmndChar(D_JSON_STARTED); -} - -void CmndColorTemperature(void) -{ - - - - - if (Light.pwm_multi_channels) { return; } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - uint32_t ct = light_state.getCT(); - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; - } - else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; - } - } - if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { - light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); - LightPreparePower(2); - } else { - ResponseCmndNumber(ct); - } - } -} - -void LightDimmerOffset(uint32_t index, int32_t offset) { - int32_t dimmer = light_state.getDimmer(index) + offset; - if (dimmer < 1) { dimmer = Settings.flag3.slider_dimmer_stay_on; } - if (dimmer > 100) { dimmer = 100; } - - XdrvMailbox.index = index; - XdrvMailbox.payload = dimmer; - CmndDimmer(); -} - -void CmndDimmer(void) -{ - - - - - - - - uint32_t dimmer; - if (XdrvMailbox.index == 3) { - skip_light_fade = true; - XdrvMailbox.index = 0; - } - else if (XdrvMailbox.index > 2) { - XdrvMailbox.index = 1; - } - - if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { - dimmer = light_state.getDimmer(); - } else { - dimmer = light_state.getDimmer(XdrvMailbox.index); - } - - 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)) { - if (light_controller.isCTRGBLinked()) { - - light_controller.changeDimmer(XdrvMailbox.payload); - LightPreparePower(); - } else { - if (0 != XdrvMailbox.index) { - light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); - LightPreparePower(1 << (XdrvMailbox.index - 1)); - } else { - - light_controller.changeDimmer(XdrvMailbox.payload, 1); - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(); - } - } -#if defined(USE_PWM_DIMMER) && defined(USE_DEVICE_GROUPS) - uint8_t bri = light_state.getBri(); - if (bri != Settings.bri_power_on) { - Settings.bri_power_on = bri; - SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); - } -#endif - Light.update = true; - if (skip_light_fade) LightAnimate(); - } else { - ResponseCmndNumber(dimmer); - } - skip_light_fade = false; -} - -void CmndDimmerRange(void) -{ - - - if (XdrvMailbox.data_len > 0) { - uint32_t parm[2]; - parm[0] = Settings.dimmer_hw_min; - parm[1] = Settings.dimmer_hw_max; - ParseParameters(2, parm); - if (parm[0] < parm[1]) { - Settings.dimmer_hw_min = parm[0]; - Settings.dimmer_hw_max = parm[1]; - } else { - Settings.dimmer_hw_min = parm[1]; - Settings.dimmer_hw_max = parm[0]; - } - LightCalcPWMRange(); - Light.update = true; - } - Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); -} - -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; - } - LightCalcPWMRange(); - Light.update = true; - } - ResponseCmndStateText(Settings.light_correction); -} - -void CmndRgbwwTable(void) -{ - - - if ((XdrvMailbox.data_len > 0)) { - uint32_t parm[LST_RGBCW -1]; - uint32_t parmcount = ParseParameters(LST_RGBCW, parm); - for (uint32_t i = 0; i < parmcount; i++) { - Settings.rgbwwTable[i] = parm[i]; - } - Light.update = true; - } - char scolor[LIGHT_COLOR_SIZE]; - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGBCW; i++) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); - } - ResponseCmndChar(scolor); -} - -void CmndFade(void) -{ - - - - - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_fade = XdrvMailbox.payload; - break; - case 2: - Settings.light_fade ^= 1; - break; - } -#ifdef USE_DEVICE_GROUPS - if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); -#endif -#ifdef USE_LIGHT - if (!Settings.light_fade) { Light.fade_running = false; } -#endif - 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 < 40)) { - XdrvMailbox.payload = Settings.light_speed + 1; - } - } - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { - Settings.light_speed = XdrvMailbox.payload; -#ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed); -#endif - } - 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); -} - -#ifdef USE_LIGHT_PALETTE -void CmndPalette(void) -{ - uint8_t * palette_entry; - char * p; - - - if (XdrvMailbox.data_len) { - Light.wheel = 0; - Light.palette_count = 0; - if (Light.palette) { - free(Light.palette); - Light.palette = nullptr; - } - if (XdrvMailbox.data_len > 1 || XdrvMailbox.data[0] != '0') { - uint8_t palette_count = 0; - char * color = XdrvMailbox.data; - if (!(Light.palette = (uint8_t *)malloc(255 * Light.subtype))) return; - palette_entry = Light.palette; - for (;;) { - p = strchr(color, ' '); - if (p) *p = 0; - color = Trim(color); - if (*color && LightColorEntry(color, strlen(color))) { - memcpy(palette_entry, Light.entry_color, Light.subtype); - palette_entry += Light.subtype; - palette_count++; - } - if (!p) break; - color = p + 1; - } - if (!(Light.palette = (uint8_t *)realloc(Light.palette, palette_count * Light.subtype))) return; - Light.palette_count = palette_count; - } - } - - char palette_str[5 * Light.subtype * Light.palette_count + 3]; - p = palette_str; - *p++ = '['; - if (Light.palette_count) { - palette_entry = Light.palette; - for (int entry = 0; entry < Light.palette_count; entry++) { - if (Settings.flag.decimal_text) { - *p++ = '"'; - for (uint32_t i = 0; i < Light.subtype; i++) { - p += sprintf_P(p, PSTR("%d,"), *palette_entry++); - } - *(p - 1) = '"'; - } - else { - for (uint32_t i = 0; i < Light.subtype; i++) { - p += sprintf_P(p, PSTR("%02X"), *palette_entry++); - } - } - *p++ = ','; - } - p--; - } - *p++ = ']'; - *p = 0; - ResponseCmndChar(palette_str); -} -#endif - -#ifdef USE_DGR_LIGHT_SEQUENCE -void CmndSequenceOffset(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { - if (XdrvMailbox.payload != Light.sequence_offset) { - if (Light.sequence_offset) free(Light.channels_fifo); - Light.sequence_offset = XdrvMailbox.payload; - if (Light.sequence_offset) Light.channels_fifo = (uint8_t *)calloc(Light.sequence_offset, LST_MAX); - } - } - ResponseCmndNumber(Light.sequence_offset); -} -#endif - -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 (FUNC_MODULE_INIT == function) { - return LightModuleInit(); - } - else if (light_type) { - switch (function) { - case FUNC_SERIAL: - result = XlgtCall(FUNC_SERIAL); - break; - case FUNC_LOOP: - if (Light.fade_running) { - if (LightApplyFade()) { - LightSetOutputs(Light.fade_cur_10); - } - } - break; - case FUNC_EVERY_50_MSECOND: - LightAnimate(); - break; -#ifdef USE_DEVICE_GROUPS - case FUNC_DEVICE_GROUP_ITEM: - LightHandleDevGroupItem(); - break; -#endif - case FUNC_SET_POWER: - LightSetPower(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kLightCommands, LightCommand); - if (!result) { - result = XlgtCall(FUNC_COMMAND); - } - break; - case FUNC_PRE_INIT: - LightInit(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" -# 55 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" -#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) - - - - -#define XDRV_05 5 - -#include -#include - -enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; - -const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; - - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrSend }; -# 81 "/workspace/Tasmota/tasmota/xdrv_05_irremote.ino" -class IRRawTable { -public: - IRRawTable() : timings() {} - - int32_t getTimingForLetter(uint8_t l) const { - l = toupper(l); - if ((l < 'A') || (l > 'Z')) { return -1; } - return timings[l - 'A']; - } - uint8_t findOrAdd(uint16_t t) { - if (0 == t) { return 0; } - - for (uint32_t i=0; i<26; i++) { - if (timings[i] == t) { return i + 'A'; } - if (timings[i] == 0) { timings[i] = t; break; } - } - return 0; - } - void add(uint16_t t) { - if (0 == t) { return; } - - for (uint32_t i=0; i<26; i++) { - if (timings[i] == 0) { timings[i] = t; break; } - } - } - -protected: - uint16_t timings[26]; -}; - - -static const uint8_t MAX_STANDARD_IR = NEC; -const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; - - - - - -#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(void) -{ - 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[8]; - int8_t iridx = 0; - - decode_results results; - - if (irrecv->decode(&results)) { - char hvalue[65]; - - iridx = results.decode_type; - if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { 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); - } - - IRRawTable raw_table; - bool prev_number = false; - bool ir_high = true; - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); - size_t rawlen = results.rawlen; - uint32_t i; - - for (i = 1; i < rawlen; i++) { - - uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; - uint16_t raw_dms = (raw_val_millis*2 + 5) / 10; - - uint8_t letter = raw_table.findOrAdd(raw_dms); - if (letter) { - if (!ir_high) { letter = tolower(letter); } - ResponseAppend_P(PSTR("%c"), letter); - prev_number = false; - } else { - - ResponseAppend_P(PSTR("%c%d"), ir_high ? '+' : '-', (uint32_t)raw_dms * 5); - prev_number = true; - } - ir_high = !ir_high; - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = getCorrectedRawLength(&results); - ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - -#ifdef USE_DOMOTICZ - if (iridx) { - unsigned long value = results.value | (iridx << 28); - DomoticzSensor(DZ_COUNT, value); - } -#endif - } - - irrecv->resume(); - } -} -#endif - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - - - - RemoveSpace(XdrvMailbox.data); - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { return IE_INVALID_JSON; } - - - - const char *protocol = root.getStr(PSTR(D_JSON_IR_PROTOCOL), ""); - uint16_t bits = root.getUInt(PSTR(D_JSON_IR_BITS), 0); - uint64_t data = root.getULong(PSTR(D_JSON_IR_DATA), 0); - uint16_t repeat = root.getUInt(PSTR(D_JSON_IR_REPEAT), 0); - - - 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 - 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 = IE_INVALID_JSON; - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar_P(PSTR(D_JSON_INVALID_RAWDATA)); - break; - case IE_INVALID_JSON: - ResponseCmndChar_P(PSTR(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; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) { - switch (function) { - case FUNC_PRE_INIT: - if (PinUsed(GPIO_IRSEND)) { - IrSendInit(); - } -#ifdef USE_IR_RECEIVE - if (PinUsed(GPIO_IRRECV)) { - IrReceiveInit(); - } -#endif - break; - case FUNC_EVERY_50_MSECOND: -#ifdef USE_IR_RECEIVE - if (PinUsed(GPIO_IRRECV)) { - IrReceiveCheck(); - } -#endif - irsend_active = false; - break; - case FUNC_COMMAND: - if (PinUsed(GPIO_IRSEND)) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" -# 55 "/workspace/Tasmota/tasmota/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, IE_MEMORY }; - -const char kIrRemoteCommands[] PROGMEM = "|" - D_CMND_IRHVAC "|" D_CMND_IRSEND ; - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrHvac, &CmndIrSend }; -# 85 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" -class IRRawTable { -public: - IRRawTable() : timings() {} - - int32_t getTimingForLetter(uint8_t l) const { - l = toupper(l); - if ((l < 'A') || (l > 'Z')) { return -1; } - return timings[l - 'A']; - } - uint8_t findOrAdd(uint16_t t) { - if (0 == t) { return 0; } - - for (uint32_t i=0; i<26; i++) { - if (timings[i] == t) { return i + 'A'; } - if (timings[i] == 0) { timings[i] = t; break; } - } - return 0; - } - void add(uint16_t t) { - if (0 == t) { return; } - - for (uint32_t i=0; i<26; i++) { - if (timings[i] == 0) { timings[i] = t; break; } - } - } - -protected: - uint16_t timings[26]; -}; - - - - - -IRsend *irsend = nullptr; -bool irsend_active = false; - - -bool irhvac_stateful = true; -stdAc::state_t irac_prev_state; - - -enum class StateModes { SEND_ONLY, - STORE_ONLY, - SEND_STORE }; -StateModes strToStateMode(class JsonParserToken token, StateModes def); - -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(void) -{ - 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) { - JsonGeneratorObject json; - json.add(PSTR(D_JSON_IRHVAC_VENDOR), typeToString(state.protocol)); - json.add(PSTR(D_JSON_IRHVAC_MODEL), state.model); - - - if (state.mode == stdAc::opmode_t::kOff || !state.power) { - json.add(PSTR(D_JSON_IRHVAC_MODE), IRac::opmodeToString(stdAc::opmode_t::kOff)); - json.add(PSTR(D_JSON_IRHVAC_POWER), IRac::boolToString(false)); - } else { - json.add(PSTR(D_JSON_IRHVAC_MODE), IRac::opmodeToString(state.mode)); - json.add(PSTR(D_JSON_IRHVAC_POWER), IRac::boolToString(state.power)); - } - json.add(PSTR(D_JSON_IRHVAC_CELSIUS), IRac::boolToString(state.celsius)); - if (floorf(state.degrees) == state.degrees) { - json.add(PSTR(D_JSON_IRHVAC_TEMP), (int32_t) floorf(state.degrees)); - } else { - - json.addStrRaw(PSTR(D_JSON_IRHVAC_TEMP), String(state.degrees, 1).c_str()); - } - - json.add(PSTR(D_JSON_IRHVAC_FANSPEED), IRac::fanspeedToString(state.fanspeed)); - json.add(PSTR(D_JSON_IRHVAC_SWINGV), IRac::swingvToString(state.swingv)); - json.add(PSTR(D_JSON_IRHVAC_SWINGH), IRac::swinghToString(state.swingh)); - json.add(PSTR(D_JSON_IRHVAC_QUIET), IRac::boolToString(state.quiet)); - json.add(PSTR(D_JSON_IRHVAC_TURBO), IRac::boolToString(state.turbo)); - json.add(PSTR(D_JSON_IRHVAC_ECONO), IRac::boolToString(state.econo)); - json.add(PSTR(D_JSON_IRHVAC_LIGHT), IRac::boolToString(state.light)); - json.add(PSTR(D_JSON_IRHVAC_FILTER), IRac::boolToString(state.filter)); - json.add(PSTR(D_JSON_IRHVAC_CLEAN), IRac::boolToString(state.clean)); - json.add(PSTR(D_JSON_IRHVAC_BEEP), IRac::boolToString(state.beep)); - json.add(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); - - String payload = json.toString(); - 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 += "\"0x"; - json += hvalue; - json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; - Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); - json += hvalue; - json += "\""; - } else { - Uint64toHex(results.value, hvalue, 32); - json += "\"0x"; - json += hvalue; - json += "\""; - } - } - } - json += ",\"" D_JSON_IR_REPEAT "\":"; - json += results.repeat; - - stdAc::state_t new_state; - if (IRAcUtils::decodeToState(&results, &new_state, irhvac_stateful && irac_prev_state.protocol == results.decode_type ? &irac_prev_state : nullptr)) { - - json += ",\"" D_CMND_IRHVAC "\":"; - json += sendACJsonState(new_state); - irac_prev_state = new_state; - } - - return json; -} - -void IrReceiveCheck(void) -{ - decode_results results; - - if (irrecv->decode(&results)) { - uint32_t now = millis(); - - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); - - IRRawTable raw_table; - bool prev_number = false; - bool ir_high = true; - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); - size_t rawlen = results.rawlen; - uint32_t i; - - for (i = 1; i < rawlen; i++) { - - uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; - uint16_t raw_dms = (raw_val_millis*2 + 5) / 10; - - uint8_t letter = raw_table.findOrAdd(raw_dms); - if (letter) { - if (!ir_high) { letter = tolower(letter); } - ResponseAppend_P(PSTR("%c"), letter); - prev_number = false; - } else { - - ResponseAppend_P(PSTR("%c%d"), ir_high ? '+' : '-', (uint32_t)raw_dms * 5); - prev_number = true; - } - ir_high = !ir_high; - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = getCorrectedRawLength(&results); - ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - } - - 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; -} - -bool strToBool(class JsonParserToken token, bool def) { - if (token.isBool() || token.isNum()) { - return token.getBool(); - } else if (token.isStr()) { - return IRac::strToBool(token.getStr()); - } else { - return def; - } -} - -StateModes strToStateMode(class JsonParserToken token, StateModes def) { - if (token.isStr()) { - const char * str = token.getStr(); - if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_SEND_ONLY))) - return StateModes::SEND_ONLY; - else if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_STORE_ONLY))) - return StateModes::STORE_ONLY; - else if (!strcasecmp_P(str, PSTR(D_JSON_IRHVAC_STATE_MODE_SEND_STORE))) - return StateModes::SEND_STORE; - } - return def; -} - - -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; - - - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { 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; - - JsonParserToken val; - if (val = root[PSTR(D_JSON_IRHVAC_VENDOR)]) { state.protocol = strToDecodeType(val.getStr()); } - if (val = root[PSTR(D_JSON_IRHVAC_PROTOCOL)]) { state.protocol = strToDecodeType(val.getStr()); } - if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } - if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } - - - JsonParserToken tok_fan_speed = root[PSTR(D_JSON_IRHVAC_FANSPEED)]; - if (tok_fan_speed) { - uint32_t fan_speed = tok_fan_speed.getUInt(); - if ((fan_speed >= 1) && (fan_speed <= 5)) { - state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); - } else { - state.fanspeed = IRac::strToFanspeed(tok_fan_speed.getStr()); - } - } - - if (val = root[PSTR(D_JSON_IRHVAC_MODEL)]) { state.model = IRac::strToModel(val.getStr()); } - if (val = root[PSTR(D_JSON_IRHVAC_MODE)]) { state.mode = IRac::strToOpmode(val.getStr()); } - if (val = root[PSTR(D_JSON_IRHVAC_SWINGV)]) { state.swingv = IRac::strToSwingV(val.getStr()); } - if (val = root[PSTR(D_JSON_IRHVAC_SWINGH)]) { state.swingh = IRac::strToSwingH(val.getStr()); } - state.degrees = root.getFloat(PSTR(D_JSON_IRHVAC_TEMP), state.degrees); - - - - - StateModes stateMode = StateModes::SEND_ONLY; - if (irhvac_stateful && (val = root[PSTR(D_JSON_IRHVAC_STATE_MODE)])) { stateMode = strToStateMode(val, stateMode); } - - - state.power = strToBool(root[PSTR(D_JSON_IRHVAC_POWER)], state.power); - state.celsius = strToBool(root[PSTR(D_JSON_IRHVAC_CELSIUS)], state.celsius); - state.light = strToBool(root[PSTR(D_JSON_IRHVAC_LIGHT)], state.light); - state.beep = strToBool(root[PSTR(D_JSON_IRHVAC_BEEP)], state.beep); - state.econo = strToBool(root[PSTR(D_JSON_IRHVAC_ECONO)], state.econo); - state.filter = strToBool(root[PSTR(D_JSON_IRHVAC_FILTER)], state.filter); - state.turbo = strToBool(root[PSTR(D_JSON_IRHVAC_TURBO)], state.turbo); - state.quiet = strToBool(root[PSTR(D_JSON_IRHVAC_QUIET)], state.quiet); - state.clean = strToBool(root[PSTR(D_JSON_IRHVAC_CLEAN)], state.clean); - - - state.sleep = root.getInt(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); - - - if (stateMode == StateModes::SEND_ONLY || stateMode == StateModes::SEND_STORE) { - IRac ac(Pin(GPIO_IRSEND)); - bool success = ac.sendAc(state, irhvac_stateful && irac_prev_state.protocol == state.protocol ? &irac_prev_state : nullptr); - if (!success) { return IE_SYNTAX_IRHVAC; } - } - if (stateMode == StateModes::STORE_ONLY || stateMode == StateModes::SEND_STORE) { - irac_prev_state = state; - } - - 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) -{ - - - RemoveSpace(XdrvMailbox.data); - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { return IE_INVALID_JSON; } - - - - JsonParserToken value; - - decode_type_t protocol = decode_type_t::UNKNOWN; - value = root[PSTR(D_JSON_IRHVAC_VENDOR)]; - if (root) { protocol = strToDecodeType(value.getStr()); } - value = root[PSTR(D_JSON_IRHVAC_PROTOCOL)]; - if (root) { protocol = strToDecodeType(value.getStr()); } - if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } - - uint16_t bits = root.getUInt(PSTR(D_JSON_IR_BITS), 0); - uint16_t repeat = root.getUInt(PSTR(D_JSON_IR_REPEAT), 0); - - uint64_t data; - value = root[PSTR(D_JSON_IR_DATALSB)]; - if (root) { data = reverseBitsInBytes64(value.getULong()); } - value = root[PSTR(D_JSON_IR_DATA)]; - if (value) { data = value.getULong(); } - if (0 == bits) { return IE_SYNTAX_IRSEND; } - - - if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } - - char dvalue[32]; - char hvalue[32]; - - - - 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; -} -# 549 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" -uint32_t IrRemoteSendGC(char ** pp, uint32_t count, uint32_t repeat) { - - uint16_t GC[count+1]; - for (uint32_t i = 0; i <= count; i++) { - GC[i] = strtol(strtok_r(nullptr, ",", pp), nullptr, 0); - if (!GC[i]) { return IE_INVALID_RAWDATA; } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendGC(GC, count+1); - } - return IE_NO_ERROR; -} - - - - -uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { - if (count < 2) { return IE_INVALID_RAWDATA; } - - - char * str = strtok_r(nullptr, ",", pp); - uint16_t freq = parsqeFreq(str); - - - - uint16_t parm[count-1]; - for (uint32_t i = 0; i < count-1; i++) { - parm[i] = strtol(strtok_r(nullptr, ",", pp), nullptr, 0); - if (0 == parm[i]) { return IE_INVALID_RAWDATA; } - } - - uint16_t i = 0; - if (count < 4) { - - - - - uint16_t mark, space; - space = parm[0]; - mark = space * 2; - if (3 == count) { - if (parm[1] <= 10) { - - mark = parm[0] * parm[1]; - } else { - - mark = parm[1]; - } - } - - - uint16_t raw_array[strlen(*pp)]; - for (; **pp; *(*pp)++) { - if (**pp == '0') { - raw_array[i++] = space; - } - else if (**pp == '1') { - raw_array[i++] = mark; - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - - irsend->sendRaw(raw_array, i, freq); - if (r < repeat) { - irsend->space(40000); - } - } - } else if (6 == count) { - - uint16_t raw_array[strlen(*pp)*2+3]; - raw_array[i++] = parm[0]; - raw_array[i++] = parm[1]; - uint32_t inter_message_32 = (parm[0] + parm[1]) * 3; - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; - for (; **pp; *(*pp)++) { - if (**pp == '0') { - raw_array[i++] = parm[2]; - raw_array[i++] = parm[3]; - } - else if (**pp == '1') { - raw_array[i++] = parm[2]; - raw_array[i++] = parm[4]; - } - } - raw_array[i++] = parm[2]; - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - - irsend->sendRaw(raw_array, i, freq); - if (r < repeat) { - irsend->space(inter_message); - } - } - } - else { return IE_INVALID_RAWDATA; } - return IE_NO_ERROR; -} -# 656 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" -uint32_t IrRemoteParseRawCompact(char * str, uint16_t * arr, size_t arr_len) { - char *p = str; - size_t i = 0; - IRRawTable raw_table; - - for (char *p = str; *p; ) { - int32_t value = -1; - if ((arr_len > 0) && (i >= arr_len)) { return 0; } - - while ((*p == ',') || (*p == '+') || (*p == '-')) { p++; } - if ((*p >= '0') && (*p <= '9')) { - - value = strtoul(p, &p, 10); - raw_table.add(value); - } else { - value = raw_table.getTimingForLetter(*p); - p++; - } - if (value < 0) { return 0; } - if (nullptr != arr) { - arr[i] = value; - } - i++; - } - return i; -} -# 691 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" -uint32_t IrRemoteSendRawStandard(char ** pp, uint32_t count, uint32_t repeat) { - uint16_t freq = parsqeFreq(*pp); - - - - uint16_t * arr = nullptr; - if (count == 0) { - - count = IrRemoteParseRawCompact(*pp, nullptr, 0); - if (0 == count) { return IE_INVALID_RAWDATA; } - } else { - count++; - } - - arr = (uint16_t*) malloc(count * sizeof(uint16_t)); - if (nullptr == arr) { return IE_MEMORY; } - - count = IrRemoteParseRawCompact(*pp, arr, count); - - - if (0 == count) { return IE_INVALID_RAWDATA; } - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(arr, count, freq); - } - - if (nullptr != arr) { - free(arr); - } - return IE_NO_ERROR; - - - - count++; - if (count < 200) { - uint16_t raw_array[count]; - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", pp), 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, ", ", pp), nullptr, 0); - } - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } -} - - -uint16_t parsqeFreq(char * str) { - uint16_t freq = atoi(str); - if (0 == freq) { freq = 38000; } - return freq; -} - -uint32_t IrRemoteCmndIrSendRaw(void) -{ -# 772 "/workspace/Tasmota/tasmota/xdrv_05_irremote_full.ino" - 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 count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - - - if (strcasecmp(str, "gc") == 0) { - - - return IrRemoteSendGC(&p, count, repeat); - } else if (strcasecmp(str, "raw") == 0) { - - - - - return IrRemoteSendRawFormatted(&p, count, repeat); - } else { - - - - return IrRemoteSendRawStandard(&p, count, repeat); - } -} - -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_P(PSTR(D_JSON_INVALID_RAWDATA)); - break; - case IE_INVALID_JSON: - ResponseCmndChar_P(PSTR(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; - case IE_MEMORY: - ResponseCmndChar_P(PSTR(D_JSON_MEMORY_ERROR)); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) { - switch (function) { - case FUNC_PRE_INIT: - if (PinUsed(GPIO_IRSEND)) { - IrSendInit(); - } - if (PinUsed(GPIO_IRRECV)) { - IrReceiveInit(); - } - break; - case FUNC_EVERY_50_MSECOND: - if (PinUsed(GPIO_IRRECV)) { - IrReceiveCheck(); - } - irsend_active = false; - break; - case FUNC_COMMAND: - if (PinUsed(GPIO_IRSEND)) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_06_snfbridge.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_06_snfbridge.ino" -#ifdef USE_SONOFF_RF - - - - -#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(C2_DEVID_EFM8BB1); - 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(C2_DEVID_EFM8BB1); - 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("\"}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); -} - - - -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); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - #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("\"#%06X\""), 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(PSTR(D_JSON_START_LEARNING)); - } - else if (3 == XdrvMailbox.payload) { - Settings.rf_code[XdrvMailbox.index][0] = 0; - ResponseCmndIdxChar(PSTR(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(PSTR(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(PSTR(D_JSON_DEFAULT_SENT)); - } else { - SonoffBridgeSend(XdrvMailbox.index, 0); - ResponseCmndIdxChar(PSTR(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; - -#ifdef ESP8266 - 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: - SetSerial(19200, TS_SERIAL_8N1); - break; - } - } -#endif - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" -#ifdef USE_DOMOTICZ - -#define XDRV_07 7 - - -#define D_PRFX_DOMOTICZ "Dz" -#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" -#define D_CMND_DZSEND "Send" - -const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" - D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER "|" D_CMND_DZSEND ; - -void (* const DomoticzCommand[])(void) PROGMEM = { - &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer, &CmndDomoticzSend }; - -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 "|" D_DOMOTICZ_SHUTTER ; - -const char kDomoticzCommand[] PROGMEM = "switchlight|switchscene"; - -char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; - -int domoticz_update_timer = 0; -uint32_t domoticz_fan_debounce = 0; -bool domoticz_subscribe = false; -bool domoticz_update_flag = true; - -#ifdef USE_SHUTTER -bool domoticz_is_shutter = false; -#endif - -int DomoticzBatteryQuality(void) { - - - - - int quality = 100; - -#ifdef ESP8266 -#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 -#endif - return quality; -} - -int DomoticzRssiQuality(void) { - - - return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; -} - -#ifdef USE_SONOFF_IFAN -void MqttPublishDomoticzFanState(void) { - 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(void) { - if (domoticz_update_flag) { - MqttPublishDomoticzFanState(); - } - domoticz_update_flag = true; -} -#endif - -void MqttPublishDomoticzPowerState(uint8_t device) { - if (Settings.flag.mqtt_enabled) { - if (device < 1) { device = 1; } - if ((device > devices_present) || (device > MAX_DOMOTICZ_IDX)) { return; } - if (Settings.domoticz_relay_idx[device -1]) { -#ifdef USE_SHUTTER - if (domoticz_is_shutter) { - - } else { -#endif -#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 -#ifdef USE_SHUTTER - } -#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_SHUTTER - if (domoticz_is_shutter) - { - - break; - } -#endif -#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(DOMOTICZ_OUT_TOPIC "/#")); - MqttSubscribe(stopic); - } -} - -bool DomoticzMqttData(void) { - - - - - - - domoticz_update_flag = true; - - if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { - return false; - } - - - if (XdrvMailbox.data_len < 20) { - return true; - } - - String domoticz_data = XdrvMailbox.data; - JsonParser parser((char*)domoticz_data.c_str()); - JsonParserObject domoticz = parser.getRootObject(); - if (!domoticz) { - return true; - } - - - - uint32_t idx = domoticz.getUInt(PSTR("idx"), 0); - int16_t nvalue = domoticz.getInt(PSTR("nvalue"), -1); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - - 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.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0; - bool isShutter = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0 & strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0; - - char stemp1[10]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { - JsonParserToken svalue_tok = domoticz[PSTR("svalue1")]; - if (!svalue_tok) { - return true; - } - uint8_t svalue = svalue_tok.getUInt(); - svalue = (2 == nvalue) ? 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 -#ifdef USE_SHUTTER - if (isShutter) { - uint8_t position = domoticz.getUInt(PSTR("svalue1"), 0); - if (nvalue != 2) { - position = (0 == nvalue) ? 0 : 100; - } - - snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); - XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); - - found = true; - } else -#endif -#ifdef USE_LIGHT - if (iscolordimmer && 10 == nvalue) { - - JsonParserObject color = domoticz[PSTR("Color")].getObject(); - - uint16_t level = nvalue = domoticz.getUInt(PSTR("svalue1"), 0); - uint16_t r = color.getUInt(PSTR("r"), 0) * level / 100; - uint16_t g = color.getUInt(PSTR("g"), 0) * level / 100; - uint16_t b = color.getUInt(PSTR("b"), 0) * level / 100; - uint16_t cw = color.getUInt(PSTR("cw"), 0) * level / 100; - uint16_t ww = color.getUInt(PSTR("ww"), 0) * level / 100; - uint16_t m = color.getUInt(PSTR("m"), 0); - uint16_t t = color.getUInt(PSTR("t"), 0); - if (2 == m) { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); - } else { - 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[PSTR("svalue1")]) { - nvalue = domoticz.getUInt(PSTR("svalue1"), 0); - } 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 -#endif - 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; -} - - - -void DomoticzSendSwitch(uint32_t type, uint32_t index, uint32_t state) { - char stemp[16]; - Response_P(PSTR("{\"command\":\"%s\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - GetTextIndexed(stemp, sizeof(stemp), type, kDomoticzCommand), index, (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); - MqttPublish(domoticz_in_topic); -} - -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)) { - DomoticzSendSwitch(0, (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], state); - result = true; - } - } - return result; -} -# 362 "/workspace/Tasmota/tasmota/xdrv_07_domoticz.ino" -void DomoticzSendData(uint32_t sensor_idx, uint32_t idx, char *data) { - if (DZ_AIRQUALITY == sensor_idx) { - Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), - idx, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } else { - uint8_t nvalue = 0; -#ifdef USE_SHUTTER - if (DZ_SHUTTER == sensor_idx) { - uint8_t position = atoi(data); - nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); - } -#endif - Response_P(DOMOTICZ_MESSAGE, - idx, nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } - MqttPublish(domoticz_in_topic); -} - -void DomoticzSensor(uint8_t idx, char *data) { - if (Settings.domoticz_sensor_idx[idx]) { - char dmess[128]; - - memcpy(dmess, mqtt_data, sizeof(dmess)); - DomoticzSendData(idx, Settings.domoticz_sensor_idx[idx], data); - memcpy(mqtt_data, dmess, sizeof(dmess)); - } -} - -uint8_t DomoticzHumidityState(float h) { - return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; -} - -void DomoticzSensor(uint8_t idx, uint32_t value) { - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d"), value); - DomoticzSensor(idx, data); -} - - -void DomoticzTempHumPressureSensor(float temp, float hum, float baro) { - char temperature[FLOATSZ]; - dtostrfd(temp, 2, temperature); - char humidity[FLOATSZ]; - dtostrfd(hum, 2, humidity); - - char data[32]; - if (baro > -1) { - char pressure[FLOATSZ]; - dtostrfd(baro, 2, pressure); - - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temperature, humidity, DomoticzHumidityState(hum), pressure); - DomoticzSensor(DZ_TEMP_HUM_BARO, data); - } else { - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temperature, humidity, DomoticzHumidityState(hum)); - DomoticzSensor(DZ_TEMP_HUM, 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); -} - -void CmndDomoticzSend(void) { - - - - - - - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char *data; - uint32_t index = strtoul(strtok_r(XdrvMailbox.data, ",", &data), nullptr, 10); - if ((index > 0) && (data != nullptr)) { - if (XdrvMailbox.index > 3) { - uint32_t state = strtoul(data, nullptr, 10); - DomoticzSendSwitch(XdrvMailbox.index -4, index, state); - } else { - uint32_t type = DZ_TEMP; - if (2 == XdrvMailbox.index) { type = DZ_SHUTTER; } - else if (3 == XdrvMailbox.index) { type = DZ_AIRQUALITY; } - DomoticzSendData(type, index, data); - } - } - } - } - } -} - - - - - -#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 (PinUsed(GPIO_SWT1, i)) { - 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(PSTR("/" WEB_HANDLE_DOMOTICZ), HandleDomoticzConfiguration); - break; -#endif - case FUNC_MQTT_SUBSCRIBE: - DomoticzMqttSubscribe(); -#ifdef USE_SHUTTER - if (Settings.domoticz_sensor_idx[DZ_SHUTTER]) { domoticz_is_shutter = true; } -#endif - 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 "/workspace/Tasmota/tasmota/xdrv_08_serial_bridge.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_08_serial_bridge.ino" -#ifdef USE_SERIAL_BRIDGE - - - - -#define XDRV_08 8 -#define HARDWARE_FALLBACK 2 - -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) { - bool in_byte_is_delimiter = - (((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || - ((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && - !serial_bridge_raw; - - if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && - !in_byte_is_delimiter) { - serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; - } - - if ((serial_bridge_in_byte_counter >= SERIAL_BRIDGE_BUFFER_SIZE -1) || - in_byte_is_delimiter) { - serial_bridge_polling_window = 0; - break; - } - - serial_bridge_polling_window = millis(); - } - } - - if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { - serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; - bool assume_json = (!serial_bridge_raw && (serial_bridge_buffer[0] == '{')); - - Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":")); - if (assume_json) { - ResponseAppend_P(serial_bridge_buffer); - } else { - ResponseAppend_P(PSTR("\"")); - if (serial_bridge_raw) { - char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; - ResponseAppend_P(ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char))); - } else { - ResponseAppend_P(EscapeJSONString(serial_bridge_buffer).c_str()); - } - ResponseAppend_P(PSTR("\"")); - } - ResponseJsonEnd(); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); - serial_bridge_in_byte_counter = 0; - } -} - - - -void SerialBridgeInit(void) -{ - serial_bridge_active = false; - if (PinUsed(GPIO_SBR_RX) && PinUsed(GPIO_SBR_TX)) { - SerialBridgeSerial = new TasmotaSerial(Pin(GPIO_SBR_RX), Pin(GPIO_SBR_TX), HARDWARE_FALLBACK); - 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 <= 6)) { - 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 > 1) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - SerialBridgeSerial->write(code); - size -= 2; - codes += 2; - } - } - else if (6 == XdrvMailbox.index) { - char *p; - uint8_t code; - char *values = XdrvMailbox.data; - for (char* str = strtok_r(values, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { - code = (uint8_t)atoi(str); - SerialBridgeSerial->write(code); - } - } - 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 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" -#ifdef USE_TIMERS -# 39 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xdrv_09_timers.ino" -const float pi2 = TWO_PI; -const float pi = PI; -const float RAD = DEG_TO_RAD; - - - -uint32_t JulianDate(const struct TIME_T &now) { - - - uint32_t Year = now.year; - uint32_t Month = now.month; - uint32_t Day = now.day_of_month; - uint32_t Julian; - - if (Month <= 2) { - Month += 12; - Year -= 1; - } - - - Julian = (1461 * Year + 6884416) / 4 + (153 * Month - 457) / 5 + Day; - return Julian; -} - - -float InPi(float x) -{ - return ModulusRangef(x, 0.0f, pi2); -} - - - -float TimeFormula(float *DK, uint32_t Tdays) { - float RA_Mean = 18.71506921f + (2400.0513369f / 36525.0f) * Tdays; - float M = InPi( (pi2 * 0.993133f) + (pi2 * 99.997361f / 36525.0f) * Tdays); - float L = InPi( (pi2 * 0.7859453f) + M + (6893.0f * sinf(M) + 72.0f * sinf(M+M) + (6191.2f / 36525.0f) * Tdays) * (pi2 / 1296.0e3f)); - - float eps = 0.40904f; - float cos_eps = 0.91750f; - float sin_eps = 0.39773f; - - float RA = atanf(tanf(L) * cos_eps); - if (RA < 0.0f) RA += pi; - if (L > pi) RA += pi; - RA = RA * (24.0f/pi2); - *DK = asinf(sin_eps * sinf(L)); - RA_Mean = ModulusRangef(RA_Mean, 0.0f, 24.0f); - float dRA = ModulusRangef(RA_Mean - RA, -12.0f, 12.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) -{ - const uint32_t JD2000 = 2451545; - uint32_t JD = JulianDate(RtcTime); - uint32_t Tdays = JD - JD2000; - - - float DK; - - - - - - - const float h = SUNRISE_DAWN_ANGLE * RAD; - const float sin_h = sinf(h); - - float B = Settings.latitude / (1000000.0f / RAD); - - float GeographischeLaenge = ((float)Settings.longitude)/1000000; - - - - float Zeitzone = ((float)Rtc.time_timezone) / 60; - float Zeitgleichung = TimeFormula(&DK, Tdays); - float Zeitdifferenz = acosf((sin_h - sinf(B)*sinf(DK)) / (cosf(B)*cosf(DK))) * (12.0f / 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 + (1/120.0f); - - Aufgang = ModulusRangef(Aufgang, 0.0f, 24.0f); - int AufgangStunden = (int)Aufgang; - int AufgangMinuten = (int)(60.0f * fmodf(Aufgang, 1.0f)); - float Untergang = UntergangWeltzeit + Zeitzone; - - Untergang = ModulusRangef(Untergang, 0.0f, 24.0f); - int UntergangStunden = (int)Untergang; - int UntergangMinuten = (int)(60.0f * fmodf(Untergang, 1.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]; - - if (hour[mode]==255) { - - if ((Settings.latitude > 0) != (RtcTime.month>=4 && RtcTime.month<=9)) { - duskdawn->time=2046; - } else { - duskdawn->time=2047; - } - - return; - } - - - 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]; - if (xtimer.arm) { -#ifdef USE_SUNRISE - if ((1 == xtimer.mode) || (2 == xtimer.mode)) { - ApplyTimerOffsets(&xtimer); - if (xtimer.time>=2046) { continue; } - } -#endif - 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 - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { - Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); - error = 1; - } - else { - char parm_uc[10]; - index--; - JsonParserToken val = root[PSTR(D_JSON_TIMER_ARM)]; - if (val) { - Settings.timer[index].arm = (val.getInt() != 0); - } -#ifdef USE_SUNRISE - val = root[PSTR(D_JSON_TIMER_MODE)]; - if (val) { - Settings.timer[index].mode = val.getUInt() & 0x03; - } -#endif - val = root[PSTR(D_JSON_TIMER_TIME)]; - if (val) { - uint16_t itime = 0; - int8_t value = 0; - uint8_t sign = 0; - char time_str[10]; - - strlcpy(time_str, val.getStr(), 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; - } - val = root[PSTR(D_JSON_TIMER_WINDOW)]; - if (val) { - Settings.timer[index].window = val.getUInt() & 0x0F; - TimerSetRandomWindow(index); - } - val = root[PSTR(D_JSON_TIMER_DAYS)]; - if (val) { - - Settings.timer[index].days = 0; - const char *tday = val.getStr(); - 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++; - } - } - val = root[PSTR(D_JSON_TIMER_REPEAT)]; - if (val) { - Settings.timer[index].repeat = (val.getUInt() != 0); - } - val = root[PSTR(D_JSON_TIMER_OUTPUT)]; - if (val) { - uint8_t device = (val.getUInt() -1) & 0x0F; - Settings.timer[index].device = (device < devices_present) ? device : 0; - } - val = root[PSTR(D_JSON_TIMER_ACTION)]; - if (val) { - uint8_t action = val.getUInt() & 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); - } - ResponseCmndFloat((float)(Settings.longitude) /1000000, 6); -} - -void CmndLatitude(void) -{ - if (XdrvMailbox.data_len) { - Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); - } - ResponseCmndFloat((float)(Settings.latitude) /1000000, 6); -} -#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 = - "

"; - -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_TIMER_SCRIPT1_SIZE = 106; -const char HTTP_TIMER_SCRIPT1_COMPRESSED[] PROGMEM = "\x33\xBF\xA1\x94\x7C\x3D\xE3\xDF\x3A\x83\xA3\xE1\xC4\x8F\x04\x60\x5F\x07\x5B\x9C" - "\x83\x67\x77\x4E\xA3\x51\xDE\x3D\xA6\x77\xF5\x87\xC1\x30\x31\x63\x5F\x51\xD0\x3F" - "\xBB\xA6\x4C\x26\x35\xF5\x1D\xD3\xEF\x06\x56\xE7\x1F\x67\x78\xF1\x87\x4A\x66\xCA" - "\x20\xF3\xA9\xF5\x1F\x34\xF0\x6A\x3A\x58\xC1\x8F\x84\x20\xC5\x68\x42\x1D\xDC\x3B" - "\xC7\x83\xDC"; -#define HTTP_TIMER_SCRIPT1 Decompress(HTTP_TIMER_SCRIPT1_COMPRESSED,HTTP_TIMER_SCRIPT1_SIZE).c_str() -#else -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);" - "}"; -#endif - -#ifdef USE_SUNRISE -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_TIMER_SCRIPT2_SIZE = 630; -const char HTTP_TIMER_SCRIPT2_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x43\xD4\x77\x4E\xF1\xED\x33\xBF\xA1\xA7\x50\xC3\xA8\xD4\x78" - "\x1A\x7C\x35\x78\xEE\x9F\x7B\xC3\x05\xD1\xEF\x75\x8D\x67\xC3\xD9\xF1\x0F\x61\xEF" - "\x9E\x61\x8A\x61\x9A\x31\x0F\xB3\xBC\x74\x33\xB0\x85\xB3\xC0\xC3\xE0\xCA\x3D\xE0" - "\xE8\xF7\xCF\xD1\xC6\x46\xC3\x9E\x22\x30\x46\x0F\x1A\x60\xEE\x8D\x3E\x1F\x0E\x33" - "\xBC\x7B\x4B\xD8\x77\x4E\x33\xBC\x78\x23\x51\xF0\x86\xDD\x0A\x3A\x18\x0B\x33\xE7" - "\x74\x61\xD8\x73\x99\xDE\x3C\x16\x98\x3B\xA6\xA3\xD0\xE4\x67\x78\xF6\x91\xA8\xF8" - "\x7D\x9C\x67\xD9\xDB\x23\x51\xE0\xF7\x1A\xBC\x77\x4F\xB3\xC8\x56\x02\x1E\x5E\x7C" - "\x35\x1E\x0D\x47\xC1\x87\xD1\xF4\x73\x99\x02\x9E\x10\x37\x41\x1B\x08\x3D\xDA\x60" - "\xEE\x9D\xD1\xA7\xC3\xE1\xC8\x77\x8F\xF1\xFE\x3B\xA4\x34\xF8\x7C\x39\x47\x78\xEF" - "\x1E\xD2\xF6\x1D\xD3\x90\x81\x53\x59\x3F\x0F\x87\x25\x1D\xE3\xDA\x46\xA3\xAC\xF8" - "\x72\x51\xE0\x8D\x5E\x3B\xA7\xD9\xE4\x27\xCF\xB3\xBC\x74\xF3\x09\x87\x4C\x42\xDE" - "\x11\x9B\x0F\x87\x21\xE0\xF7\x13\x0B\xCC\xF6\x82\x9D\xC3\x8C\xF0\x7B\x88\x19\x67" - "\x04\x87\xB8\x11\x38\xE6\xF6\x1D\xD1\xC7\x78\xF6\xE1\xF0\x11\x32\xD3\xC3\x3E\x61" - "\xD0\x31\x5A\x10\x84\xC2\x63\x5F\x51\x07\x82\xFA\x8F\x1A\x60\xEE\x8E\x3E\x1F\x0E" - "\x43\xBC\x40\x8F\xC0\x1D\x19\x04\xCE\x86\x7B\xED\x1D\xA1\x6D\x19\x1F\x0F\xB3\xEC" - "\xF1\xA6\x0E\xEB\x3F\x0E\x4A\x3B\xC7\xB4\x8C\x67\xCE\xEE\x9F\x0E\x4A\x3C\x16\x9E" - "\x87\xC3\x95\x67\x82\xD3\xB6\x76\xCE\xF1\xED\xC3\xA7\xD8\xDC\x33\x64\x18\xAD\x08" - "\x43\xBB\x87\x40\xAF\xD4\x08\x7A\x08\xAD\x08\x43\xBC\x78\x3D\xC7\xB8\x13\x38\x68" - "\x04\xCD\x04\x56\x88\x23\xE0\x41\xD1\xCF\x43\x95\x64\x0A\x3A\x38\x6C\xEE\xE9\xD5" - "\x87\x78\xF0\x7B\x8F\x71\xEE\x3D\xC6"; -#define HTTP_TIMER_SCRIPT2 Decompress(HTTP_TIMER_SCRIPT2_COMPRESSED,HTTP_TIMER_SCRIPT2_SIZE).c_str() -#else -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').style.visibility='';" - "if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" - "}else{" - "qs('#dr').style.visibility='hidden';" - "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" - "}" - "}"; -#endif -#endif - -#ifdef USE_UNISHOX_COMPRESSION -#ifdef USE_SUNRISE -const size_t HTTP_TIMER_SCRIPT3_SIZE = 587; -const char HTTP_TIMER_SCRIPT3_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x5E\xA3\xBA\x77\x8F\x69\x9D\xFD\x69\xD4\x11\xD4\x34\xEA\xE3" - "\xA8\x61\xD5\xE3\xC0\xD3\xE1\xC6\x78\x2F\x1F\x0E\x33\xC1\x71\xF0\xE4\x3D\x0F\x4B" - "\x87\x82\xD3\x07\x75\x8E\x3B\xA7\xDD\x9C\x67\xD9\xDE\x3A\x10\x62\x98\x66\x8C\x43" - "\xBC\x7B\x7C\x7F\x8F\x9C\x78\x3D\xDC\x7C\x39\x0F\x43\xD2\x69\x02\x1D\xFF\x82\x75" - "\xF3\x19\xF3\xBB\xA7\xC3\x8C\xF0\x5A\x7A\x1C\xF1\xE0\xB4\xED\x9D\xB3\xBC\x7B\x78" - "\xF8\x72\x1E\x87\xA1\xDD\x9C\x76\xCB\x4E\xF0\x21\xE2\x83\xE7\xD9\xDB\xD0\x4C\xC5" - "\x4F\x70\xD3\xE1\xAB\xC7\x74\xFB\xDE\x18\x2E\x8F\x7B\xAC\x6B\x3E\x1E\xCF\x88\x7B" - "\x0F\x7C\xF3\x04\x2C\x0C\xFB\x3B\xC7\x43\x3B\x08\x5B\x3C\x78\xFF\x1F\x0E\xE8\x2F" - "\xE0\xA7\xA1\xE8\x72\x91\xDE\x3C\x16\x98\x3B\xA7\xD0\x87\xE1\xC6\x77\x8F\x69\x69" - "\xF0\xD5\xE3\xBA\x7D\x9E\x42\x1C\x87\xD9\xDE\x3A\x17\x98\x4C\x3A\x62\x16\xF0\x8C" - "\xD8\x78\xD3\x07\x77\x4F\xC3\xE1\xC6\x77\x8F\x69\x78\xFF\x1F\x0E\xEE\x9E\x87\xA1" - "\xCA\xB3\xBC\x78\x3D\xC4\x08\x7A\x11\xE4\x30\x13\x30\xD3\xD0\xF4\x39\x5E\x3B\xC7" - "\x83\xDC\x4C\x2F\x33\xDB\xE3\xFC\x7C\x39\x67\xA1\xE9\x5E\x3C\x1E\xE2\x08\xF8\x77" - "\x41\x07\x0D\x15\x80\x97\x86\x9E\xB3\x9C\xCE\xF1\xDB\x23\x57\x8E\xE9\xF6\x79\x0D" - "\xD0\x4B\xB0\x77\x8F\xD1\xC6\x46\xC3\x9E\x22\x30\x46\x0F\x1A\x60\xEE\x8D\x3E\x02" - "\x16\xC2\x11\xE0\xF7\x69\x83\xBA\x77\x46\x9F\x0F\x87\x21\xDE\x3F\xC7\xF8\xEE\x90" - "\xD3\xE1\xF0\xE5\x1D\xE3\xBC\x7B\x4B\x4C\x02\x0E\x78\x27\xC1\x2F\x20\x3F\x0E\x33" - "\xBC\x7B\x4B\x4C\x1D\xD0\x8F\xC3\x8C\xEF\x1E\xD2\x08\xED\x9F\x0E\x7A\x99\xE0\xF7" - "\x1E\xE2\xF1\xFE\x3E\x04\x08\x59\xC1\xEE\xF1\xFE\x04\x3D\xE4\x68\xF8\x27\xEB\xA7" - "\x19\x11\x83\xBC\x7A\x1E\x87\x24\x3C\x10\xCA\x3D\xE0\xE8\xF7\xCF\x9E\x3C\x31\xC7" - "\x74\xFB\xA3\x8C\x81\x0F\x8A\x63\xE0\xCA\x3A\x1A\xF3\x78\xEE\x9D\xE3\xC1\xEE"; -#define HTTP_TIMER_SCRIPT3 Decompress(HTTP_TIMER_SCRIPT3_COMPRESSED,HTTP_TIMER_SCRIPT3_SIZE).c_str() -#else -const size_t HTTP_TIMER_SCRIPT3_SIZE = 424; -const char HTTP_TIMER_SCRIPT3_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x5E\xA3\xBA\x77\x8F\x69\x9D\xFD\x69\xD4\x11\xD4\x34\xEA\xE3" - "\xA8\x61\xD5\xE3\xC0\xD3\xE1\xC6\x78\x2F\x1F\x0E\x33\xC1\x71\xF0\xE4\x3D\x0F\x4B" - "\x87\x82\xD3\x07\x75\x8E\x3B\xA7\xDD\x9C\x67\xD9\xDE\x3A\x10\x62\x98\x66\x8C\x43" - "\xBC\x7B\x7C\x7F\x8F\x9C\x78\x3D\xDC\x7C\x39\x0F\x43\xD2\x69\x02\x1D\xFF\x82\x75" - "\xF3\x19\xF3\xBB\xA7\xC3\x8C\xF0\x5A\x7A\x1C\xF1\xE0\xB4\xED\x9D\xB3\xBC\x7B\x78" - "\xF8\x72\x1E\x87\xA1\xDD\x9C\x76\xCB\x4E\xF0\x21\xE2\x83\xE7\xD9\xDB\xD0\x4C\xC5" - "\x4F\x76\x98\x3B\xA7\xD0\x87\xE1\xC6\x77\x8F\x69\x69\xF0\xD5\xE3\xBA\x7D\x9E\x42" - "\x1C\x87\xD9\xDE\x3A\x17\x98\x4C\x3A\x62\x16\xF0\x8C\xD8\x78\xD3\x07\x77\x4F\xC3" - "\xE1\xC6\x77\x8F\x69\x78\xFF\x1F\x0E\xEE\x9E\x87\xA1\xCA\xB3\xBC\x78\x3D\xC5\xE3" - "\xFC\x7C\x3B\xA6\xAF\x1D\xD3\xEC\xF2\x18\x09\x98\x69\xE8\x7A\x1C\xAF\x1D\xE3\xC1" - "\xEE\x26\x17\x99\xED\xF1\xFE\x3E\x1C\xB3\xD0\xF4\xAF\x1E\x0F\x71\x04\x7C\x3B\xA0" - "\x83\x86\x8A\xC0\x4B\xC3\x4F\x59\xCE\x67\x78\xED\x91\xAB\xC7\x74\xFB\x3C\x86\xE8" - "\x25\xD8\x3B\xC7\xE8\xE3\x23\x61\xCF\x11\x18\x23\x07\x8D\x30\x77\x46\x9F\x01\x0B" - "\x61\x08\x10\x75\xB0\x41\xCA\xC6\x8F\x82\x7E\x1E\x71\x91\x18\x3B\xC7\xA1\xE8\x72" - "\x43\xC1\x0C\xA3\xDE\x0E\x8F\x7C\xF9\xE3\xC3\x1C\x77\x4F\xBA\x38\xCF\xB3\xBC\x74" - "\x23\x3B\x08\x5B\x3E\x0C\xA3\xA1\xAF\x37\x8E\xE9\xDE\x3C\x1E\xE3"; -#define HTTP_TIMER_SCRIPT3 Decompress(HTTP_TIMER_SCRIPT3_COMPRESSED,HTTP_TIMER_SCRIPT3_SIZE).c_str() -#endif -#else -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){if(l>0){l+=720;}}" - "s|=l&0x7FF;" - "}" -#endif - "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" - "pt[ct]=s;" - "eb('t0').value=pt.join();" - "}"; -#endif - -#ifdef USE_UNISHOX_COMPRESSION -#ifdef USE_SUNRISE -const size_t HTTP_TIMER_SCRIPT4_SIZE = 548; -const char HTTP_TIMER_SCRIPT4_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x59\x47\x76\x8E\xA6\x77\x8F\x69\x9D\xFD\x69\xD5\xC7\x56\x1D" - "\x43\x0E\xA3\x51\xD5\xE3\xC6\x98\x3B\xA1\xD1\xE8\x71\x23\xBC\x7B\x4B\xD4\x77\x4E" - "\xF1\xE0\xF7\x07\x47\xCA\x3C\x61\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35" - "\xF5\x78\x87\x19\x10\x61\x5F\xBC\x5D\x63\x59\xDD\x3E\xE8\x23\xEC\xEF\x1E\x0C\x67" - "\xCE\xEE\x9F\x0E\x33\xC1\x69\xE9\x87\x40\x9F\x0F\x50\xA3\xC6\x9D\xB3\xB6\x77\x8F" - "\x6E\x1E\xF6\x9E\xF9\xD3\xD4\x64\x13\x3A\x07\xEF\x15\x33\x65\x1F\x0F\x60\xEB\x0C" - "\xD0\x7B\xF8\x2F\x84\x3C\xCF\x23\xE8\xE3\xE2\x36\x1E\x03\xC0\xB3\xE0\x85\x20\xC6" - "\x75\x1D\x63\xEF\x47\x85\x51\xE7\xD9\xF1\xB6\x11\xE0\xF6\x1E\xE6\x0C\x53\x1F\x1D" - "\x81\x08\x78\x3D\x87\x8F\x1F\x06\x51\xEF\x07\x47\xBE\x78\x18\x7C\x3B\xBE\x3F\x0F" - "\xC3\x94\x8E\xF1\xFA\xB3\xC1\x31\xC7\x74\xFB\x1C\x7D\x9D\xB1\x87\x78\xE8\x18\xA6" - "\x19\xA3\x10\xF8\x72\x1E\x08\x7A\x8E\xE9\xDE\x3C\x1A\x8F\x87\x77\xC7\xE1\xF8\x72" - "\x43\xBC\x7E\x99\x1B\x08\xC1\xE3\x4C\x1D\xD3\x51\xE8\x72\x33\xBC\x7B\x48\xD4\x7C" - "\x3E\xCE\x33\xEC\xED\x91\xA8\xF0\x7B\x8D\x5E\x3B\xA7\xD9\xE4\x34\x7C\xFB\x3B\xC7" - "\x43\x3B\x08\x5B\x3E\x1A\x81\x1B\x85\xB3\x9E\x20\x41\xE1\x50\x10\x74\x43\xBA\x72" - "\x71\xDB\x2D\x3B\xC7\x78\xFD\x1C\x87\x82\x63\x8E\xE9\xF6\x3E\x7D\x9D\xBD\x04\x5D" - "\x20\x61\xE0\xF7\x69\x83\xBA\x7D\x08\x7E\x1C\x64\x08\x78\x51\xCA\xB2\x04\x1D\x34" - "\xD5\xE3\xBA\x7D\x9E\x42\x1C\x84\x08\x99\xD8\xC3\xB6\x72\x10\x21\xF0\x28\x73\xC7" - "\x78\xFD\x59\x02\x0D\xC1\x87\x21\xF6\x77\x8E\x85\xE6\x13\x0E\x98\x85\xBC\x23\x36" - "\x1F\x06\x1E\x0F\x70\x20\xE0\x67\x26\x90\x21\xE9\xFF\x38\xCF\xB2\x04\x7D\x38\x10" - "\x6D\x9C\xB8\x40\x87\x6E\xC1\x26\xD9\xEE"; -#define HTTP_TIMER_SCRIPT4 Decompress(HTTP_TIMER_SCRIPT4_COMPRESSED,HTTP_TIMER_SCRIPT4_SIZE).c_str() -#else -const size_t HTTP_TIMER_SCRIPT4_SIZE = 620; -const char HTTP_TIMER_SCRIPT4_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x59\x47\x76\x8E\xA6\x77\x8F\x69\x9D\xFD\x69\xD5\xC7\x56\x1D" - "\x43\x0E\xA3\x51\xD5\xE3\xC6\x98\x3B\xA1\xD1\xE8\x71\x23\xBC\x7B\x4B\xD4\x77\x4E" - "\xF1\xE0\xF7\x07\x47\xCA\x3C\x61\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26\x35" - "\xF5\x78\x87\x19\x10\x61\x5F\xBC\x5D\x63\x59\xDD\x3E\xE8\x23\xEC\xEF\x1E\x0C\x67" - "\xCE\xEE\x9F\x0E\x33\xC1\x69\xE9\x87\x40\x9F\x0F\x50\xA3\xC6\x9D\xB3\xB6\x77\x8F" - "\x6E\x1E\xF6\x9E\xF9\xD3\xD4\x64\x13\x3A\x07\xEF\x15\x33\x65\x1F\x0F\x60\xEB\x0C" - "\xD0\x7B\xF8\x2F\x84\x3C\xCF\x23\xE8\xE3\xE2\x36\x1E\x03\xC0\xB3\xE0\x85\x20\xC6" - "\x75\x1D\x63\xEF\x47\x85\x51\xE7\xD9\xF1\xB6\x11\xE0\xF6\x1E\xE6\x0C\x53\x1F\x1D" - "\x81\x08\x78\x3D\x87\x8F\x1F\x06\x51\xEF\x07\x47\xBE\x78\x18\x7C\xF1\xFA\x38\xC8" - "\xD8\x73\xC4\x46\x08\xC1\xE0\xD4\x7C\x21\xB7\x42\x8E\x86\x02\xCC\xF9\xDD\x18\x76" - "\x1C\xE6\x77\x8F\x05\xA6\x0E\xE9\xA8\xF4\x39\x19\xDE\x3D\xA4\x6A\x3E\x1F\x67\x19" - "\xF6\x76\xC8\xD4\x78\x3D\xC6\xAF\x1D\xD3\xEC\xF2\x15\x87\xD9\xDE\x3A\x19\xD8\x42" - "\xD9\xF0\xD4\x78\x35\x1F\x06\x1F\x47\xD1\xCE\x64\x0A\x78\x40\xDD\x04\x8C\x20\xEE" - "\xF8\xFC\x3F\x0E\x48\x77\x8F\xD3\x23\x61\x18\x05\x4C\x38\x7C\x11\xB0\xE0\x45\xE2" - "\x8C\xE7\x88\x10\x78\x9C\x18\x7C\x3B\xBE\x3F\x0F\xC3\xBA\x72\x71\xDB\x2D\x3B\xC7" - "\x78\xFD\x1C\x87\x82\x63\x8E\xE9\xF6\x3E\x7D\x9D\xBD\x3B\xC7\x40\xC5\x30\xCD\x18" - "\x87\xC1\x87\x83\xDD\xA6\x0E\xE9\xF4\x21\xF8\x71\x90\x21\xE1\x47\x2A\x2B\xC8\x10" - "\x74\xD3\x57\x8E\xE9\xF6\x79\x08\x72\x10\x22\x67\x63\x0E\xD9\xC8\x78\x20\x42\xBC" - "\x73\xC7\x78\xFD\x59\x02\x0D\xC1\x87\x21\xF6\x77\x8E\x85\xE6\x13\x0E\x98\x85\xBC" - "\x23\x36\x1F\x06\x1E\x0F\x70\x20\xE0\x67\x26\x90\x21\xE9\xFF\x38\xCF\xB2\x04\x7D" - "\x38\x10\x6D\x9C\xB8\x40\x87\x6E\xC1\x26\xD9\xEE"; -#define HTTP_TIMER_SCRIPT4 Decompress(HTTP_TIMER_SCRIPT4_COMPRESSED,HTTP_TIMER_SCRIPT4_SIZE).c_str() -#endif -#else -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;" - "}"; -#endif - -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+=\" \"}" - - "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 " " - "
" - "



" - "



" - "

" - "
" - " " - "" - "

" - "
"; -#ifdef USE_SUNRISE -const char HTTP_FORM_TIMER3[] PROGMEM = - "
" - "
" - "
" - "
" - "
" - "

" - "" - " "; -#else -const char HTTP_FORM_TIMER3[] PROGMEM = - "" D_TIMER_TIME " "; -#endif - -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_FORM_TIMER4_SIZE = 249; -const char HTTP_FORM_TIMER4_COMPRESSED[] PROGMEM = "\x3D\x3C\x32\xF8\xFC\x3D\x3C\xC2\x61\xD2\xF5\x19\x04\xCF\x87\xD8\xFE\x89\x42\x8F" - "\x33\x9C\xC8\x61\xB0\xF0\x7D\xAD\x10\xF8\x7D\x8A\xC3\xEC\xFC\x3D\x0E\xC0\x41\xC0" - "\x4F\xC3\xD0\xEC\xF0\xCB\xE3\xF0\xFD\x70\xEF\x0C\x3C\x1F\x5E\x04\x18\x80\xC0\x72" - "\x41\xBA\x09\xD9\x23\x1B\xE1\x87\x83\xD0\x71\xF8\x76\xCE\xC3\xAC\xF4\x3B\x07\x02" - "\x16\x68\x0C\x0B\x2C\x1F\x04\xDC\xB0\xF4\x3B\x04\xD3\x33\xF0\xF4\x1D\xF3\xF0\xF4" - "\x13\x4C\xD6\x88\x7C\x3E\xC4\xF1\xF6\xBA\xC6\xB3\xE1\xF6\x27\x8F\xB0\x42\xBA"; -#define HTTP_FORM_TIMER4 Decompress(HTTP_FORM_TIMER4_COMPRESSED,HTTP_FORM_TIMER4_SIZE).c_str() -#else -const char HTTP_FORM_TIMER4[] PROGMEM = - "" - " " D_HOUR_MINUTE_SEPARATOR " " - "" - " +/- " - "" - "

" - "
"; -#endif - -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 -#ifdef USE_UNISHOX_COMPRESSION - WSContentSend_P(HTTP_FORM_TIMER4,D_HOUR_MINUTE_SEPARATOR); -#else - WSContentSend_P(HTTP_FORM_TIMER4); -#endif - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void TimerSaveSettings(void) -{ - char tmp[MAX_TIMERS *12]; - char message[LOGSZ]; - Timer timer; - - Settings.flag3.timers_enable = Webserver->hasArg("e0"); - WebGetArg("t0", tmp, sizeof(tmp)); - char *p = tmp; - snprintf_P(message, sizeof(message), 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(message, sizeof(message), PSTR("%s,0x%08X"), message, Settings.timer[i].data); - } - AddLog_P(LOG_LEVEL_DEBUG, message); -} -#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(PSTR("/" 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 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -#ifdef USE_RULES -#ifndef USE_SCRIPT -# 68 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -#define XDRV_10 10 - -#include - -#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 = "+-*/%^\0"; - #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; - uint16_t mems_event = 0; - bool teleperiod = false; - bool busy = 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>16) -#error MAX_RULE_MEMS is bigger than 16 -#endif -# 214 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -#ifdef USE_UNISHOX_COMPRESSION - -String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; - -#endif - - -inline bool IsRuleUncompressed(uint32_t idx) { -#ifdef USE_UNISHOX_COMPRESSION - return Settings.rules[idx][0] ? true : false; -#else - return true; -#endif -} - - -inline bool IsRuleEmpty(uint32_t idx) { -#ifdef USE_UNISHOX_COMPRESSION - return (Settings.rules[idx][0] == 0) && (Settings.rules[idx][1] == 0) ? true : false; -#else - return (Settings.rules[idx][0] == 0) ? true : false; -#endif -} - - -size_t GetRuleLen(uint32_t idx) { - - if (IsRuleUncompressed(idx)) { - return strlen(Settings.rules[idx]); - } else { - return Settings.rules[idx][1] * 8; - } -} - - -size_t GetRuleLenStorage(uint32_t idx) { -#ifdef USE_UNISHOX_COMPRESSION - if (Settings.rules[idx][0] || !Settings.rules[idx][1]) { - return 1 + strlen(Settings.rules[idx]); - } else { - return 2 + strlen(&Settings.rules[idx][1]); - } -#else - return 1 + strlen(Settings.rules[idx]); -#endif -} - -#ifdef USE_UNISHOX_COMPRESSION - -void GetRule_decompress(String &rule, const char *rule_head) { - size_t buf_len = 1 + *rule_head * 8; - rule_head++; - - rule = Decompress(rule_head, buf_len); -} -#endif - - - - - -String GetRule(uint32_t idx) { - if (IsRuleUncompressed(idx)) { - return String(Settings.rules[idx]); - } else { -#ifdef USE_UNISHOX_COMPRESSION - - String rule(""); - if (Settings.rules[idx][1] == 0) { return rule; } - - - if (0 == k_rules[idx].length() ) { - GetRule_decompress(rule, &Settings.rules[idx][1]); - if (!Settings.flag4.compress_rules_cpu) { - k_rules[idx] = rule; - } - } else { - - rule = k_rules[idx]; - } - return rule; -#endif - } - return ""; -} - -#ifdef USE_UNISHOX_COMPRESSION - - -int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out, size_t out_len) { - int32_t len_compressed; - len_compressed = compressor.unishox_compress(in, in_len, out, out_len); - - if (len_compressed >= 0) { - - k_rules[idx] = (const char*) nullptr; - if ((!Settings.flag4.compress_rules_cpu) && out) { - - k_rules[idx] = in; - } - } - return len_compressed; -} -#endif - - - - -int32_t SetRule(uint32_t idx, const char *content, bool append = false) { - if (nullptr == content) { content = ""; } - size_t len_in = strlen(content); - bool needsCompress = false; - size_t offset = 0; - - if (len_in >= MAX_RULE_SIZE) { - needsCompress = true; - } - if (append) { - if (IsRuleUncompressed(idx) || IsRuleEmpty(idx)) { - offset = strlen(Settings.rules[idx]); - if (len_in + offset >= MAX_RULE_SIZE) { - needsCompress = true; - } - } else { - needsCompress = true; - } - } - - if (!needsCompress) { - strlcpy(Settings.rules[idx] + offset, content, sizeof(Settings.rules[idx])); - if (0 == Settings.rules[idx][0]) { - Settings.rules[idx][1] = 0; - } - -#ifdef USE_UNISHOX_COMPRESSION - if (0 != len_in + offset) { - - int32_t len_compressed, len_uncompressed; - - len_uncompressed = strlen(Settings.rules[idx]); - len_compressed = compressor.unishox_compress(Settings.rules[idx], len_uncompressed, nullptr , MAX_RULE_SIZE + 8); - AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Stored uncompressed, would compress from %d to %d (-%d%%)"), len_uncompressed, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_uncompressed, 0, 100)); - } - -#endif - - return len_in + offset; - } else { -#ifdef USE_UNISHOX_COMPRESSION - int32_t len_compressed; - - char *buf_out = (char*) malloc(MAX_RULE_SIZE + 8); - if (!buf_out) { return -1; } - - - if (append) { - String content_append = GetRule(idx); - content_append += content; - len_in = content_append.length(); - len_compressed = SetRule_compress(idx, content_append.c_str(), len_in, buf_out, MAX_RULE_SIZE + 8); - } else { - len_compressed = SetRule_compress(idx, content, len_in, buf_out, MAX_RULE_SIZE + 8); - } - - if ((len_compressed >= 0) && (len_compressed < MAX_RULE_SIZE - 2)) { - - Settings.rules[idx][0] = 0; - Settings.rules[idx][1] = (len_in + 7) / 8; - memcpy(&Settings.rules[idx][2], buf_out, len_compressed); - Settings.rules[idx][len_compressed + 2] = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Compressed from %d to %d (-%d%%)"), len_in, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_in, 0, 100)); - - - } else { - len_compressed = -1; - - k_rules[idx] = (const char *) nullptr; - } - free(buf_out); - return len_compressed; - -#else - return -1; -#endif - } - -} - - - -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all_rules) -{ - - - - - bool match = false; - char stemp[10]; - - - String rule_expr = rule; - if (Rules.teleperiod) { - int ppos = rule_expr.indexOf("TELE-"); - if (ppos == -1) { return false; } - rule_expr = rule.substring(5); - } - - String rule_name, rule_param; - int8_t compareOperator = parseCompareExpression(rule_expr, rule_name, rule_param); - - - - - - - char rule_svalue[80] = { 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 = SettingsText(SET_MEM1 + i); - break; - } - } - if (rule_param.startsWith(F("%TIME%"))) { - rule_param = String(MinutesPastMidnight()); - } - if (rule_param.startsWith(F("%UPTIME%"))) { - rule_param = String(MinutesUptime()); - } - if (rule_param.startsWith(F("%TIMESTAMP%"))) { - rule_param = GetDateAndTime(DT_LOCAL).c_str(); - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - if (rule_param.startsWith(F("%SUNRISE%"))) { - rule_param = String(SunMinutes(0)); - } - if (rule_param.startsWith(F("%SUNSET%"))) { - rule_param = String(SunMinutes(1)); - } -#endif -# 478 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" - 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); - } - } - - - int pos; - int rule_name_idx = 0; - if ((pos = rule_name.indexOf("[")) > 0) { - 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); - } - - String buf = event; - - - - JsonParser parser((char*)buf.c_str()); - JsonParserObject obj = parser.getRootObject(); - if (!obj) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: No valid JSON (%s)"), buf.c_str()); - return false; - } - String subtype; - uint32_t i = 0; - while ((pos = rule_name.indexOf("#")) > 0) { - subtype = rule_name.substring(0, pos); - obj = obj[subtype.c_str()].getObject(); - if (!obj) { return false; } - - rule_name = rule_name.substring(pos +1); - if (i++ > 10) { return false; } - - yield(); - } - - JsonParserToken val = obj[rule_name.c_str()]; - if (!val) { return false; } - const char* str_value; - if (rule_name_idx) { - if (val.isArray()) { - str_value = (val.getArray())[rule_name_idx -1].getStr(); - } else { - str_value = val.getStr(); - } - } else { - str_value = val.getStr(); - } - - - - - 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 (stop_all_rules) { match = false; } - - - - 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; -} -# 614 "/workspace/Tasmota/tasmota/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; -} - -void RulesVarReplace(String &commands, const String &sfind, const String &replace) -{ - - - - char *find = (char*)sfind.c_str(); - uint32_t flen = strlen(find); - - String ucommand = commands; - ucommand.toUpperCase(); - char *read_from = (char*)ucommand.c_str(); - char *write_to = (char*)commands.c_str(); - char *found_at; - while ((found_at = strstr(read_from, find)) != nullptr) { - write_to += (found_at - read_from); - memmove_P(write_to, find, flen); - write_to += flen; - read_from = found_at + flen; - } - - commands.replace(find, replace); -} - - - -bool RuleSetProcess(uint8_t rule_set, String &event_saved) -{ - bool serviced = false; - char stemp[10]; - - delay(0); - - - - String rules = GetRule(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); - - String commands = rules.substring(pevt +4, plen); - Rules.event_value = ""; - String event = event_saved; - - - - if (RulesRuleMatch(rule_set, event, event_trigger, stop_all_rules)) { - if (plen == plen2) { stop_all_rules = true; } - commands.trim(); - String ucommand = commands; - ucommand.toUpperCase(); - - - - if ((ucommand.indexOf("IF ") == -1) && - (ucommand.indexOf("EVENT ") != -1) && - (ucommand.indexOf("BACKLOG ") == -1)) { - commands = "backlog " + commands; - } - - RulesVarReplace(commands, 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); - RulesVarReplace(commands, stemp, rules_vars[i]); - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); - RulesVarReplace(commands, stemp, SettingsText(SET_MEM1 +i)); - } - RulesVarReplace(commands, F("%TIME%"), String(MinutesPastMidnight())); - RulesVarReplace(commands, F("%UTCTIME%"), String(UtcTime())); - RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime())); - RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL)); - RulesVarReplace(commands, F("%TOPIC%"), mqtt_topic); - snprintf_P(stemp, sizeof(stemp), PSTR("%06X"), ESP_getChipId()); - RulesVarReplace(commands, F("%DEVICEID%"), stemp); - String mac_address = WiFi.macAddress(); - mac_address.replace(":", ""); - RulesVarReplace(commands, F("%MACADDR%"), mac_address); -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0))); - RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1))); -#endif -#ifdef USE_ZIGBEE - snprintf_P(stemp, sizeof(stemp), PSTR("0x%04X"), Z_GetLastDevice()); - RulesVarReplace(commands, F("%ZBDEVICE%"), String(stemp)); - RulesVarReplace(commands, F("%ZBGROUP%"), String(Z_GetLastGroup())); - RulesVarReplace(commands, F("%ZBCLUSTER%"), String(Z_GetLastCluster())); - RulesVarReplace(commands, F("%ZBENDPOINT%"), String(Z_GetLastEndpoint())); -#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; - } - plen += 6; - Rules.trigger_count[rule_set]++; - } - return serviced; -} - - - -bool RulesProcessEvent(char *json_event) -{ - if (Rules.busy) { return false; } - - Rules.busy = true; - 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 (GetRuleLen(i) && bitRead(Settings.rule_enabled, i)) { - if (RuleSetProcess(i, event_saved)) { serviced = true; } - } - } - - Rules.busy = false; - - return serviced; -} - -bool RulesProcess(void) -{ - return RulesProcessEvent(mqtt_data); -} - -void RulesInit(void) -{ - - bitWrite(Settings.rule_once, 7, 0); - - bitWrite(Settings.rule_once, 6, 0); - - rules_flag.data = 0; - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (0 == GetRuleLen(i)) { - bitWrite(Settings.rule_enabled, i, 0); - bitWrite(Settings.rule_once, i, 0); - } - } - Rules.teleperiod = false; -} - -void RulesEvery50ms(void) -{ - if (Settings.rule_enabled && !Rules.busy) { - 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 (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) { -#else - if (PinUsed(GPIO_SWT1, i)) { -#endif - snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (SwitchState(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, SettingsText(SET_MEM1 +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\":{\"Init\":1}}"), sizeof(json_event)); break; - case 1: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; - case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; - case 3: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; - case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; - case 5: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; - case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; - case 7: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; - case 8: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break; -#ifdef USE_SHUTTER - case 9: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event)); break; - case 10: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event)); break; -#endif - } - if (json_event[0]) { - RulesProcessEvent(json_event); - break; - } - } - mask <<= 1; - } - } - } -} - -uint8_t rules_xsns_index = 0; - -void RulesEvery100ms(void) -{ - if (Settings.rule_enabled && !Rules.busy && (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(); - RulesProcessEvent(mqtt_data); - } - } -} - -void RulesEverySecond(void) -{ - if (Settings.rule_enabled && !Rules.busy) { - 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 && !Rules.busy) { - 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 -# 1021 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -bool RulesMqttData(void) -{ - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { - return false; - } - bool serviced = 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 { - JsonParser parser((char*)sData.c_str()); - JsonParserObject jsonData = parser.getRootObject(); - - String key1 = event_item.Key; - String key2; - if (!jsonData) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - JsonParserToken value_tok = jsonData[key1.c_str()].getObject()[key2.c_str()]; - if (!value_tok) break; - value = value_tok.getStr(); - - - } else { - JsonParserToken value_tok = jsonData[key1.c_str()]; - if (!value_tok) break; - value = value_tok.getStr(); - - - } - } - value.trim(); - - snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); - } - } - return serviced; -} -# 1090 "/workspace/Tasmota/tasmota/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()); -} -# 1170 "/workspace/Tasmota/tasmota/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 -# 1212 "/workspace/Tasmota/tasmota/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; - } -} -# 1251 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -bool findNextNumber(char * &pNumber, float &value) -{ - bool bSucceed = false; - String sNumber = ""; - if (*pNumber == '-') { - sNumber = "-"; - pNumber++; - } - while (*pNumber) { - if (isdigit(*pNumber) || (*pNumber == '.')) { - sNumber += *pNumber; - pNumber++; - } else { - break; - } - } - if (sNumber.length() > 0) { - value = CharToFloat(sNumber.c_str()); - bSucceed = true; - } - return bSucceed; -} -# 1287 "/workspace/Tasmota/tasmota/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(SettingsText(SET_MEM1 + 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 -# 1335 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" - } else { - succeed = false; - } - - return succeed; -} -# 1359 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -bool findNextObjectValue(char * &pointer, float &value) -{ - bool bSucceed = false; - while (*pointer) - { - if (isspace(*pointer)) { - pointer++; - continue; - } - if (isdigit(*pointer) || (*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 - 1); - pointer = closureBracket + 1; - bSucceed = true; - } - break; - } else { - break; - } - } - return bSucceed; -} -# 1403 "/workspace/Tasmota/tasmota/xdrv_10_rules.ino" -bool findNextOperator(char * &pointer, int8_t &op) -{ - bool bSucceed = false; - while (*pointer) - { - if (isspace(*pointer)) { - pointer++; - continue; - } - 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; - } - return bSucceed; -} -# 1440 "/workspace/Tasmota/tasmota/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; -} -# 1493 "/workspace/Tasmota/tasmota/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 == pgm_read_byte(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(void) -{ - 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(); -} -# 1567 "/workspace/Tasmota/tasmota/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; -} -# 1623 "/workspace/Tasmota/tasmota/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; -} -# 1660 "/workspace/Tasmota/tasmota/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 - 1); - pointer = closureBracket + 1; - bSucceed = true; - } - break; - } - pointer++; - } - if (!bSucceed && pointer > pExpr) { - - value = evaluateComparisonExpression(pExpr, pointer - pExpr); - bSucceed = true; - } - return bSucceed; -} -# 1709 "/workspace/Tasmota/tasmota/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); -} -# 1780 "/workspace/Tasmota/tasmota/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; -} -# 1837 "/workspace/Tasmota/tasmota/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; -} -# 1907 "/workspace/Tasmota/tasmota/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; - } - } - } -} -# 1971 "/workspace/Tasmota/tasmota/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) -{ - if (0 == XdrvMailbox.index) { - char data = '\0'; - if (XdrvMailbox.data_len > 0) { - if (!((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10))) { - if ('"' == XdrvMailbox.data[0]) { - data = '"'; - } else { - XdrvMailbox.data_len = 0; - } - } - } - for (uint32_t i = 1; i <= MAX_RULE_SETS; i++) { - XdrvMailbox.index = i; - XdrvMailbox.data[0] = data; - CmndRule(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); - } - mqtt_data[0] = '\0'; - return; - } - uint8_t index = XdrvMailbox.index; - if ((index > 0) && (index <= MAX_RULE_SETS)) { - - if (XdrvMailbox.data_len > 0) { - 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 { - bool append = false; - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.data[0] = ' '; - append = true; - } - int32_t res = SetRule(index - 1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, append); - if (res < 0) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("RUL: Not enough space")); - } - } - Rules.triggers[index -1] = 0; - } - String rule = GetRule(index - 1); - size_t rule_len = rule.length(); - if (rule_len > MAX_RULE_SIZE - 3) { - - size_t start_index = 0; - while (start_index < rule_len) { - size_t last_index = start_index + MAX_RULE_SIZE - 3; - if (last_index < rule_len) { - int32_t next_index = rule.lastIndexOf(" ", last_index); - if (next_index > 0) { - last_index = next_index; - } - } else { - last_index = rule_len; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Rule%d %s%s"), - index, 0 == start_index ? PSTR("") : PSTR("+"), - rule.substring(start_index, last_index).c_str()); - start_index = last_index + 1; - } - - - rule = rule.substring(0, MAX_RULE_SIZE); - rule += F("..."); - } - - - - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"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)), - rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1), - EscapeJSONString(rule.c_str()).c_str()); - } -} - -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)); -#ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_EVENT, XdrvMailbox.data); -#endif - } - if (XdrvMailbox.command) 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) { - ResponseCmndAll(SET_MEM1, MAX_RULE_MEMS); - } 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, SettingsText(SET_MEM1 + XdrvMailbox.index -1)); - } else { - SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); - } -#else - SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); -#endif - bitSet(Rules.mems_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(SettingsText(SET_MEM1 + 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_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 - case FUNC_PRE_INIT: - RulesInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -# 21 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#ifdef USE_SCRIPT -#ifndef USE_RULES -# 41 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#define XDRV_10 10 -#define XI2C_37 37 - -#define SCRIPT_DEBUG 0 - -#define FORMAT_SPIFFS_IF_FAILED true - - -#ifndef MAXVARS -#define MAXVARS 50 -#endif -#ifndef MAXSVARS -#define MAXSVARS 5 -#endif -#define MAXNVARS MAXVARS-MAXSVARS - -#ifndef MAXFILT -#define MAXFILT 5 -#endif -#define SCRIPT_SVARSIZE 20 -#define SCRIPT_MAXSSIZE 48 -#define SCRIPT_EOL '\n' -#define SCRIPT_FLOAT_PRECISION 2 -#define PMEM_SIZE sizeof(Settings.script_pram) -#define SCRIPT_MAXPERM (PMEM_SIZE)-4/sizeof(float) -#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS - -#define MAX_SARRAY_NUM 32 - -uint32_t EncodeLightId(uint8_t relay_id); -uint32_t DecodeLightId(uint32_t hue_id); - -#ifdef USE_UNISHOX_COMPRESSION -#define USE_SCRIPT_COMPRESSION -#endif - - - -#ifdef USE_SCRIPT_FATFS -#undef LITTLEFS_SCRIPT_SIZE -#undef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION - -#if USE_SCRIPT_FATFS==-1 - -#ifdef ESP32 - -# 87 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script fat file option -1 used" -# 87 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#else - -# 89 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script fat file option -1 used" -# 89 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#endif - -#else - -# 93 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script fat file SDC option used" -# 93 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#endif -#endif - - -#ifdef LITTLEFS_SCRIPT_SIZE -#undef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION - -# 101 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script little file system option used" -# 101 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#endif - - -#ifdef EEP_SCRIPT_SIZE -#undef USE_SCRIPT_COMPRESSION -#ifdef USE_24C256 - -# 108 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script 24c256 file option used" -# 108 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#else - - -# 111 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "internal eeprom script buffer used" -# 111 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - - -#endif -#endif - - -#ifdef USE_SCRIPT_COMPRESSION - -# 118 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -#pragma message "script compression option used" -# 118 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - -#endif - - -#ifdef USE_SCRIPT_COMPRESSION -#include - -#define SCRIPT_COMPRESS compressor.unishox_compress -#define SCRIPT_DECOMPRESS compressor.unishox_decompress -#ifndef UNISHOXRSIZE -#define UNISHOXRSIZE 2560 -#endif -#endif - -#ifndef STASK_PRIO -#define STASK_PRIO 1 -#endif - -#ifdef USE_SCRIPT_TIMER -#include -Ticker Script_ticker1; -Ticker Script_ticker2; -Ticker Script_ticker3; -Ticker Script_ticker4; - -void Script_ticker1_end(void) { - Script_ticker1.detach(); - Run_Scripter(">ti1", 4, 0); -} -void Script_ticker2_end(void) { - Script_ticker2.detach(); - Run_Scripter(">ti2", 4, 0); -} -void Script_ticker3_end(void) { - Script_ticker3.detach(); - Run_Scripter(">ti3", 4, 0); -} -void Script_ticker4_end(void) { - Script_ticker4.detach(); - Run_Scripter(">ti4", 4, 0); -} -#endif - - -#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) -#ifdef ESP32 -#include "FS.h" -#ifdef LITTLEFS_SCRIPT_SIZE -#include "SPIFFS.h" -#else -#include "FFat.h" -#endif -#else -#include -#endif -FS *fsp; -#endif - - -#ifdef LITTLEFS_SCRIPT_SIZE -void SaveFile(const char *name, const uint8_t *buf, uint32_t len) { - File file = fsp->open(name, "w"); - if (!file) return; - file.write(buf, len); - file.close(); -} - - -uint8_t fs_mounted=0; - -void LoadFile(const char *name, uint8_t *buf, uint32_t len) { - if (!fs_mounted) { -#ifdef ESP32 - if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) { -#else - if (!fsp->begin()) { -#endif - - return; - } - fs_mounted=1; - } - File file = fsp->open(name, "r"); - if (!file) return; - file.read(buf, len); - file.close(); -} -#endif - - -#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,SCRIPT_EVENT_HANDLED}; - -#ifdef USE_SCRIPT_FATFS - -#if USE_SCRIPT_FATFS>=0 -#include -#include -#ifdef ESP32 -FS *fsp; -#else -SDClass *fsp; -#endif -#endif - -#ifndef ESP32 - - -#if USE_SCRIPT_FATFS>=0 - -#undef FILE_WRITE -#define FILE_WRITE (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT) -#define FILE_APPEND (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT | sdfat::O_APPEND) - -#else - -#undef FILE_WRITE -#define FILE_WRITE "w" -#undef FILE_READ -#define FILE_READ "r" -#undef FILE_APPEND -#define FILE_APPEND "a" -#endif - -#endif - - -#ifndef FAT_SCRIPT_SIZE -#define FAT_SCRIPT_SIZE 4096 -#endif - -#ifdef ESP32 -#undef FAT_SCRIPT_NAME -#define FAT_SCRIPT_NAME "/script.txt" -#else -#undef FAT_SCRIPT_NAME -#define FAT_SCRIPT_NAME "script.txt" -#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 { -#ifdef USE_SCRIPT_GLOBVARS - uint16_t data; -#else - uint8_t data; -#endif - 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; -#ifdef USE_SCRIPT_GLOBVARS - uint8_t global : 1; -#endif - }; -} SCRIPT_TYPE; - -struct T_INDEX { - uint8_t index; - SCRIPT_TYPE bits; -}; - -struct M_FILT { -#ifdef LARGE_ARRAYS - uint16_t numvals; - uint16_t index; -#else - uint8_t numvals; - uint8_t index; -#endif - float maccu; - float rbuff[1]; -}; - - -#ifdef LARGE_ARRAYS -#undef AND_FILT_MASK -#undef OR_FILT_MASK -#define AND_FILT_MASK 0x7fff -#define OR_FILT_MASK 0x8000 -#undef MAX_ARRAY_SIZE -#define MAX_ARRAY_SIZE 1000 -#else -#undef AND_FILT_MASK -#undef OR_FILT_MASK -#define AND_FILT_MASK 0x7f -#define OR_FILT_MASK 0x80 -#undef MAX_ARRAY_SIZE -#define MAX_ARRAY_SIZE 127 -#endif - - -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; - -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 udp_connected : 1; - uint8_t udp_used : 1; - }; -} UDP_FLAGS; - - -#define NUM_RES 0xfe -#define STR_RES 0xfd -#define VAR_NV 0xff - -#define NTYPE 0 -#define STYPE 0x80 - -#ifndef FLT_MAX -#define FLT_MAX 99999999 -#endif - -#define SFS_MAX 4 - -struct SCRIPT_MEM { - float *fvars; - float *s_fvars; - struct T_INDEX *type; - struct M_FILT *mfilt; - char *glob_vnp; -#ifdef SCRIPT_LARGE_VNBUFF - uint16_t *vnp_offset; -#else - uint8_t *vnp_offset; -#endif - 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 script_lzero; - uint8_t var_not_found; - uint8_t glob_error; - uint8_t max_ssize; - uint8_t script_loglevel; - uint8_t flags; - uint8_t si_num[3]; - uint8_t siro_num[3]; - uint8_t sind_num; - char *last_index_string[3]; - -#ifdef USE_SCRIPT_FATFS - File files[SFS_MAX]; - FILE_FLAGS file_flags[SFS_MAX]; - uint8_t script_sd_found; - char flink[2][14]; -#endif -#ifdef USE_SCRIPT_GLOBVARS - UDP_FLAGS udp_flags; -#endif - char web_mode; -} glob_script_mem; - - - -bool event_handeled = false; - - -#ifdef USE_SCRIPT_GLOBVARS -IPAddress last_udp_ip; -WiFiUDP Script_PortUdp; - -#ifndef USE_DEVICE_GROUPS -char * IPAddressToString(const IPAddress& ip_address) { - static char ipbuffer[16]; - sprintf_P(ipbuffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); - return ipbuffer; -} -#endif -#endif - -int16_t last_findex; -int16_t last_sindex; -uint8_t tasm_cmd_activ=0; -uint8_t fast_script=0; -uint8_t glob_script=0; -uint32_t script_lastmillis; - -void flt2char(float num, char *nbuff) { - dtostrfd(num, glob_script_mem.script_dprec, nbuff); -} - -void f2char(float num, uint32_t dprec, uint32_t lzeros, char *nbuff) { - dtostrfd(num, dprec, nbuff); - if (lzeros>1) { - - uint32_t nd = num; - nd/=10; - nd+=1; - if (lzeros>nd) { - - char cpbuf[24]; - char *cp = cpbuf; - for (uint32_t cnt = 0; cnt < lzeros - nd; cnt++) { - *cp++='0'; - } - *cp=0; - strcat(cpbuf,nbuff); - strcpy(nbuff,cpbuf); - } - } -} - -#ifdef USE_BUTTON_EVENT -int8_t script_button[MAX_KEYS]; -#endif - -char *GetNumericArgument(char *lp,uint8_t lastop,float *fp, JsonParserObject *jo); -char *GetStringArgument(char *lp,uint8_t lastop,char *cp, JsonParserObject *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.0; - 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); -} - - - -#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); - - -#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; -#define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; - -float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos); - - -int16_t Init_Scripter(void) { -char *script; - - script = glob_script_mem.script_ram; - - - uint16_t lines = 0; - uint16_t nvars = 0; - uint16_t svars = 0; - uint16_t 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; - uint8_t numflt = 0; - uint16_t 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=='>' || !*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)) { - - uint16_t flen = atoi(op); - if (flen>MAX_ARRAY_SIZE) { - - flen = MAX_ARRAY_SIZE; - } - mfilt[numflt-1].numvals &= OR_FILT_MASK; - mfilt[numflt-1].numvals |= flen&AND_FILT_MASK; - } - } - - } 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; count MAXVNSIZ) { - free(glob_script_mem.script_mem); - return -5; - } - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR("Script: nv=%d, tv=%d, vns=%d, ram=%d"), nvars, svars, index, glob_script_mem.script_mem_size); - - - char *cp1 = glob_script_mem.glob_snp; - char *sp = strings; - for (count = 0; countnumvals = mfilt[count].numvals; - mp += sizeof(struct M_FILT) + ((mfilt[count].numvals & AND_FILT_MASK) - 1) * sizeof(float); - } - - glob_script_mem.numvars = vars; - glob_script_mem.script_dprec = SCRIPT_FLOAT_PRECISION; - glob_script_mem.script_lzero = 0; - 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; count=0 - - fsp = &SD; - if (SD.begin(USE_SCRIPT_FATFS)) { -#else - -#ifdef ESP32 - - if (FFat.begin(true)) { -#else - if (fsp->begin()) { -#endif - -#endif - - glob_script_mem.script_sd_found = 1; - } else { - glob_script_mem.script_sd_found = 0; - } - } - for (uint8_t cnt = 0; cnt0 - ClaimSerial(); - SetSerialBaudrate(9600); -#endif - - - glob_script_mem.scriptptr = lp - 1; - glob_script_mem.scriptptr_bu = glob_script_mem.scriptptr; - -#ifdef USE_SCRIPT_GLOBVARS - if (glob_script_mem.udp_flags.udp_used) { - Script_Init_UDP(); - glob_script = Run_Scripter(">G", -2, 0); - } -#endif - - return 0; - -} - -#ifdef USE_SCRIPT_FATFS -uint32_t get_fsinfo(uint32_t sel) { -uint32_t result = 0; -#ifdef ESP32 -#if USE_SCRIPT_FATFS >=0 - if (sel == 0) { - result = SD.totalBytes()/1000; - } else if (sel == 1) { - result = (SD.totalBytes() - SD.usedBytes())/1000; - } -#else - if (sel == 0) { - result = FFat.totalBytes()/1000; - } else if (sel == 1) { - result = FFat.freeBytes()/1000; - } -#endif -#else - - FSInfo64 fsinfo; - fsp->info64(fsinfo); - if (sel == 0) { - result = fsinfo.totalBytes/1000; - } else if (sel == 1) { - result = (fsinfo.totalBytes - fsinfo.usedBytes)/1000; - } -#endif - return result; -} - - -void form1000(uint32_t number, char *dp, char sc) { - char str[32]; - sprintf(str, "%d", number); - char *sp = str; - uint32_t inum = strlen(sp)/3; - uint32_t fnum = strlen(sp)%3; - if (!fnum) inum--; - for (uint32_t count=0; count<=inum; count++) { - if (fnum){ - memcpy(dp,sp,fnum); - dp+=fnum; - sp+=fnum; - fnum=0; - } else { - memcpy(dp,sp,3); - dp+=3; - sp+=3; - } - if (count!=inum) { - *dp++=sc; - } - } - *dp=0; -} - -#endif - -#ifdef USE_SCRIPT_GLOBVARS -#define SCRIPT_UDP_BUFFER_SIZE 128 -#define SCRIPT_UDP_PORT 1999 -IPAddress script_udp_remote_ip; - -void Restart_globvars(void) { - Script_Stop_UDP(); - Script_Init_UDP(); -} - -void Script_Stop_UDP(void) { - if (!glob_script_mem.udp_flags.udp_used) return; - if (glob_script_mem.udp_flags.udp_connected) { - Script_PortUdp.flush(); - Script_PortUdp.stop(); - glob_script_mem.udp_flags.udp_connected = 0; - } -} - -void Script_Init_UDP() { - if (global_state.network_down) return; - if (!glob_script_mem.udp_flags.udp_used) return; - if (glob_script_mem.udp_flags.udp_connected) return; - - if (Script_PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP started")); - glob_script_mem.udp_flags.udp_connected = 1; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP failed")); - glob_script_mem.udp_flags.udp_connected = 0; - } -} - -void Script_PollUdp(void) { - if (global_state.network_down) return; - if (!glob_script_mem.udp_flags.udp_used) return; - if (glob_script_mem.udp_flags.udp_connected ) { - while (Script_PortUdp.parsePacket()) { - char packet_buffer[SCRIPT_UDP_BUFFER_SIZE]; - int32_t len = Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE - 1); - packet_buffer[len] = 0; - script_udp_remote_ip = Script_PortUdp.remoteIP(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); - char *lp=packet_buffer; - if (!strncmp(lp,"=>", 2)) { - lp += 2; - char *cp=strchr(lp, '='); - if (cp) { - char vnam[32]; - for (uint32_t count = 0; countG", 2, 0); - } - } - } - } - optimistic_yield(100); - } - } else { - Script_Init_UDP(); - } -} - -void script_udp_sendvar(char *vname,float *fp,char *sp) { - if (!glob_script_mem.udp_flags.udp_used) return; - if (!glob_script_mem.udp_flags.udp_connected) return; - - char sbuf[SCRIPT_MAXSSIZE + 4]; - strcpy(sbuf, "=>"); - strcat(sbuf, vname); - strcat(sbuf, "="); - if (fp) { - char flstr[16]; - dtostrfd(*fp, 8, flstr); - strcat(sbuf, flstr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"), sbuf); - } else { - strcat(sbuf, sp); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"), sbuf); - } - Script_PortUdp.beginPacket(IPAddress(239, 255, 255, 250), SCRIPT_UDP_PORT); - - Script_PortUdp.write((const uint8_t*)sbuf, strlen(sbuf)); - Script_PortUdp.endPacket(); -} - -#endif - -#ifdef USE_LIGHT -#ifdef USE_WS2812 -void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) { - - Ws2812ForceSuspend(); - for (uint32_t cnt = 0; cntSettings.light_pixels) break; - uint32_t col = array[cnt]; - Ws2812SetColor(index + 1, col>>16, col>>8, col, 0); - } - Ws2812ForceUpdate(); -} -#endif -#endif - - - -float median_array(float *array, uint16_t len) { - uint8_t ind[len]; - uint8_t mind = 0; - uint8_t index = 0; - uint8_t flg; - float min = FLT_MAX; - - for (uint8_t hcnt = 0; hcntnumvals & AND_FILT_MASK; - if (ipos) *ipos = mflp->index; - return mflp->rbuff; - } - mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); - } - return 0; -} - -char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonParserObject *jo); - - -float *get_array_by_name(char *name, uint16_t *alen) { - struct T_INDEX ind; - uint8_t vtype; - isvar(name, &vtype, &ind, 0, 0, 0); - if (vtype==VAR_NV) return 0; - if (vtype&STYPE) return 0; - uint16_t index = glob_script_mem.type[ind.index].index; - - if (glob_script_mem.type[ind.index].bits.is_filter) { - float *fa = Get_MFAddr(index, alen, 0); - return fa; - } - return 0; -} - -float Get_MFVal(uint8_t index, int16_t bind) { - uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; - for (uint8_t count = 0; countnumvals & AND_FILT_MASK; - if (!bind) { - return mflp->index; - } - if (bind<0) { - return maxind; - } - if (bind<1 || bind>maxind) bind = maxind; - return mflp->rbuff[bind - 1]; - } - mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); - } - return 0; -} - -void Set_MFVal(uint8_t index, uint16_t bind, float val) { - uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; - for (uint8_t count = 0; countnumvals & AND_FILT_MASK; - 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 & AND_FILT_MASK) - 1) * sizeof(float); - } -} - - -float Get_MFilter(uint8_t index) { - uint8_t *mp = (uint8_t*)glob_script_mem.mfilt; - for (uint8_t count = 0; countnumvals & OR_FILT_MASK) { - - return mflp->maccu / (mflp->numvals & AND_FILT_MASK); - } else { - - return median_array(mflp->rbuff, mflp->numvals); - } - } - mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 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 & OR_FILT_MASK) { - - mflp->maccu -= mflp->rbuff[mflp->index]; - mflp->maccu += invar; - mflp->rbuff[mflp->index] = invar; - mflp->index++; - if (mflp->index>=(mflp->numvals&AND_FILT_MASK)) 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 & AND_FILT_MASK) - 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 - - -#ifdef USE_ANGLE_FUNC -uint32_t pulse_time_hl; -uint32_t pulse_time_lh; -uint32_t pulse_ltime_hl; -uint32_t pulse_ltime_lh; -uint8_t pt_pin; - -#define MPT_DEBOUNCE 10 - -void ICACHE_RAM_ATTR MP_Timer(void) { - uint32_t level = digitalRead(pt_pin&0x3f); - uint32_t ms = millis(); - uint32_t time; - if (level) { - - pulse_ltime_lh = ms; - time = ms - pulse_ltime_hl; - if (time>MPT_DEBOUNCE) pulse_time_hl = time; - } else { - - pulse_ltime_hl = ms; - time = ms - pulse_ltime_lh; - if (time>MPT_DEBOUNCE) pulse_time_lh = time; - } -} - -uint32_t MeasurePulseTime(int32_t in) { - if (in >= 0) { - - pt_pin = in; - pinMode(pt_pin & 0x3f, INPUT_PULLUP); - attachInterrupt(pt_pin & 0x3f, MP_Timer, CHANGE); - pulse_ltime_lh = millis(); - pulse_ltime_hl = millis(); - return 0; - } - uint32_t ptime; - if (in==-1) { - ptime = pulse_time_lh; - pulse_time_lh = 0; - } else { - ptime = pulse_time_hl; - pulse_time_hl = 0; - } - return ptime; -} -#endif - -#ifdef USE_SCRIPT_GLOBVARS -uint32_t match_vars(char *dvnam, float **fp, char **sp, uint32_t *ind) { - uint16_t olen = strlen(dvnam); - struct T_INDEX *vtp = glob_script_mem.type; - for (uint32_t count = 0; count0 && glob_script_mem.last_index_string[isind]) { - free(glob_script_mem.last_index_string[isind]); - } - char *sstart = lp; - uint8_t slen = 0; - for (uint32_t cnt = 0; cnt<256; cnt++) { - if (*lp=='\n' || *lp=='"' || *lp==0) { - lp++; - if (cnt>0 && !slen) { - slen++; - } - glob_script_mem.siro_num[isind] = slen; - break; - } - if (*lp=='|') { - slen++; - } - lp++; - } - - glob_script_mem.si_num[isind] = fvar; - if (glob_script_mem.si_num[isind]>0) { - if (glob_script_mem.si_num[isind]>MAX_SARRAY_NUM) { - glob_script_mem.si_num[isind] = MAX_SARRAY_NUM; - } - - glob_script_mem.last_index_string[isind] = (char*)calloc(glob_script_mem.max_ssize*glob_script_mem.si_num[isind], 1); - for (uint32_t cnt = 0; cntglob_script_mem.si_num[isind]) { - index = glob_script_mem.si_num[isind]; - } - strlcpy(str,glob_script_mem.last_index_string[isind] + (index * glob_script_mem.max_ssize), glob_script_mem.max_ssize); - } - } - lp++; - if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); - return lp; -} - - - -char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonParserObject *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; - last_sindex = -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 = GetNumericArgument(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) { - - char jvname[32]; - strcpy(jvname, vname); - const char* str_value; - uint8_t aindex; - String vn; - char *ja=strchr(jvname, '['); - if (ja) { - - *ja = 0; - ja++; - - float fvar; - GetNumericArgument(ja, OPER_EQU, &fvar, 0); - aindex = fvar; - if (aindex<1 || aindex>6) aindex = 1; - aindex--; - } - if (jo->isValid()) { - char *subtype = strchr(jvname, '#'); - char *subtype2; - if (subtype) { - *subtype = 0; - subtype++; - subtype2 = strchr(subtype, '#'); - if (subtype2) { - *subtype2 = 0; - *subtype2++; - } - } - vn = jvname; - str_value = (*jo)[vn].getStr(); - if ((*jo)[vn].isValid()) { - if (subtype) { - JsonParserObject jobj1 = (*jo)[vn]; - if (jobj1.isValid()) { - vn = subtype; - jo = &jobj1; - str_value = (*jo)[vn].getStr(); - if ((*jo)[vn].isValid()) { - - if (subtype2) { - JsonParserObject jobj2 = (*jo)[vn]; - if ((*jo)[vn].isValid()) { - vn = subtype2; - jo = &jobj2; - str_value = (*jo)[vn].getStr(); - if ((*jo)[vn].isValid()) { - goto skip; - } else { - goto chknext; - } - } else { - goto chknext; - } - } - - goto skip; - } - } else { - goto chknext; - } - } - skip: - if (ja) { - - str_value = (*jo)[vn].getArray()[aindex].getStr(); - } - if (str_value && *str_value) { - if ((*jo)[vn].isStr()) { - if (!strncmp(str_value, "ON", 2)) { - if (fp) *fp = 1; - goto nexit; - } else if (!strncmp(str_value, "OFF", 3)) { - if (fp) *fp = 0; - goto nexit; - } 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); - } - } - nexit: - *vtype = NUM_RES; - tind->bits.constant = 1; - tind->bits.is_string = 0; - return lp + len; - } - } - } - } - } - -chknext: - switch (vname[0]) { - case 'a': -#ifdef USE_ANGLE_FUNC - if (!strncmp(vname, "acos(", 5)) { - lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - fvar = acosf(fvar); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "abs(", 4)) { - lp=GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - fvar = fabs(fvar); - lp++; - len = 0; - goto exit; - } -#endif - if (!strncmp(vname, "asc(", 4)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); - fvar = str[0]; - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "adc(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - while (*lp==' ') lp++; - float fvar1 = 1; - if (*lp!=')') { - lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); - if (fvar1<32 || fvar1>39) fvar1 = 32; - } - lp++; - if (fvar > 7) fvar = 7; -#ifdef ESP32 - -#ifdef USE_ADC - fvar = AdcRead(fvar1, fvar); -#else - fvar = 999.999; -#endif -#else - -#ifndef USE_ADC_VCC - fvar = AdcRead(17, fvar); -#else - fvar = (float)ESP.getVcc() / 1000.0; -#endif -#endif - len = 0; - goto exit; - } - break; - - case 'b': - if (!strncmp(vname, "boot", 4)) { - if (rules_flag.system_boot) { - rules_flag.system_boot = 0; - fvar = 1; - } - goto exit; - } -#ifdef USE_BUTTON_EVENT - if (!strncmp(vname, "bt[", 3)) { - - GetNumericArgument(vname+3, OPER_EQU, &fvar, 0); - 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; - } -#endif - 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; - } - } - } -#ifdef ESP32 - if (!strncmp(vname, "core", 4)) { - fvar = xPortGetCoreID(); - goto exit; - } -#ifdef USE_SCRIPT_TASK - if (!strncmp(vname, "ct(", 3)) { - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); - while (*lp==' ') lp++; - float fvar1; - lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); - while (*lp==' ') lp++; - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - float prio = STASK_PRIO; - if (*lp!=')') { - lp = GetNumericArgument(lp, OPER_EQU, &prio, 0); - } - lp++; - fvar = scripter_create_task(fvar, fvar1, fvar2, prio); - len = 0; - goto exit; - } -#endif -#endif - 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; - } - if (!strncmp(vname, "eres", 4)) { - fvar = event_handeled; - tind->index = SCRIPT_EVENT_HANDLED; - goto exit_settable; - } -#ifdef USE_ENERGY_SENSOR - if (!strncmp(vname, "enrg[", 5)) { - lp=GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - while (*lp==' ') lp++; - switch ((uint32_t)fvar) { - case 0: - fvar = Energy.total; - break; - case 1: - fvar = Energy.voltage[0]; - break; - case 2: - fvar = Energy.voltage[1]; - break; - case 3: - fvar = Energy.voltage[2]; - break; - case 4: - fvar = Energy.current[0]; - break; - case 5: - fvar = Energy.current[1]; - break; - case 6: - fvar = Energy.current[2]; - break; - case 7: - fvar = Energy.active_power[0]; - break; - case 8: - fvar = Energy.active_power[1]; - break; - case 9: - fvar = Energy.active_power[2]; - break; - - default: - fvar = 99999; - break; - } - len = 0; - lp++; - goto exit; - } -#endif - break; - case 'f': - -#ifdef USE_SCRIPT_FATFS - if (!strncmp(vname, "fo(", 3)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - while (*lp==' ') lp++; - uint8_t mode = 0; - if ((*lp=='r') || (*lp=='w') || (*lp=='a')) { - switch (*lp) { - case 'r': - mode = 0; - break; - case 'w': - mode = 1; - break; - case 'a': - mode = 2; - break; - } - lp++; - } else { - lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); - mode = fvar; - } - fvar = -1; - for (uint8_t cnt = 0;cntopen(str, FILE_READ); - if (glob_script_mem.files[cnt].isDirectory()) { - glob_script_mem.files[cnt].rewindDirectory(); - glob_script_mem.file_flags[cnt].is_dir = 1; - } else { - glob_script_mem.file_flags[cnt].is_dir = 0; - } - } - else { - if (mode==1) { - glob_script_mem.files[cnt] = fsp->open(str,FILE_WRITE); -#ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for write %d"), cnt); -#endif - } else { - glob_script_mem.files[cnt] = fsp->open(str,FILE_APPEND); -#ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO, PSTR("open file for append %d"), cnt); -#endif - } - } - if (glob_script_mem.files[cnt]) { - fvar = cnt; - glob_script_mem.file_flags[cnt].is_open = 1; - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("file open failed")); - } - break; - } - } - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "fc(", 3)) { - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); - if (fvar>=0) { - uint8_t ind = fvar; - if (ind>=SFS_MAX) ind = SFS_MAX - 1; -#ifdef DEBUG_FS - AddLog_P2(LOG_LEVEL_INFO, PSTR("closing file %d"), ind); -#endif - 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 = GetNumericArgument(lp + 3, 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)) { - char str[SCRIPT_MAXSSIZE]; - lp = ForceStringVar(lp + 3, str); - while (*lp==' ') lp++; - lp = GetNumericArgument(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)) { - struct T_INDEX ind; - uint8_t vtype; - uint8_t sindex = 0; - lp = isvar(lp + 3, &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 = GetNumericArgument(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())) { - char *ep = (char*)entry.name(); - if (*ep=='/') ep++; - char *lcp = strrchr(ep,'/'); - if (lcp) { - ep = lcp + 1; - } - strcpy(str, ep); - 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)) { - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - fsp->remove(str); - lp++; - len = 0; - goto exit; - } -#if defined(ESP32) && defined(USE_WEBCAM) - if (!strncmp(vname, "fwp(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - while (*lp==' ') lp++; - float fvar1; - lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); - uint8_t ind = fvar1; - if (ind>=SFS_MAX) ind = SFS_MAX - 1; - if (glob_script_mem.file_flags[ind].is_open) { - uint8_t *buff; - float maxps = WcGetPicstore(-1, 0); - if (fvar<1 || fvar>maxps) fvar = 1; - uint32_t len = WcGetPicstore(fvar - 1, &buff); - if (len) { - - fvar = glob_script_mem.files[ind].write(buff, len); - } else { - fvar = 0; - } - - } else { - fvar = 0; - } - lp++; - len = 0; - goto exit; - } -#endif -#ifdef USE_SCRIPT_FATFS_EXT - if (!strncmp(vname, "fe(", 3)) { - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - - File ef = fsp->open(str, FILE_READ); - 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)) { - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); - fvar = fsp->mkdir(str); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "frd(", 4)) { - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); - fvar = fsp->rmdir(str); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "fx(", 3)) { - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - if (fsp->exists(str)) fvar = 1; - else fvar = 0; - lp++; - len = 0; - goto exit; - } - - if (!strncmp(vname, "fsi(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - fvar = get_fsinfo(fvar); - lp++; - len = 0; - goto exit; - } - - if (!strncmp(vname, "fwa(", 4)) { - struct T_INDEX ind; - uint8_t vtype; - lp = isvar(lp + 4, &vtype, &ind, 0, 0, 0); - if (vtype!=VAR_NV && (vtype&STYPE)==0 && glob_script_mem.type[ind.index].bits.is_filter) { - - - } else { - - fvar = 0; - goto exit; - } - - while (*lp==' ') lp++; - lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); - uint8_t index = fvar; - if (index>=SFS_MAX) index = SFS_MAX - 1; - if (glob_script_mem.file_flags[index].is_open) { - uint16_t len = 0; - float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0); - char dstr[24]; - for (uint32_t cnt = 0; cnt=SFS_MAX) find = SFS_MAX - 1; - char str[glob_script_mem.max_ssize + 1]; - if (glob_script_mem.file_flags[find].is_open) { - uint16_t len = 0; - float *fa = Get_MFAddr(glob_script_mem.type[ind.index].index, &len, 0); - char dstr[24]; - for (uint32_t cnt = 0; cnt=glob_script_mem.max_ssize - 1) break; - } - } - *cp = 0; - *fa++=CharToFloat(str); - } - } else { - fvar = 0; - } - lp++; - len = 0; - goto exit; - } - -#endif - if (!strncmp(vname, "fl1(", 4) || !strncmp(vname, "fl2(", 4) ) { - uint8_t lknum = *(lp+2)&3; - char str[glob_script_mem.max_ssize + 1]; - lp = GetStringArgument(lp + 4, 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; - } -#endif - if (!strncmp(vname, "freq", 4)) { -#ifdef ESP32 - fvar = getCpuFrequencyMhz(); -#else - fvar = ESP.getCpuFreqMHz(); -#endif - goto exit; - } - break; - case 'g': - if (!strncmp(vname, "gtmp", 4)) { - fvar = global_temperature_celsius; - goto exit; - } - if (!strncmp(vname, "ghum", 4)) { - fvar = global_humidity; - goto exit; - } - if (!strncmp(vname, "gprs", 4)) { - fvar = global_pressure_hpa; - goto exit; - } - if (!strncmp(vname, "gtopic", 6)) { - if (sp) strlcpy(sp, SettingsText(SET_MQTT_GRP_TOPIC), glob_script_mem.max_ssize); - goto strexit; - } - -#ifdef SCRIPT_GET_HTTPS_JP - if (!strncmp(vname, "gjp(", 4)) { - char host[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 4, OPER_EQU, host, 0); - SCRIPT_SKIP_SPACES - char path[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, path, 0); - fvar = call2https(host, path); - lp++; - len = 0; - goto exit; - } -#endif - 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 = GetNumericArgument(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 = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); - lp++; - len = 0; - if (sp) { - sprintf(sp, "%08x", (uint32_t)fvar); - } - goto strexit; - } - if (!strncmp(vname, "hd(", 3)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - fvar = strtol(str, NULL, 16); - lp++; - len = 0; - goto exit; - } -#ifdef USE_LIGHT - if (!strncmp(vname, "hsvrgb(", 7)) { - lp = GetNumericArgument(lp + 7, OPER_EQU, &fvar, 0); - if (fvar<0 || fvar>360) fvar = 0; - SCRIPT_SKIP_SPACES - - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - if (fvar2<0 || fvar2>100) fvar2 = 0; - SCRIPT_SKIP_SPACES - - float fvar3; - lp = GetNumericArgument(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 = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - fvar = floor(fvar); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "is(", 3)) { - lp = isargs(lp + 3, 0); - fvar = 0; - len = 0; - goto exit; - } - if (!strncmp(vname, "is1(", 4)) { - lp = isargs(lp + 4, 1); - fvar = 0; - len = 0; - goto exit; - } - if (!strncmp(vname, "is2(", 4)) { - lp = isargs(lp + 4, 2); - fvar = 0; - len = 0; - goto exit; - } - if (!strncmp(vname, "is[", 3)) { - lp = isget(lp + 3, sp, 0); - len = 0; - goto strexit; - } - if (!strncmp(vname, "is1[", 4)) { - lp = isget(lp + 4, sp, 1); - len = 0; - goto strexit; - } - if (!strncmp(vname, "is2[", 4)) { - lp = isget(lp + 4, sp, 2); - len = 0; - goto strexit; - } - break; - case 'l': - if (!strncmp(vname, "lip", 3)) { - if (sp) strlcpy(sp, (const char*)WiFi.localIP().toString().c_str(), glob_script_mem.max_ssize); - goto strexit; - } -#ifdef USE_SCRIPT_GLOBVARS - if (!strncmp(vname, "luip", 4)) { - if (sp) strlcpy(sp, IPAddressToString(last_udp_ip), glob_script_mem.max_ssize); - goto strexit; - } -#endif - 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 = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = DoMedian5(fvar1, fvar2); - lp++; - len = 0; - goto exit; - } -#ifdef USE_ANGLE_FUNC - if (!strncmp(vname, "mpt(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - fvar = MeasurePulseTime(fvar); - lp++; - len = 0; - goto exit; - } -#endif - 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; - } - if (!strncmp(vname, "mp(", 3)) { - float fvar1; - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - while (*lp!=')') { - char *opp = lp; - lp++; - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - SCRIPT_SKIP_SPACES - fvar = fvar1; - if ((*opp=='<' && fvar1' && fvar1>fvar2) || - (*opp=='=' && fvar1==fvar2)) { - if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { - float fvar3; - lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); - SCRIPT_SKIP_SPACES - fvar=fvar3; - } else { - fvar = fvar2; - } - break; - } - while (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) lp++; - } - len = 0; - goto exit; - } -#ifdef USE_MORITZ - if (!strncmp(vname, "mo(", 3)) { - float fvar1; - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - SCRIPT_SKIP_SPACES - char rbuff[64]; - fvar = mo_getvars(fvar1, fvar2, rbuff); - lp++; - if (sp) strlcpy(sp, rbuff, glob_script_mem.max_ssize); - len = 0; - goto strexit; - } -#endif - break; - case 'p': - if (!strncmp(vname, "pin[", 4)) { - - GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); - fvar = digitalRead((uint8_t)fvar); - - len++; - goto exit; - } - if (!strncmp(vname, "pn[", 3)) { - GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); - fvar = Pin(fvar); - - len++; - goto exit; - } -#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) - if (!strncmp(vname, "pl(", 3)) { - char path[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, path, 0); - Play_mp3(path); - len++; - len = 0; - goto exit; - } -#endif - if (!strncmp(vname, "pd[", 3)) { - GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); - uint8_t gpiopin = fvar; -# 2640 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) { - fvar = gpio_pin[gpiopin]; - - len++; - goto exit; - } - fvar = 999; - goto exit; - } -#ifdef ESP32 - if (!strncmp(vname, "pheap", 5)) { - fvar = ESP.getFreePsram(); - goto exit; - } -#endif - if (!strncmp(vname, "prefix1", 7)) { - if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX1), glob_script_mem.max_ssize); - goto strexit; - } - if (!strncmp(vname, "prefix2", 7)) { - if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX2), glob_script_mem.max_ssize); - goto strexit; - } - if (!strncmp(vname, "prefix3", 7)) { - if (sp) strlcpy(sp, SettingsText(SET_MQTTPREFIX3), glob_script_mem.max_ssize); - goto strexit; - } - if (!strncmp(vname, "pow(", 4)) { - - float fvar1; - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - lp++; - fvar = FastPrecisePowf(fvar1, fvar2); - len = 0; - goto exit; - } - if (!strncmp(vname, "pwr[", 4)) { - GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); - uint8_t index = fvar; - if (index<=devices_present) { - fvar = bitRead(power, index - 1); - } else { - fvar = -1; - } - len += 1; - goto exit; - } - if (!strncmp(vname, "pc[", 3)) { - GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); - uint8_t index = fvar; - if (index<1 || index>MAX_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) + (PMEM_SIZE); - goto exit; - } - if (!strncmp(vname, "rnd(", 4)) { - - GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); - if (fvar<0) { - randomSeed(-fvar); - fvar = 0; - } else { - fvar = random(fvar); - } - - len++; - goto exit; - } - break; - case 's': - if (!strncmp(vname, "secs", 4)) { - fvar = RtcTime.second; - goto exit; - } - if (!strncmp(vname, "sw[", 3)) { - - GetNumericArgument(vname + 3, OPER_EQU, &fvar, 0); - fvar = SwitchLastState((uint32_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)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - lp++; - len = 0; - fvar = strlen(str); - goto exit; - } - if (!strncmp(vname, "sb(", 3)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - SCRIPT_SKIP_SPACES - float fvar1; - lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - float fvar2; - lp = GetNumericArgument(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)) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); - while (*lp==' ') lp++; - char token[2]; - token[0] = *lp++; - token[1] = 0; - while (*lp==' ') lp++; - lp = GetNumericArgument(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 = GetNumericArgument(lp + 2, OPER_EQU, &fvar, 0); - char str[glob_script_mem.max_ssize + 1]; - f2char(fvar, glob_script_mem.script_dprec, glob_script_mem.script_lzero, str); - if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); - lp++; - len = 0; - goto strexit; - } -#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) - if (!strncmp(vname, "say(", 4)) { - char text[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp + 4, OPER_EQU, text, 0); - Say(text); - len++; - len = 0; - goto exit; - } -#endif - -#ifdef ESP32 - if (!strncmp(vname, "sf(", 3)) { - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0); - if (fvar<80) fvar = 80; - if (fvar>240) fvar = 240; - setCpuFrequencyMhz(fvar); - fvar = getCpuFrequencyMhz(); - lp++; - len = 0; - goto exit; - } -#endif -#ifdef USE_TTGO_WATCH - if (!strncmp(vname, "slp(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - SCRIPT_SKIP_SPACES - TTGO_Sleep(fvar); - lp++; - len = 0; - goto exit; - } -#endif -#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 - -#ifdef USE_SHUTTER - if (!strncmp(vname, "sht[", 4)) { - GetNumericArgument(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 -#ifdef USE_ANGLE_FUNC - if (!strncmp(vname, "sin(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - fvar = sinf(fvar); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "sqrt(", 5)) { - lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - fvar = sqrtf(fvar); - lp++; - len = 0; - goto exit; - } -#endif - -#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) - if (!strncmp(vname, "sml[", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - SCRIPT_SKIP_SPACES - fvar = SML_GetVal(fvar); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "sml(", 4)) { - float fvar1; - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - SCRIPT_SKIP_SPACES - if (fvar2==0) { - float fvar3; - lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); - fvar = SML_SetBaud(fvar1, fvar3); - } else if (fvar2==1) { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, str, 0); - fvar = SML_Write(fvar1, str); - } else if (fvar2==2) { - char str[SCRIPT_MAXSSIZE]; - str[0] = 0; - fvar = SML_Read(fvar1, str, SCRIPT_MAXSSIZE); - if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); - lp++; - len = 0; - goto strexit; - - } else { -#ifdef ED300L - fvar = SML_Status(fvar1); -#else - fvar = 0; -#endif - } - lp++; - len = 0; - 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)) { - fvar = rules_flag.time_init; - goto exit; - } - if (!strncmp(vname, "tset", 4)) { - fvar = rules_flag.time_set; - 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, SettingsText(SET_MQTT_TOPIC), glob_script_mem.max_ssize); - goto strexit; - } -#ifdef USE_SCRIPT_TIMER - if (!strncmp(vname, "ts1(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - if (fvar<10) fvar = 10; - Script_ticker1.attach_ms(fvar, Script_ticker1_end); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "ts2(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - if (fvar<10) fvar = 10; - Script_ticker2.attach_ms(fvar, Script_ticker2_end); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "ts3(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - if (fvar<10) fvar = 10; - Script_ticker3.attach_ms(fvar, Script_ticker3_end); - lp++; - len = 0; - goto exit; - } - if (!strncmp(vname, "ts4(", 4)) { - lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); - if (fvar<10) fvar = 10; - Script_ticker4.attach_ms(fvar, Script_ticker4_end); - lp++; - len = 0; - goto exit; - } -#endif - -#ifdef USE_DISPLAY -#ifdef USE_TOUCH_BUTTONS - if (!strncmp(vname, "tbut[", 5)) { - GetNumericArgument(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.on_off; - } 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 defined(ESP32) && defined(USE_WEBCAM) - if (!strncmp(vname, "wc(", 3)) { - float fvar1; - lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar1, 0); - SCRIPT_SKIP_SPACES - switch ((uint32)fvar1) { - case 0: - { float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = WcSetup(fvar2); - } - break; - case 1: - { float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = WcGetFrame(fvar2); - } - break; - case 2: - { float fvar2,fvar3; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp, OPER_EQU, &fvar3, 0); - fvar = WcSetOptions(fvar2, fvar3); - } - break; - case 3: - fvar = WcGetWidth(); - break; - case 4: - fvar = WcGetHeight(); - break; - case 5: - { float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = WcSetStreamserver(fvar2); - } - break; - case 6: - { float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = WcSetMotionDetect(fvar2); - } - break; -#ifdef USE_FACE_DETECT - case 7: - { float fvar2; - lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0); - fvar = WcSetFaceDetect(fvar2); - } - break; -#endif - default: - fvar = 0; - } - lp++; - len = 0; - goto exit; - } -#endif -#if defined(USE_TTGO_WATCH) && defined(USE_BMA423) - if (!strncmp(vname, "wdclk", 5)) { - fvar = TTGO_doubleclick(); - goto exit; - } - if (!strncmp(vname, "wbut", 4)) { - fvar = TTGO_button(); - goto exit; - } -#endif -#if defined(USE_TTGO_WATCH) && defined(USE_FT5206) - if (!strncmp(vname, "wtch(", 5)) { - lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - fvar = Touch_Status(fvar); - lp++; - len = 0; - goto exit; - } -#endif - if (!strncmp(vname, "wm", 2)) { - fvar = glob_script_mem.web_mode; - goto exit; - } - 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; -} - - -#ifdef ESP8266 -extern "C" { -#include - extern cont_t* g_pcont; -} -uint16_t GetStack(void) { - register uint32_t *sp asm("a1"); - return (4 * (sp - g_pcont->stack)); -} -#else -uint16_t GetStack(void) { - register uint8_t *sp asm("a1"); - return (sp - pxTaskGetStackStart(NULL)); -} -#endif - -char *GetStringArgument(char *lp, uint8_t lastop, char *cp, JsonParserObject *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) - strlen(str1)); - 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; - } - } - return lp; -} - -char *GetNumericArgument(char *lp, uint8_t lastop, float *fp, JsonParserObject *jo) { -uint8_t operand = 0; -float fvar1,fvar; -char *slp; -uint8_t vtype; -struct T_INDEX ind; - while (1) { - - if (*lp=='(') { - lp++; - lp = GetNumericArgument(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 = GetStringArgument(lp, OPER_EQU, dstr, 0); - if (glob_script_mem.glob_error) { - - lp = GetNumericArgument(slp, OPER_EQU, &fvar, 0); - dtostrfd(fvar, 6, dstr); - glob_script_mem.glob_error = 0; - } - return lp; -} - - -void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { - char *cp; - uint16_t count; - uint8_t vtype; - uint8_t dprec = glob_script_mem.script_dprec; - uint8_t lzero = glob_script_mem.script_lzero; - float fvar; - cp = srcbuf; - struct T_INDEX ind; - char string[SCRIPT_MAXSSIZE]; - dstsize -= 2; - for (count = 0; count=sizeof(str)) 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, JsonParserObject *jo) { - float fvar,*dfvar,fvar1; - uint8_t numeric; - struct T_INDEX ind; - uint8_t vtype = 0,lastop; - uint8_t res = 0; - char *llp = lp; - char *slp; - - SCRIPT_SKIP_SPACES - if (*lp=='(') { - uint8_t res = 0; - uint8_t xand_or = 0; - lp++; - -loop: - SCRIPT_SKIP_SPACES - lp = Evaluate_expression(lp, xand_or, &res, jo); - if (*lp==')') { - lp++; - goto exit0; - } - - SCRIPT_SKIP_SPACES - if (!strncmp(lp, "or", 2)) { - lp += 2; - xand_or = 1; - goto loop; - } else if (!strncmp(lp, "and", 3)) { - lp += 3; - xand_or = 2; - goto loop; - } -exit0: - if (!and_or) { - *result = res; - } else if (and_or==1) { - *result|=res; - } else { - *result &= res; - } - goto exit10; - } - - llp = lp; - - dfvar = &fvar; - glob_script_mem.glob_error = 0; - slp = lp; - numeric = 1; - lp = GetNumericArgument(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 = GetStringArgument(lp, OPER_EQU, str, jo); - if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { - res = strcmp(cmpstr, str); - if (lastop==OPER_EQUEQU) res=!res; - goto exit; - } - - } else { - - - lp = getop(lp, &lastop); - lp = GetNumericArgument(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; - } - -exit: - if (!and_or) { - *result = res; - } else if (and_or==1) { - *result |= res; - } else { - *result &= res; - } - } - - -exit10: -#if IFTHEN_DEBUG>0 - char tbuff[128]; - sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d,and_or=%d line: ", (int32_t)*dfvar, (int32_t)fvar1, *result, and_or); - toLogEOL(tbuff, llp); -#endif - return lp; -} - -#ifdef ESP32 - -TimerHandle_t beep_th; -void StopBeep( TimerHandle_t xTimer ); - -void StopBeep( TimerHandle_t xTimer ) { - ledcWriteTone(7, 0); - xTimerStop(xTimer, 0); -} - -void esp32_beep(int32_t freq ,uint32_t len) { - if (freq<0) { - ledcSetup(7, 500, 10); - ledcAttachPin(-freq, 7); - ledcWriteTone(7, 0); - if (!beep_th) { - beep_th = xTimerCreate("beep", 100, pdFALSE, ( void * ) 0, StopBeep); - } - } else { - if (!beep_th) return; - if (!freq) { - ledcWriteTone(7, 0); - xTimerStop(beep_th, 10); - return; - } - if (len < 10) return; - if (xTimerIsTimerActive(beep_th)) return; - ledcWriteTone(7, freq); - uint32_t ticks = pdMS_TO_TICKS(len); - xTimerChangePeriod( beep_th, ticks, 10); - } -} -#endif - - - -char *scripter_sub(char *lp, uint8_t fromscriptcmd) { - lp += 1; - char *slp = lp; - uint8_t plen = 0; - while (*lp) { - if (*lp=='\n'|| *lp=='\r'|| *lp=='(') { - break; - } - lp++; - plen++; - } - if (fromscriptcmd) { - char *sp = glob_script_mem.scriptptr; - glob_script_mem.scriptptr = glob_script_mem.scriptptr_bu; - Run_Scripter(slp, plen, 0); - glob_script_mem.scriptptr = sp; - } else { - Run_Scripter(slp, plen, 0); - } - lp = slp; - return lp; -} - -#define IF_NEST 8 - -int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { -int16_t retval; - - if (!glob_script_mem.scriptptr) { - return -99; - } - - if (tasm_cmd_activ && tlen>0) return 0; - - JsonParserObject jo; - if (js) { - - - JsonParser parser(js); - jo = parser.getRootObject(); - retval = Run_script_sub(type, tlen, &jo); - } else { - retval = Run_script_sub(type, tlen, 0); - } - return retval; -} - -int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { - uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0; - char *lp_next; - int16_t globaindex,saindex; - 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; - - 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_next = 0; - 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 = GetNumericArgument(lp, OPER_EQU, cv_count, 0); - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp, OPER_EQU, &cv_max, 0); - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp, OPER_EQU, &cv_inc, 0); - - cv_ptr = lp; - if (*cv_count<=cv_max && cv_inc>0) { - - floop = 1; - } else { - - floop = 2; - if (cv_inc>0) { - floop = 1; - } - } - } else { - - toLogEOL("for error", lp); - } - } else if (!strncmp(lp, "next", 4)) { - lp_next = lp; - if (floop>0) { - - *cv_count += cv_inc; - if (floop==1) { - if (*cv_count<=cv_max) { - lp = cv_ptr; - } else { - lp += 4; - floop = 0; - } - } else { - 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 = GetNumericArgument(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 = GetNumericArgument(lp, OPER_EQU, &cvar, 0); - if (swvar!=cvar) { - swflg = 2; - } else { - swflg = 1; - } - } else { - char str[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(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)) { - lp += 5; - if (floop) { - - if (lp_next) { - lp = lp_next; - } - floop = 0; - } else { - section = 0; - } - goto next_line; - } else if (!strncmp(lp, "dp", 2) && isdigit(*(lp + 2))) { - lp += 2; - - if (*(lp + 1)== '.') { - glob_script_mem.script_lzero = atoi(lp); - lp+=2; - } - glob_script_mem.script_dprec = atoi(lp); - goto next_line; - } -#ifdef USE_DISPLAY - else if (!strncmp(lp, "dt", 2)) { - char dstbuf[256]; - lp += 2; - SCRIPT_SKIP_SPACES - Replace_Cmd_Vars(lp, 1, dstbuf, sizeof(dstbuf)); - char *savptr = XdrvMailbox.data; - XdrvMailbox.data = dstbuf; - XdrvMailbox.data_len = 0; - DisplayText(); - XdrvMailbox.data = savptr; - goto next_line; - } -#endif - else if (!strncmp(lp, "delay(", 6)) { - - lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - delay(fvar); - goto next_line; - } else if (!strncmp(lp, "spinm(", 6)) { - - lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); - int8_t pinnr = fvar; - SCRIPT_SKIP_SPACES - uint8_t mode = 0; - if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { - switch (*lp) { - case 'I': - mode = 0; - break; - case 'O': - mode = 1; - break; - case 'P': - mode = 2; - break; - } - lp++; - } else { - lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); - mode = fvar; - } - uint8_t pm=0; - if (mode==0) pm = INPUT; - if (mode==1) pm = OUTPUT; - if (mode==2) pm = INPUT_PULLUP; - pinMode(pinnr, pm); - goto next_line; - } else if (!strncmp(lp, "spin(", 5)) { - - lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - int8_t pinnr = fvar; - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(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_SCRIPT_GLOBVARS - else if (!strncmp(lp, "gvr", 3)) { - lp += 3; - - Restart_globvars(); - goto next_line; - } -#endif -#ifdef USE_LIGHT -#ifdef USE_WS2812 - else if (!strncmp(lp, "ws2812(", 7)) { - lp = isvar(lp + 7, &vtype, &ind, 0, 0, 0); - if (vtype!=VAR_NV) { - SCRIPT_SKIP_SPACES - if (*lp!=')') { - lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); - } else { - fvar = 0; - } - - uint8_t index = glob_script_mem.type[ind.index].index; - if ((vtype&STYPE)==0) { - - if (glob_script_mem.type[ind.index].bits.is_filter) { - uint16_t len = 0; - float *fa = Get_MFAddr(index, &len, 0); - - if (fa && len) ws2812_set_array(fa, len, fvar); - } - } - } - goto next_line; - } -#endif -#endif -#ifdef ESP32 - else if (!strncmp(lp, "beep(", 5)) { - lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0); - SCRIPT_SKIP_SPACES - float fvar1; - lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0); - esp32_beep(fvar, fvar1); - lp++; - goto next_line; - } -#endif - else if (!strncmp(lp, "wcs", 3)) { - lp+=4; - - char tmp[256]; - Replace_Cmd_Vars(lp ,1 , tmp, sizeof(tmp)); - WSContentFlush(); - WSContentSend_P(PSTR("%s"),tmp); - WSContentFlush(); - goto next_line; - } - else if (!strncmp(lp,"=>",2) || !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; - if (*lp=='+') sflag = 2; - 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", 1, jo); - glob_script_mem.scriptptr = svd_sp; - } - - - if (if_state[ifstck]==1) { - - lp = Evaluate_expression(lp, and_or, &if_result[ifstck], jo); - SCRIPT_SKIP_SPACES - if (*lp=='{' && if_state[ifstck]==1) { - lp += 1; - if_state[ifstck] = 2; - if (if_exe[ifstck - 1]) if_exe[ifstck] = if_result[ifstck]; - } - goto next_line; - } else { - char *vnp = lp; - lp = isvar(lp, &vtype, &ind, &sysvar, 0, 0); - if (vtype!=VAR_NV) { -#ifdef USE_SCRIPT_GLOBVARS - char varname[16]; - uint32_t vnl = (uint32_t)lp - (uint32)vnp; - strncpy(varname, vnp, vnl); - varname[vnl] = 0; -#endif - - - globvindex = ind.index; - globaindex = last_findex; - uint8_t index = glob_script_mem.type[ind.index].index; - if ((vtype&STYPE)==0) { - - if (ind.bits.settable || ind.bits.is_filter) { - dfvar = &sysvar; - if (ind.bits.settable) { - sysv_type = ind.index; - } else { - sysv_type = 0; - } - - } else { - dfvar = &glob_script_mem.fvars[index]; - sysv_type = 0; - } - numeric = 1; - lp = getop(lp, &lastop); - char *slp = lp; - glob_script_mem.glob_error = 0; - lp = GetNumericArgument(lp, OPER_EQU, &fvar, jo); - if (glob_script_mem.glob_error==1) { - - - lp = isvar(slp, &vtype, &ind, 0, cmpstr, jo); - fvar = CharToFloat(cmpstr); - } - switch (lastop) { - case OPER_EQU: - if (glob_script_mem.var_not_found) { - if (!jo) toLogEOL("var not found: ",lp); - goto next_line; - } - *dfvar = fvar; - break; - case OPER_PLSEQU: - *dfvar += fvar; - break; - case OPER_MINEQU: - *dfvar -= fvar; - break; - case OPER_MULEQU: - *dfvar *= fvar; - break; - case OPER_DIVEQU: - *dfvar /= fvar; - break; - case OPER_PERCEQU: - *dfvar = fmodf(*dfvar, fvar); - break; - case OPER_ANDEQU: - *dfvar = (uint32_t)*dfvar & (uint32_t)fvar; - break; - case OPER_OREQU: - *dfvar = (uint32_t)*dfvar | (uint32_t)fvar; - break; - case OPER_XOREQU: - *dfvar = (uint32_t)*dfvar ^ (uint32_t)fvar; - break; - default: - - break; - } - - glob_script_mem.type[globvindex].bits.changed = 1; -#ifdef USE_SCRIPT_GLOBVARS - if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname, dfvar, 0); - } -#endif - if (glob_script_mem.type[globvindex].bits.is_filter) { - 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) { - 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; - case SCRIPT_EVENT_HANDLED: - event_handeled = *dfvar; - break; - } - sysv_type = 0; - } - } else { - - numeric = 0; - sindex = index; - saindex = last_sindex; - - char str[SCRIPT_MAXSSIZE]; - lp = getop(lp, &lastop); - char *slp = lp; - glob_script_mem.glob_error = 0; - lp = GetStringArgument(lp, OPER_EQU, str, jo); - if (!jo && glob_script_mem.glob_error) { - - lp = GetNumericArgument(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; -#ifdef USE_SCRIPT_GLOBVARS - if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname, 0, str); - } -#endif - if (saindex>=0) { - if (lastop==OPER_EQU) { - strlcpy(glob_script_mem.last_index_string[glob_script_mem.sind_num] + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); - } else if (lastop==OPER_PLSEQU) { - strncat(glob_script_mem.last_index_string[glob_script_mem.sind_num] + (saindex * glob_script_mem.max_ssize), str, glob_script_mem.max_ssize); - } - last_sindex = -1; - } else { - 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; - GetNumericArgument((char*)ctype, OPER_EQU, &fparam, 0); - if (glob_script_mem.glob_error==1) { - - numeric = 0; - - GetStringArgument((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 (Settings.rule_enabled) { - 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; countglob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent = 0; - return; - } - while (len--) { - *fp++ = *fa++; - } - } else { - mlen += sizeof(float); - if (mlen>glob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent = 0; - return; - } - *fp++ = glob_script_mem.fvars[index]; - } - } - } - char *cp = (char*)fp; - for (uint8_t count = 0; countglob_script_mem.script_pram_size) { - vtp[count].bits.is_permanent = 0; - return; - } - strcpy(cp, sp); - cp += slen + 1; - } - } -} - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_SCRIPT "s10" - -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 = - "
" - "
" - "
" - ""; - -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_FILE_UPGc[] PROGMEM = -"
total size: %s kB - free: %s kB
"; - -const char HTTP_FORM_SDC_DIRa[] PROGMEM = -"
"; -const char HTTP_FORM_SDC_DIRb[] PROGMEM = - "
%s     %s : %8d
"; -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 - - -uint8_t *script_ex_ptr; -uint16_t uplsize; -uint8_t sc_state; - - -void script_upload_start(void) { - - - - HTTPUpload& upload = Webserver->upload(); - if (upload.status == UPLOAD_FILE_START) { - - script_ex_ptr = (uint8_t*)glob_script_mem.script_ram; - - - if (strcmp(upload.filename.c_str(), "execute_script")) { - Web.upload_error = 1; - WSSend(500, CT_PLAIN, F("500: wrong filename")); - return; - } - if (upload.totalSize>=glob_script_mem.script_size) { - Web.upload_error = 1; - WSSend(500, CT_PLAIN, F("500: file to large")); - return; - } - uplsize = 0; - - sc_state = bitRead(Settings.rule_enabled, 0); - bitWrite(Settings.rule_enabled, 0, 0); - - } else if(upload.status == UPLOAD_FILE_WRITE) { - - uint32_t csiz = upload.currentSize; - uint32_t tsiz = glob_script_mem.script_size - 1; - if (uplsize0 -#undef REJCMPL -#define REJCMPL 6 -#else -#undef REJCMPL -#define REJCMPL 8 -#endif - -uint8_t reject(char *name) { - - char *lcp = strrchr(name,'/'); - if (lcp) { - name = lcp + 1; - } - - while (*name=='/') name++; - if (*name=='_') return 1; - if (*name=='.') return 1; - - 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; - if (!strncasecmp(name, "System Volume", 13)) return 1; - 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 = fsp->open(path, FILE_READ); - 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, ".."); - } - char *ep; - while (true) { - File entry = dir.openNextFile(); - if (!entry) { - break; - } - - ep = (char*)entry.name(); - if (*ep=='/') ep++; - char *lcp = strrchr(ep,'/'); - if (lcp) { - ep = lcp + 1; - } - - time_t tm = entry.getLastWrite(); - char tstr[24]; - strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm)); - - char *pp = path; - if (!*(pp + 1)) pp++; - char *cp = name; - - if (reject((char*)ep)) goto fclose; - - for (uint8_t cnt = 0; cnt1) { - strcat(path, "/"); - } - strcat(path, ep); - ListDir(path, depth + 4); - path[plen] = 0; - } else { - snprintf_P(npath, sizeof(npath), HTTP_FORM_SDC_HREF, WiFi.localIP().toString().c_str(), pp,ep); - WSContentSend_P(HTTP_FORM_SDC_DIRb, npath, ep, name, tstr, 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, D_SCRIPT_UPLOAD); -#ifdef SDCARD_DIR - char ts[16]; - char fs[16]; - form1000(get_fsinfo(0), ts, '.'); - form1000(get_fsinfo(1), fs, '.'); - WSContentSend_P(HTTP_FORM_FILE_UPGc, ts, fs); - 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; -} - -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(); -} - - -File upload_file; - -void script_upload(void) { - - HTTPUpload& upload = Webserver->upload(); - if (upload.status == UPLOAD_FILE_START) { - char npath[48]; -#if defined(ESP32) && defined(USE_SCRIPT_FATFS) && USE_SCRIPT_FATFS==-1 - - sprintf(npath, "%s/%s", path, upload.filename.c_str()); -#else - sprintf(npath, "%s/%s", path, upload.filename.c_str()); -#endif - fsp->remove(npath); - upload_file = fsp->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 (!fsp->exists(file)) { - AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); - return 0; - } - - download_file = fsp->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); - - -#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 - - - 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 SaveScript(void) { - -#ifdef EEP_SCRIPT_SIZE - 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) { - fsp->remove(FAT_SCRIPT_NAME); - File file = fsp->open(FAT_SCRIPT_NAME, FILE_WRITE); - file.write((const uint8_t*)glob_script_mem.script_ram, FAT_SCRIPT_SIZE); - file.close(); - } -#endif - -#ifdef LITTLEFS_SCRIPT_SIZE - if (glob_script_mem.flags&1) { - SaveFile("/script.txt", (uint8_t*)glob_script_mem.script_ram, LITTLEFS_SCRIPT_SIZE); - } -#endif -} - -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"); - -#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); - - if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { - AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); - bitWrite(Settings.rule_enabled, 0, 0); - } - - SaveScript(); - - } - - SaveScriptEnd(); -} - -void SaveScriptEnd(void) { - -#ifdef USE_SCRIPT_GLOBVARS - Script_Stop_UDP(); -#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; - } - -#ifdef USE_SCRIPT_COMPRESSION - - uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); - if (len_compressed > 0) { - Settings.rules[0][len_compressed] = 0; - AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); - } -#endif - - if (bitRead(Settings.rule_enabled, 0)) { - - - - int16_t res = Init_Scripter(); - if (res) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); - return; - } - - Run_Scripter(">B\n", 3, 0); - Run_Scripter(">BS", 3, 0); - - fast_script = Run_Scripter(">F", -2, 0); - } -} - -#endif - - -#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -#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\":\"{m1}\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -# 5264 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -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\"" -"}"; -# 5345 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -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")); - String light_status = ""; - if (hue_script[hue_devs].index[1]>0) { - - 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) { - - uint32_t hue = glob_script_mem.fvars[hue_script[hue_devs].index[2] - 1]; - - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - } - if (hue_script[hue_devs].index[3]>0) { - - 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) { - - uint32_t ct = glob_script_mem.fvars[hue_script[hue_devs].index[4] - 1]; - light_status += "\"ct\":"; - light_status += String(ct); - light_status += ","; - } - - float temp; - switch (hue_script[hue_devs].type) { - case 'C': - response->replace("{type}","Color Ligh"); - response->replace("{m1","LST001"); - break; - case 'D': - response->replace("{type}","Dimmable Light"); - response->replace("{m1","LWB004"); - break; - case 'T': - response->replace("{type}","Color Temperature Light"); - response->replace("{m1","LTW011"); - break; - case 'E': - response->replace("{type}","Extended color light"); - response->replace("{m1","LCT007"); - break; - case 'S': - response->replace("{type}","On/Off light"); - response->replace("{m1","LCT007"); - break; - default: - response->replace("{type}","color light"); - response->replace("{m1","LST001"); - break; - } - - response->replace("{light_status}", light_status); - response->replace("{j1", hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs)); - -} - -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 tmp[256]; - 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!=';') { - - Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); - - - cp = tmp; - cp = strchr(cp,','); - if (!cp) break; - *cp = 0; - - strlcpy(hue_script[hue_devs].name, tmp, HUE_DEV_NSIZE); - cp++; - while (*cp==' ') cp++; - - hue_script[hue_devs].type = *cp; - - for (vindex = 0; vindex0) *response += ",\""; - else *response += "\""; - } - *response += String(EncodeLightId(hue_devs + devices_present + 1))+"\":"; - Script_HueStatus(response, hue_devs); - - } - - hue_devs++; - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } -#if 0 - 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\"}}]"; - - - -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 = "["; - - JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); - JsonParserObject root = parser.getRootObject(); - JsonParserToken hue_on = root[PSTR("on")]; - if (hue_on) { - - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - - bool on = hue_on.getBool(); - if (on==false) { - glob_script_mem.fvars[hue_script[index].index[0] - 1] = 0; - response.replace("{re", "false"); - } else { - glob_script_mem.fvars[hue_script[index].index[0] - 1] = 1; - response.replace("{re", "true"); - } - glob_script_mem.type[hue_script[index].vindex[0]].bits.changed = 1; - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_bri = root[PSTR("bri")]; - if (hue_bri) { - tmp = hue_bri.getUInt(); - 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; - } - - JsonParserToken hue_xy = root[PSTR("xy")]; - if (hue_xy) { - float x, y; - JsonParserArray arr_xy = JsonParserArray(hue_xy); - JsonParserToken tok_x = arr_xy[0]; - JsonParserToken tok_y = arr_xy[1]; - x = tok_x.getFloat(); - y = tok_y.getFloat(); - String x_str = tok_x.getStr(); - String y_str = tok_y.getStr(); - 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; - } - - JsonParserToken hue_hue = root[PSTR("hue")]; - if (hue_hue) { - tmp = hue_hue.getUInt(); - - - 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; - } - - JsonParserToken hue_sat = root[PSTR("sat")]; - if (hue_sat) { - tmp = hue_sat.getUInt(); - 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; - } - - JsonParserToken hue_ct = root[PSTR("ct")]; - if (hue_ct) { - ct = hue_ct.getUInt(); - 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 - - -#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++ = '#'; - 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 { - if (pl>=0) { - Response_P(S_JSON_COMMAND_NVALUE, command, pl); - } else { - Response_P(S_JSON_COMMAND_SVALUE, command, pld); - } - } - 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; - - if (tasm_cmd_activ) return false; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); - if (-1 == command_code) { - serviced = false; - } - else if ((CMND_SCRIPT == command_code) && (index > 0)) { - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - 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]) { - - 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 - -#ifndef MQTT_EVENT_MSIZE -#define MQTT_EVENT_MSIZE 256 -#endif -#ifndef MQTT_EVENT_JSIZE -#define MQTT_EVENT_JSIZE 400 -#endif -# 5867 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" -bool ScriptMqttData(void) -{ - bool serviced = false; - - - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > MQTT_EVENT_MSIZE) { - 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 { - JsonParser parser((char*)sData.c_str()); - JsonParserObject jsonData = parser.getRootObject(); - String key1 = event_item.Key; - String key2; - if (!jsonData) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - lkey = key2; - JsonParserToken val = jsonData[key1.c_str()].getObject()[key2.c_str()]; - if (!val) break; - value = val.getStr(); - } else { - JsonParserToken val = jsonData[key1.c_str()]; - if (!val) break; - value = val.getStr(); - 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; -} -# 5944 "/workspace/Tasmota/tasmota/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; -} -# 6024 "/workspace/Tasmota/tasmota/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 - -#ifdef SCRIPT_FULL_WEBPAGE -const char HTTP_WEB_FULL_DISPLAY[] PROGMEM = - "

"; - -const char HTTP_SCRIPT_FULLPAGE1[] PROGMEM = - "" - "" - "" - "" - "%s - %s" - ""; - - -#ifdef USE_SCRIPT_FATFS - -const char HTTP_SCRIPT_MIMES[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "Content-disposition: inline; filename=%s" - "Content-type: %s\r\n\r\n"; - -void ScriptGetSDCard(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - String stmp = Webserver->uri(); - char *cp = strstr_P(stmp.c_str(), PSTR("/sdc/")); - - if (cp) { -#ifdef ESP32 - cp += 4; -#else - cp += 5; -#endif - if (strstr_P(cp, PSTR("scrdmp.bmp"))) { - SendFile(cp); - return; - } else { - if (fsp->exists(cp)) { - SendFile(cp); - return; - } - } - } - HandleNotFound(); -} - -extern uint8_t *buffer; - -void SendFile(char *fname) { -char buff[512]; - const char *mime; - uint8_t sflg = 0; - char *jpg = strstr(fname,".jpg"); - if (jpg) { - mime = "image/jpeg"; - } - -#ifdef USE_DISPLAY_DUMP - char *sbmp = strstr_P(fname, PSTR("scrdmp.bmp")); - if (sbmp) { - mime = "image/bmp"; - sflg = 1; - } -#endif - - char *bmp = strstr(fname, ".bmp"); - if (bmp) { - mime = "image/bmp"; - } - char *html = strstr(fname, ".html"); - if (html) { - mime = "text/html"; - } - char *txt = strstr(fname, ".txt"); - if (txt) { - mime = "text/plain"; - } - - WSContentSend_P(HTTP_SCRIPT_MIMES, fname, mime); - - if (sflg) { -#ifdef USE_DISPLAY_DUMP - - #define fileHeaderSize 14 - #define infoHeaderSize 40 - if (buffer) { - uint8_t *bp = buffer; - uint8_t *lbuf = (uint8_t*)calloc(Settings.display_width + 2, 3); - uint8_t *lbp; - uint8_t fileHeader[fileHeaderSize]; - createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader); - Webserver->client().write((uint8_t *)fileHeader, fileHeaderSize); - uint8_t infoHeader[infoHeaderSize]; - createBitmapInfoHeader(Settings.display_height, Settings.display_width, infoHeader ); - Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - for (uint32_t lins = 0; lins>1; - } - bp++; - } - Webserver->client().write((const char*)lbuf, Settings.display_width * 3); - } - if (lbuf) free(lbuf); - Webserver->client().stop(); - } -#endif - } else { - File file = fsp->open(fname,FILE_READ); - uint32_t siz = file.size(); - uint32_t len = sizeof(buff); - while (siz > 0) { - if (len>siz) len = siz; - file.read((uint8_t *)buff, len); - Webserver->client().write((const char*)buff, len); - siz -= len; - } - file.close(); - } - Webserver->client().stop(); -} -#endif - -void ScriptFullWebpage(void) { - uint32_t fullpage_refresh=10000; - if (!HttpCheckPriviledgedAccess()) { return; } - - String stmp = Webserver->uri(); - - if (Webserver->hasArg("m")) { - if (Webserver->hasArg("sv")) { - Script_Check_HTML_Setvars(); - } - WSContentBegin(200, CT_HTML); - ScriptWebShow('w'); - WSContentEnd(); - Serial.printf("fwp update sv %s\n",stmp.c_str() ); - return; - - - - - return; - } else { - Serial.printf("fwp other %s\n",stmp.c_str() ); - } - - WSContentBegin(200, CT_HTML); - const char *title = "Full Screen"; - WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, SettingsText(SET_DEVICENAME), title, fullpage_refresh); - WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh); - - - - - - WSContentSend_P(PSTR("
")); - ScriptWebShow('w'); - WSContentSend_P(PSTR("
")); - - ScriptWebShow('x'); - - WSContentStop(); -} -#endif - -void Script_Check_HTML_Setvars(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg("sv")) { - String stmp = Webserver->arg("sv"); - Serial.printf("fwp has arg dv %s\n", stmp.c_str()); - 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 = - ""; - -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 = - "
"; - - -#ifdef USE_GOOGLE_CHARTS -const char SCRIPT_MSG_GTABLE[] PROGMEM = - "" - "" - "" - ""; - -const char SCRIPT_MSG_TABLE[] PROGMEM = - ""; -const char SCRIPT_MSG_GAUGE[] PROGMEM = - ""; -const char SCRIPT_MSG_TIMELINE[] PROGMEM = - ""; - - -const char SCRIPT_MSG_GTABLEa[] PROGMEM = - ""; - -const char SCRIPT_MSG_GOPT1[] PROGMEM = -"title:'%s',isStacked:false"; - -const char SCRIPT_MSG_GAUGEOPT[] PROGMEM = -"max:%d,redFrom:%d,redTo:%d,yellowFrom:%d,yellowTo:%d"; - -const char SCRIPT_MSG_GOPT2[] PROGMEM = -"showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; - -const char SCRIPT_MSG_GOPT3[] PROGMEM = -"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; - -const char SCRIPT_MSG_GOPT4[] PROGMEM = - -"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'},theme: 'maximized'"; - -const char SCRIPT_MSG_GOPT5[] PROGMEM = -"new Date(0,1,1,%d,%d)"; - -const char SCRIPT_MSG_GOPT6[] PROGMEM = -"title:'%s',isStacked:false,vAxis:{viewWindow:{min:%d,max:%d}}%s"; - -const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; - -#define GLIBS_MAIN 1<<0 -#define GLIBS_TABLE 1<<1 -#define GLIBS_GAUGE 1<<2 -#define GLIBS_TIMELINE 1<<3 - -#define MAX_GARRAY 4 - - -char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint16_t *rentries, uint16_t *ipos) { -struct T_INDEX ind; -uint8_t vtype; -uint16 entries = 0; -uint16_t cipos = 0; - - uint8_t anum = 0; - while (anum=entries) { - if (!entries) { - entries = len; - } - - arrays[anum] = fa; - anum++; - } - } else { - - arrays[anum] = &glob_script_mem.fvars[index]; - anum++; - entries = 1; - } - } else { - lp = lp1; - break; - } - } - } - - *ranum = anum; - *rentries = entries; - *ipos = cipos; - return lp; -} - -char *gc_send_labels(char *lp,uint32_t anum) { - WSContentSend_PD("["); - for (uint32_t cnt = 0; cnt < anum + 1; cnt++) { - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - SCRIPT_SKIP_SPACES - WSContentSend_PD(SCRIPT_MSG_GTE1, label); - - if (cntw", -2, 0); - } else { - web_script = Run_Scripter(">W", -2, 0); - } - - if (web_script==99) { - char tmp[256]; - uint8_t optflg = 0; - uint8_t chartindex = 1; - uint8_t google_libs = 0; - char *lp = glob_script_mem.section_ptr + 2; - if (mc=='w') { - while (*lp) { - if (*lp=='\n') break; - lp++; - } - } - char *cv_ptr; - float cv_max=0; - float cv_inc=0; - float *cv_count=0; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - SCRIPT_SKIP_SPACES - if (!strncmp(lp, "%for ", 5)) { - - struct T_INDEX ind; - uint8_t vtype; - lp = isvar(lp + 5, &vtype, &ind, 0, 0, 0); - if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { - uint16_t index = glob_script_mem.type[ind.index].index; - cv_count = &glob_script_mem.fvars[index]; - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp , OPER_EQU, cv_count, 0); - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp , OPER_EQU, &cv_max, 0); - SCRIPT_SKIP_SPACES - lp = GetNumericArgument(lp , OPER_EQU, &cv_inc, 0); - cv_ptr = lp; - goto nextwebline; - } else { - continue; - } - } else if (!strncmp(lp, "%next", 5)) { - if (cv_count) { - - *cv_count += cv_inc; - if (*cv_count<=cv_max) { - lp = cv_ptr; - } else { - cv_count = 0; - goto nextwebline; - } - } else { - goto nextwebline; - } - } else if (!strncmp(lp, "%=#", 3)) { - - lp = scripter_sub(lp + 1, 0); - goto nextwebline; - } - - Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); - char *lin = tmp; - if ((!mc && (*lin!='$')) || (mc=='w' && (*lin!='$'))) { -# 6589 "/workspace/Tasmota/tasmota/xdrv_10_scripter.ino" - if (*lin=='@') { - lin++; - optflg = 1; - } else { - optflg = 0; - } - - if (!strncmp(lin, "sl(", 3)) { - - char *lp = lin; - float min; - lp = GetNumericArgument(lp + 3, OPER_EQU, &min, 0); - SCRIPT_SKIP_SPACES - - float max; - lp = GetNumericArgument(lp, OPER_EQU, &max, 0); - SCRIPT_SKIP_SPACES - float val; - char *slp = lp; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - char left[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, left, 0); - SCRIPT_SKIP_SPACES - char mid[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, mid, 0); - SCRIPT_SKIP_SPACES - char right[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, right, 0); - SCRIPT_SKIP_SPACES - - WSContentSend_PD(SCRIPT_MSG_SLIDER, left,mid, right, (uint32_t)min, (uint32_t)max, (uint32_t)val, vname); - - } else if (!strncmp(lin, "ck(", 3)) { - char *lp = lin + 3; - char *slp = lp; - float val; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - const char *cp; - uint8_t uval; - if (val>0) { - 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; cnt < bcnt; cnt++) { - float val; - char *slp = lp; - lp = GetNumericArgument(lp, OPER_EQU, &val, 0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname, slp, sizeof(vname)); - - SCRIPT_SKIP_SPACES - char ontxt[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, ontxt, 0); - SCRIPT_SKIP_SPACES - char offtxt[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, offtxt, 0); - - char *cp; - uint8_t uval; - if (val>0) { - 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
"), lin); - } else { - WSContentSend_PD(PSTR("{s}%s{e}"), lin); - } - } - } - - } else { - - if (*lin==mc) { - -#ifdef USE_GOOGLE_CHARTS - lin++; -exgc: - char *lp; - if (!strncmp(lin, "gc(", 3)) { - - lp = lin + 3; - SCRIPT_SKIP_SPACES - const char *type; - const char *func; - char options[312]; - uint8_t nanum = MAX_GARRAY; - uint8_t y2f = 0; - uint8_t tonly = 0; - char ctype; - ctype = *lp; - lp++; - if (!(google_libs & GLIBS_MAIN)) { - google_libs |= GLIBS_MAIN; - WSContentSend_PD(SCRIPT_MSG_GTABLE); - } - switch (ctype) { - case 'l': - type = PSTR("LineChart"); - break; - case 'b': - type = PSTR("BarChart"); - break; - case 'p': - type = PSTR("PieChart"); - break; - case 'g': - type = PSTR("Gauge"); - if (!(google_libs & GLIBS_GAUGE)) { - google_libs |= GLIBS_GAUGE; - WSContentSend_PD(SCRIPT_MSG_GAUGE); - } - break; - case 't': - type = PSTR("Table"); - if (!(google_libs & GLIBS_TABLE)) { - google_libs |= GLIBS_TABLE; - WSContentSend_PD(SCRIPT_MSG_TABLE); - } - break; - case 'T': - type = PSTR("Timeline"); - if (!(google_libs & GLIBS_TIMELINE)) { - google_libs |= GLIBS_TIMELINE; - WSContentSend_PD(SCRIPT_MSG_TIMELINE); - } - break; - case 'h': - type = PSTR("Histogram"); - break; - case 'c': - type = PSTR("ColumnChart"); - break; - case 'C': - type = PSTR("ComboChart"); - break; - case 'e': - WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); - chartindex++; - goto nextwebline; - break; - default: - - goto nextwebline; - break; - } - if (ctype=='l' && *lp=='f') { - lp++; - func = PSTR(",curveType:'function'"); - } else { - func = ""; - } - if (*lp=='2') { - lp++; - nanum = 2; - y2f = 1; - } - if (*lp=='t') { - lp++; - tonly = 1; - } - SCRIPT_SKIP_SPACES - - - - float *arrays[MAX_GARRAY]; - uint8_t anum = 0; - uint16_t entries = 0; - uint16_t ipos = 0; - lp = gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); - - if (anum>nanum) { - goto nextwebline; - } - - - - if (ctype=='T') { - if (anum && !(entries & 1)) { - WSContentSend_PD(SCRIPT_MSG_GTABLEa); - WSContentSend_PD(SCRIPT_MSG_GTABLEd); - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - SCRIPT_SKIP_SPACES - for (uint32_t ind = 0; ind < anum; ind++) { - char lbl[16]; - GetTextIndexed(lbl, sizeof(lbl), ind, label); - for (uint32_t cnt = 0; cnt < entries; cnt += 2) { - WSContentSend_PD("['%s',",lbl); - float *fp = arrays[ind]; - uint32_t time = fp[cnt]; - WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); - WSContentSend_PD(","); - time = fp[cnt + 1]; - WSContentSend_PD(SCRIPT_MSG_GOPT5, time / 60, time % 60); - WSContentSend_PD("]"); - if (cnt < entries - 2) { WSContentSend_PD(","); } - } - if (ind < anum - 1) { WSContentSend_PD(","); } - } - snprintf_P(options,sizeof(options), SCRIPT_MSG_GOPT4); - } - } else { - - WSContentSend_PD(SCRIPT_MSG_GTABLEa); - lp = gc_send_labels(lp, anum); - - - - char label[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, label, 0); - SCRIPT_SKIP_SPACES - - int16_t divflg = 1; - int16_t todflg = -1; - if (!strncmp(label, "cnt", 3)) { - char *cp = &label[3]; - - todflg = strtol(cp, &cp, 10); - if (todflg>=entries) todflg = entries - 1; - if (*cp=='/') { - cp++; - divflg = strtol(cp, &cp, 10); - } - } else { - char *lp = label; - if (!strncmp(label, "wdh:", 4)) { - - todflg = -2; - lp += 4; - } - uint16 segments = 1; - for (uint32_t cnt = 0; cnt < strlen(lp); cnt++) { - if (lp[cnt]=='|') { - segments++; - } - } - divflg = entries / segments; - } - - uint32_t aind = ipos; - if (aind>=entries) aind = entries - 1; - for (uint32_t cnt = 0; cnt < entries; cnt++) { - WSContentSend_PD("['"); - char lbl[16]; - if (todflg>=0) { - sprintf(lbl, "%d", todflg / divflg); - todflg++; - if (todflg >= entries) { - todflg = 0; - } - } else { - if (todflg==-1) { - GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label); - } else { - - GetTextIndexed(lbl, sizeof(lbl), aind / divflg, label + 4); - sprintf(lbl, "%s-%02d", lbl, aind % divflg); - } - } - WSContentSend_PD(lbl); - WSContentSend_PD("',"); - for (uint32_t ind = 0; ind < anum; ind++) { - char acbuff[32]; - float *fp = arrays[ind]; - f2char(fp[aind], glob_script_mem.script_dprec, glob_script_mem.script_lzero, acbuff); - WSContentSend_PD("%s", acbuff); - if (ind=entries) { - aind = 0; - } - } - - if (tonly) { - WSContentSend_PD("]);"); - goto nextwebline; - } - - char header[SCRIPT_MAXSSIZE]; - lp = GetStringArgument(lp, OPER_EQU, header, 0); - SCRIPT_SKIP_SPACES - - switch (ctype) { - case 't': - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT2); - break; - default: - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT1, header); - break; - } - - if (y2f) { - - SCRIPT_SKIP_SPACES - float max1; - lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); - SCRIPT_SKIP_SPACES - float max2; - lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); - SCRIPT_SKIP_SPACES - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT3, header, (uint32_t)max1, (uint32_t)max2, func); - } else { - SCRIPT_SKIP_SPACES - if (ctype!='g') { - if (*lp!=')') { - float max1; - lp = GetNumericArgument(lp, OPER_EQU, &max1, 0); - SCRIPT_SKIP_SPACES - float max2; - lp = GetNumericArgument(lp, OPER_EQU, &max2, 0); - SCRIPT_SKIP_SPACES - snprintf_P(options, sizeof(options), SCRIPT_MSG_GOPT6, header, (uint32_t)max1, (uint32_t)max2, func); - } - } - } - - if (ctype=='g') { - float yellowFrom; - lp = GetNumericArgument(lp, OPER_EQU, &yellowFrom, 0); - SCRIPT_SKIP_SPACES - float redFrom; - lp = GetNumericArgument(lp, OPER_EQU, &redFrom, 0); - SCRIPT_SKIP_SPACES - float maxValue; - lp = GetNumericArgument(lp, OPER_EQU, &maxValue, 0); - SCRIPT_SKIP_SPACES - float redTo = maxValue; - float yellowTo = redFrom; - snprintf_P(options, sizeof(options), SCRIPT_MSG_GAUGEOPT, (uint32_t)maxValue, (uint32_t)redFrom, (uint32_t)redTo, - (uint32_t)yellowFrom, (uint32_t)yellowTo); - } - } - WSContentSend_PD(SCRIPT_MSG_GTABLEb, options); - WSContentSend_PD(SCRIPT_MSG_GTABLEbx, type, chartindex); - chartindex++; - } else { - WSContentSend_PD(PSTR("%s"), lin); - } -#else - lin++; - WSContentSend_PD(PSTR("%s"), lin); - } else { - -#endif - } - } - } -nextwebline: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } -} -#endif - - -#ifdef USE_SENDMAIL - -void script_send_email_body(void(*func)(char *)) { -uint8_t msect = Run_Scripter(">m", -2, 0); - if (msect==99) { - char tmp[256]; - char *lp = glob_script_mem.section_ptr + 2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); - - func(tmp); - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } else { - - func((char*)"*"); - } -} -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT -void ScriptJsonAppend(void) { - uint8_t web_script = Run_Scripter(">J", -2, 0); - if (web_script==99) { - char tmp[256]; - char *lp = glob_script_mem.section_ptr + 2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp)); - ResponseAppend_P(PSTR("%s"), tmp); - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } -} -#endif - - -bool RulesProcessEvent(char *json_event) { - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E", 2, json_event); - return true; -} - -#ifdef ESP32 -#ifdef USE_SCRIPT_TASK - -#ifndef STASK_STACK -#define STASK_STACK 8192 -#endif - -#if 1 - -struct ESP32_Task { - uint16_t task_timer; - TaskHandle_t task_t; -} esp32_tasks[2]; - - -void script_task1(void *arg) { - - - while (1) { - - - - - - delay(esp32_tasks[0].task_timer); - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">t1", 3, 0); - } - } -} - -void script_task2(void *arg) { - - - while (1) { - - - - - - delay(esp32_tasks[1].task_timer); - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">t2", 3, 0); - } - } -} -uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) { - - BaseType_t res = 0; - if (core > 1) { core = 1; } - if (num == 1) { - if (esp32_tasks[0].task_t) { vTaskDelete(esp32_tasks[0].task_t); } - res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &esp32_tasks[0].task_t, core); - esp32_tasks[0].task_timer = time; - } else { - if (esp32_tasks[1].task_t) { vTaskDelete(esp32_tasks[1].task_t); } - res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &esp32_tasks[1].task_t, core); - esp32_tasks[1].task_timer = time; - } - return res; -} -#else - -uint16_t task_timer1; -uint16_t task_timer2; -TaskHandle_t task_t1; -TaskHandle_t task_t2; - -void script_task1(void *arg) { - while (1) { - delay(task_timer1); - Run_Scripter(">t1", 3, 0); - } -} - -void script_task2(void *arg) { - while (1) { - delay(task_timer2); - Run_Scripter(">t2", 3, 0); - } -} - -uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) { - - BaseType_t res = 0; - if (core > 1) { core = 1; } - if (num == 1) { - if (task_t1) { vTaskDelete(task_t1); } - res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &task_t1, core); - task_timer1 = time; - } else { - if (task_t2) { vTaskDelete(task_t2); } - res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &task_t2, core); - task_timer2 = time; - } - return res; -} -#endif - -#endif -#endif - -#ifdef SCRIPT_GET_HTTPS_JP -#ifdef ESP8266 -#include "WiFiClientSecureLightBearSSL.h" -#else -#include -#endif - - -uint32_t call2https(const char *host, const char *path) { - if (global_state.wifi_down) return 1; - uint32_t status = 0; -#ifdef ESP32 - WiFiClientSecure *httpsClient; - httpsClient = new WiFiClientSecure; -#else - BearSSL::WiFiClientSecure_light *httpsClient; - httpsClient = new BearSSL::WiFiClientSecure_light(1024, 1024); -#endif - - httpsClient->setTimeout(1500); - - uint32_t retry = 0; - while ((!httpsClient->connect(host, 443)) && (retry < 5)) { - delay(100); - retry++; - } - if (retry == 5) { - return 2; - } - String request = String("GET ") + path + - " HTTP/1.1\r\n" + - "Host: " + host + - "\r\n" + "Connection: close\r\n\r\n"; - httpsClient->print(request); - - while (httpsClient->connected()) { - String line = httpsClient->readStringUntil('\n'); - if (line == "\r") { - break; - } - } - String result; - while (httpsClient->available()) { - String line = httpsClient->readStringUntil('\n'); - if (line!="") { - result += line; - } - } - httpsClient->stop(); - delete httpsClient; - Run_Scripter(">jp", 3, (char*)result.c_str()); - return 0; -} -#endif - - -void cpy2lf(char *dst, uint32_t dstlen, char *src) { - for (uint32_t cnt=0; cnt0) glob_script_mem.script_ram[len_decompressed] = 0; - - bitWrite(Settings.rule_once, 6, 1); - -#else - - bitWrite(Settings.rule_once, 6, 0); -#endif - -#ifdef USE_BUTTON_EVENT - for (uint32_t cnt = 0; cnt < MAX_KEYS; cnt++) { - script_button[cnt] = -1; - } -#endif - -#ifdef EEP_SCRIPT_SIZE - if (eeprom_init(EEP_SCRIPT_SIZE)) { - - 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; - - 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 USE_SCRIPT_FATFS>=0 - -#ifdef ESP32 - if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) { - SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); - } -#endif - fsp = &SD; - if (SD.begin(USE_SCRIPT_FATFS)) { -#else - -#ifdef ESP32 - - - fsp = &FFat; - if (FFat.begin(true)) { -#else - - fsp = &LittleFS; - if (fsp->begin()) { -#endif - -#endif - AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!")); - - 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 (fsp->exists(FAT_SCRIPT_NAME)) { - File file = fsp->open(FAT_SCRIPT_NAME, FILE_READ); - file.read((uint8_t*)script, FAT_SCRIPT_SIZE); - file.close(); - } - script[FAT_SCRIPT_SIZE - 1] = 0; - - 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 { - AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount failed!")); - glob_script_mem.script_sd_found = 0; - } -#endif - - -#ifdef LITTLEFS_SCRIPT_SIZE - -#ifdef ESP32 - - fsp = &SPIFFS; - - -#else - - fsp = &LittleFS; -#endif - char *script; - script = (char*)calloc(LITTLEFS_SCRIPT_SIZE + 4, 1); - if (!script) break; - LoadFile("/script.txt", (uint8_t*)script, LITTLEFS_SCRIPT_SIZE); - - glob_script_mem.script_ram = script; - glob_script_mem.script_size = LITTLEFS_SCRIPT_SIZE; - script[LITTLEFS_SCRIPT_SIZE-1] = 0; - - 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 - - - if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { - - memset(glob_script_mem.script_ram, 0 ,glob_script_mem.script_size); - strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D")); - bitWrite(Settings.rule_enabled, 0, 0); - } - - - { uint32_t ptr = (uint32_t)glob_script_mem.script_pram; - ptr &= 0xfffffffc; - ptr += 4; - 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\n", 3, 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: - ScripterEvery100ms(); - break; - case FUNC_EVERY_SECOND: - ScriptEverySecond(); - break; - case FUNC_COMMAND: - result = ScriptCommand(); - break; - case FUNC_SET_POWER: -#ifdef SCRIPT_POWER_SECTION - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P", 2, 0); -#else - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">E", 2, 0); - result = event_handeled; - } -#endif - break; - case FUNC_RULES_PROCESS: - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">E", 2, mqtt_data); - result = event_handeled; - } - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_RULES); - break; -#ifdef USE_SCRIPT_WEB_DISPLAY - case FUNC_WEB_ADD_MAIN_BUTTON: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptWebShow('$'); -#ifdef SCRIPT_FULL_WEBPAGE - uint8_t web_script = Run_Scripter(">w", -2, 0); - if (web_script==99) { - char bname[48]; - cpy2lf(bname, sizeof(bname), glob_script_mem.section_ptr + 3); - WSContentSend_PD(HTTP_WEB_FULL_DISPLAY, bname); - Webserver->on("/sfd", ScriptFullWebpage); -#ifdef USE_SCRIPT_FATFS - Webserver->onNotFound(ScriptGetSDCard); -#endif - } -#endif - } - break; -#endif - case FUNC_WEB_ADD_HANDLER: - Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);}, script_upload_start); - Webserver->on("/exs", HTTP_GET, ScriptExecuteUploadSuccess); - -#ifdef USE_SCRIPT_FATFS - Webserver->on("/u13", HTTP_POST,[]() { Webserver->sendHeader("Location","/u13");Webserver->send(303);}, script_upload); - Webserver->on("/u13", 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(); - } -#ifdef USE_SCRIPT_GLOBVARS - Script_Stop_UDP(); -#endif - 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(0); - } - break; -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT - case FUNC_JSON_APPEND: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptJsonAppend(); - } - break; -#endif - -#ifdef USE_BUTTON_EVENT - case FUNC_BUTTON_PRESSED: - if (bitRead(Settings.rule_enabled, 0)) { - if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { - script_button[XdrvMailbox.index] = XdrvMailbox.payload; - Run_Scripter(">b", 2, 0); - } - } - break; -#endif - -#ifdef USE_SCRIPT_GLOBVARS - case FUNC_LOOP: - Script_PollUdp(); - break; -#endif - - } - return result; -} - - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" -#ifdef USE_KNX -# 51 "/workspace/Tasmota/tasmota/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_SCENE , 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", - D_KNX_TX_SCENE , - 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", - D_KNX_RX_SCENE , - 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" -#define D_CMND_KNXTXSCENE "Tx_Scene" - - -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 "|" D_CMND_KNXTXSCENE ; - -void (* const KnxCommand[])(void) PROGMEM = { - &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb, &CmndKnxTxScene }; - -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 ); -# 477 "/workspace/Tasmota/tasmota/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_SWT1 + 4; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1; i < GPIO_KEY1 + 4; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } - } - for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT1_NP + 4; ++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_KEY1_NP + 4; ++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; } -#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; } - -#if defined(USE_ENERGY_SENSOR) - - 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; - } -#endif - -#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; - device_param[KNX_SCENE-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) { - - sprintf(tempchar,"%d",msg.data[0]); - } else if (chan->type == KNX_SCENE) { - - uint8_t tempvar = knx.data_to_1byte_uint(msg.data); - dtostrfd(tempvar,0,tempchar); - } 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; - } - } - } - else if (chan->type == KNX_SCENE) - { - if (!toggle_inhibit) { - char command[25]; - - snprintf_P(command, sizeof(command), PSTR("event KNX_SCENE=%s"), 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(void) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; -# 714 "/workspace/Tasmota/tasmota/xdrv_11_knx.ino" - 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_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 CmndKnxTxScene(void) -{ - if ( (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled ) { - - uint8_t i = KNX_GA_Search(KNX_SCENE); - if ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - - uint8_t tempvar = TextToInt(XdrvMailbox.data); - dtostrfd(tempvar,0,XdrvMailbox.data); - - knx.write_1byte_uint(KNX_addr, tempvar); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1byte_uint(KNX_addr, tempvar); - knx.write_1byte_uint(KNX_addr, tempvar); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), - device_param_ga[KNX_SCENE-1], XdrvMailbox.data, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - 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.network_down) { knx.loop(); } - break; - case FUNC_EVERY_50_MSECOND: - if (toggle_inhibit) { - toggle_inhibit--; - } - break; - case FUNC_ANY_KEY: - KnxSendButtonPower(); - 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(PSTR("/kn"), HandleKNXConfiguration); - break; -#endif -#endif - case FUNC_COMMAND: - result = DecodeCommand(kKnxCommands, KnxCommand); - break; - case FUNC_PRE_INIT: - KNX_INIT(); - break; - - - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" -#ifdef USE_HOME_ASSISTANT - -#define XDRV_12 12 - - -const char kHAssJsonSensorTypes[] PROGMEM = - D_JSON_TEMPERATURE "|" D_JSON_DEWPOINT "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" - D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" D_JSON_TOTAL_START_TIME "|" - D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY "|" - D_JSON_CO2 "|" D_JSON_ECO2 "|" D_JSON_TVOC "|Red|Green|Blue|CCT|" D_PROXIMITY "|"; - - -const char kHAssJsonSensorUnits[] PROGMEM = - "||||" - "VA|%|A|cm|Hz|%|lux|" - "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³|Cos φ|W| |" - "VAr|kWh|kWh|V|kg|kWh|" - "ppm|ppm|ppb|R|G|B|" D_UNIT_KELVIN "| |"; - -const char kHAssJsonSensorDevCla[] PROGMEM = - "dev_cla\":\"temperature|ic\":\"mdi:weather-rainy|dev_cla\":\"pressure|dev_cla\":\"pressure|" - "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" - "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" - "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|ic\":\"mdi:progress-clock|" - "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power|" - "ic\":\"mdi:molecule-co2|ic\":\"mdi:molecule-co2|ic\":\"mdi:air-filter|" - "ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:temperature-kelvin|ic\":\"mdi:ruler|dev_cla\":\"illuminance|"; - - - -const char HASS_DISCOVER_BASE[] PROGMEM = - "{\"name\":\"%s\"," - "\"stat_t\":\"%s\""; - -const char HASS_DISCOVER_SENSOR[] PROGMEM = - ",\"unit_of_meas\":\"%s\",\"%s\"," - "\"frc_upd\":true," - "\"val_tpl\":\"{{value_json['%s']['%s']"; - -const char HASS_DISCOVER_SENSOR_LWT[] PROGMEM = - ",\"avty_t\":\"%s\"," - "\"pl_avail\":\"" MQTT_LWT_ONLINE "\"," - "\"pl_not_avail\":\"" MQTT_LWT_OFFLINE "\""; - -const char HASS_DISCOVER_RELAY[] PROGMEM = - ",\"cmd_t\":\"%s\"," - "\"val_tpl\":\"{{value_json.%s}}\"," - "\"pl_off\":\"%s\"," - "\"pl_on\":\"%s\""; - -const char HASS_DISCOVER_BIN_SWITCH[] PROGMEM = - ",\"val_tpl\":\"{{value_json.%s}}\"," - "\"frc_upd\":true," - "\"pl_on\":\"%s\"," - "\"pl_off\":\"%s\""; - -const char HASS_DISCOVER_BIN_PIR[] PROGMEM = - ",\"val_tpl\":\"{{value_json.%s}}\"," - "\"frc_upd\":true," - "\"pl_on\":\"%s\"," - "\"off_dly\":1"; - -const char HASS_DISCOVER_BASE_LIGHT[] PROGMEM = - ",\"bri_cmd_t\":\"%s\"," - "\"bri_stat_t\":\"%s\"," - "\"bri_scl\":100," - "\"on_cmd_type\":\"%s\"," - "\"bri_val_tpl\":\"{{value_json.%s}}\""; - -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\"," - "\"whit_val_scl\":100," - "\"whit_val_tpl\":\"{{value_json." D_CMND_WHITE "}}\""; - -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_SHUTTER_BASE[] PROGMEM = - ",\"cmd_t\":\"%s\"," - "\"pl_open\":\"ShutterOpen%d\"," - "\"pl_cls\":\"ShutterClose%d\"," - "\"pl_stop\":\"ShutterStop%d\"," - "\"opt\":false," - "\"ret\":false," - "\"qos\":1"; - -const char HASS_DISCOVER_SHUTTER_POS[] PROGMEM = - ",\"pos_t\":\"%s%d\"," - "\"pos_clsd\":0," - "\"pos_open\":100," - "\"set_pos_t\":\"%s%d\""; - -const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - ",\"json_attr_t\":\"%s\"," - "\"unit_of_meas\":\"%%\"," - "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," - "\"ic\":\"mdi:information-outline\""; - -const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"dev\":{\"ids\":[\"%06X\"]," - "\"name\":\"%s\"," - "\"mdl\":\"%s\"," - "\"sw\":\"%s%s\"," - "\"mf\":\"Tasmota\"}"; - -const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"dev\":{\"ids\":[\"%06X\"]}"; - -const char HASS_TRIGGER_TYPE[] PROGMEM = - "{\"atype\":\"trigger\"," - "\"t\":\"%sT\"," - "\"pl\":\"{\\\"TRIG\\\":\\\"%s\\\"}\"," - "\"type\":\"%s\"," - "\"stype\":\"%s\"," - "\"dev\":{\"ids\":[\"%06X\"]}}"; - -const char kHAssTriggerType[] PROGMEM = - "none|button_short_press|button_long_press|button_double_press"; - -const char kHAssTriggerTypeButtons[] PROGMEM = - "|button_short_press|button_double_press|button_triple_press|button_quadruple_press|button_quintuple_press|button_long_press|"; - -const char kHAssTriggerStringButtons[] PROGMEM = - "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|"; - -const char kHAssRelayType[] PROGMEM = - "|RL|LI|SHT|FAN"; - -const char kHAssError1[] PROGMEM = - "HASS: MQTT discovery failed due to too long topic or device/friendly name. Please shorten topic and/or device/friendly name. Failed to format"; - -const char kHAssError2[] PROGMEM = - "HASS: The configuration of the Relays is wrong, there is a Light that is using an index higher than the number of the validated relay.\n " - "The Relays have priority over the Lights, an incorrect order could lead to an erroneous Light control.\n " - "Please update your configuration to avoid inconsistent results.\n " - "Entities for Relays and Lights will not be available in Home Assistant until the configuration will be updated."; - -const char kHAssError3[] PROGMEM = - "HASS: Unable to create one or more entities from Json data, please check your configuration. Failed to parse"; - -uint8_t hass_init_step = 0; -uint8_t hass_mode = 0; -int hass_tele_period = 0; - - - -const char HASS_DISCOVER_DEVICE[] PROGMEM = - "{\"ip\":\"%s\"," - "\"dn\":\"%s\"," - "\"fn\":[%s]," - "\"hn\":\"%s\"," - "\"mac\":\"%s\"," - "\"md\":\"%s\"," - "\"ty\":%d," - "\"ofln\":\"" MQTT_LWT_OFFLINE "\"," - "\"onln\":\"" MQTT_LWT_ONLINE "\"," - "\"state\":[\"%s\",\"%s\",\"%s\",\"%s\"]," - "\"sw\":\"%s\"," - "\"t\":\"%s\"," - "\"ft\":\"%s\"," - "\"tp\":[\"%s\",\"%s\",\"%s\"]," - "\"rl\":[%s],\"swc\":[%s],\"btn\":[%s]," - "\"so\":{\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," - "\"30\":%d,\"68\":%d,\"73\":%d,\"80\":%d,\"82\":%d}," - "\"lk\":%d,\"lt_st\":%d,\"ver\":1}"; - -typedef struct HASS { - uint16_t Relay[MAX_RELAYS]; - char RelLst[MAX_RELAYS*2]; - bool RelPst; -} HASS; - -void HassDiscoveryRelays(struct HASS &Hass) -{ - Hass = {.Relay={0,0,0,0,0,0,0,0}, .RelLst={'\0'}}; - uint16_t Shutter[8] = {0,0,0,0,0,0,0,0}; - uint8_t lightidx = MAX_RELAYS + 1; - bool iFan = false; - - Hass.RelPst = devices_present > 0; - -#ifdef ESP8266 - if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { iFan = true;} -#endif - - if (Light.subtype > LST_NONE) { - if (!light_controller.isCTRGBLinked()) { - lightidx = devices_present - 2; - } else { - lightidx = devices_present - 1; - } - } - - if (Light.device > 0 && Settings.flag3.pwm_multi_channels) { - lightidx = devices_present - Light.subtype; - } - - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - - if (i < devices_present) { - -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - for (uint32_t k = 0; k < MAX_SHUTTERS; k++) { - if (0 == Settings.shutter_startrelay[k]) { - break; - } else { - if (Settings.shutter_startrelay[k] > 0 && Settings.shutter_startrelay[k] <= MAX_RELAYS) { - Shutter[Settings.shutter_startrelay[k]-1] = Shutter[Settings.shutter_startrelay[k]] = 1; - } - } - } - } -#endif - - if (Shutter[i] != 0) { - Hass.Relay[i] = 3; - } else { - if (i >= lightidx || (iFan && i == 0)) { - Hass.Relay[i] = 2; - } else { - if (!iFan) { - Hass.Relay[i] = 1; - } - } - } - } - snprintf_P(Hass.RelLst, sizeof(Hass.RelLst), PSTR("%s%s%d"), Hass.RelLst, (i > 0 ? "," : ""), Hass.Relay[i]); - } -} - -void NewHAssDiscovery(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[200]; - char stemp3[TOPSZ]; - char stemp4[TOPSZ]; - char unique_id[30]; - char relays[TOPSZ]; - char *state_topic = stemp1; - bool SerialButton = false; - bool TuyaMod = false; - - stemp2[0] = '\0'; - struct HASS Hass; - HassDiscoveryRelays(Hass); - - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; - for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - char fname[TOPSZ]; - snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%s"), stemp2, (i > 0 ? "," : ""), (i < maxfn) ? fname : "null"); - } - - stemp3[0] = '\0'; - - auto discover_switches = ((KeyTopicActive(1) && (strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic))) || !Hass.RelPst); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & discover_switches) ? Settings.switchmode[i] : -1); - } - - stemp4[0] = '\0'; - - for (uint32_t i = 0; i < MAX_KEYS; i++) { - -#ifdef ESP8266 - if (i == 0 && (SONOFF_DUAL == my_module_type )) { SerialButton = true; } - if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } -#endif - - snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%d"), stemp4, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons)); - SerialButton = false; - } - - mqtt_data[0] = '\0'; - - - String mac_address = WiFi.macAddress(); - mac_address.replace(":", ""); - snprintf_P(unique_id, sizeof(unique_id), PSTR("%s"), mac_address.c_str()); - snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id); - - - masterlog_level = 4; - if (!Settings.flag.hass_discovery) { - Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME), - stemp2, my_hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), - my_version, mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, - Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, - Settings.flag3.mqtt_buttons, Settings.flag3.shutter_mode, Settings.flag4.alexa_ct_range, light_controller.isCTRGBLinked(), Light.subtype); - } - MqttPublish(stopic, true); - - if (!Settings.flag.hass_discovery) { - snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), unique_id); - Response_P(PSTR("{\"sn\":")); - MqttShowSensor(); - ResponseAppend_P(PSTR(",\"ver\":1}")); - MqttPublish(stopic, true); - } - masterlog_level = 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("%s (%u/%u):"), kHAssError1, 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 LightControl = light_controller.isCTRGBLinked(); - bool PwmMulti = Settings.flag3.pwm_multi_channels; - bool is_topic_light = false; - bool ind_light = false; - bool ct_light = false; - bool wt_light = false; - bool err_flag = false; - bool TuyaMod = false; - bool PwmMod = false; - bool FanMod = false; - uint8_t ShowTopic; - - uint8_t dimmer = 1; - uint8_t valid_relay = 0; - uint8_t max_lights = 1; - uint8_t TuyaRel = 0; - uint8_t TuyaRelInv = 0; - uint8_t TuyaDim = 0; - uint8_t shutter_mask = 0; - - #ifdef ESP8266 - if (PWM_DIMMER == my_module_type ) { PwmMod = true; } - if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { FanMod = true; } - if (SONOFF_DUAL == my_module_type) { valid_relay = 2; } - if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } - #endif - - - - if (PwmMulti) { max_lights = Light.subtype; } - - if (!LightControl) { - ind_light = true; - if (!PwmMulti) { max_lights = 2;} - } - -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_RELAYS) { - bitSet(shutter_mask, Settings.shutter_startrelay[i] -1); - bitSet(shutter_mask, Settings.shutter_startrelay[i]); - } - } - } -#endif - - for (uint32_t i = 1; i <= MAX_RELAYS; i++) - { - -#ifdef USE_TUYA_MCU - TuyaRel = TuyaGetDpId((TUYA_MCU_FUNC_REL1+ i-1) + active_device - 1); - TuyaRelInv = TuyaGetDpId((TUYA_MCU_FUNC_REL1_INV+ i-1) + active_device - 1); - TuyaDim = TuyaGetDpId((TUYA_MCU_FUNC_DIMMER) + active_device - 1); -#endif - - masterlog_level = ShowTopic = 4; - - bool RelayX = PinUsed(GPIO_REL1, i-1) || (valid_relay >= i) || (TuyaRel > 0 && TuyaMod) || (TuyaRelInv > 0 && TuyaMod); - is_topic_light = Settings.flag.hass_light && RelayX || light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); - 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 (bitRead(shutter_mask, i-1)) { - - } else if ((i < Light.device) && !RelayX) { - err_flag = true; - AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s"), kHAssError2); - } else { - if (Settings.flag.hass_discovery && (RelayX || (Light.device > 0) && (max_lights > 0)) && !err_flag ) - { - char name[TOPSZ]; - char value_template[33]; - char prefix[TOPSZ]; - char *command_topic = stemp1; - char *state_topic = stemp2; - char *availability_topic = stemp3; - - ShowTopic = 0; - - if (i > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i-1); - } else { - snprintf_P(name, sizeof(name), PSTR ("%s"), SettingsText(SET_FRIENDLYNAME1 + 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); - Response_P(HASS_DISCOVER_BASE, name, state_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); - - #ifdef USE_LIGHT - if (i >= Light.device) { - if (!RelayX || PwmMod || (TuyaDim > 0 && TuyaMod)) { - char *brightness_command_topic = stemp1; - strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); - char channel_num[9]; - if (PwmMulti) { - snprintf_P(channel_num, sizeof(channel_num), PSTR("Channel%d"), i); - } else { - if (!LightControl) { - snprintf_P(channel_num, sizeof(channel_num), PSTR("" D_CMND_DIMMER "%d"), dimmer); - dimmer ++; - } else { - snprintf_P(channel_num, sizeof(channel_num), PSTR("" D_CMND_DIMMER "")); - } - } - GetTopic_P(brightness_command_topic, CMND, mqtt_topic, channel_num); - TryResponseAppend_P(HASS_DISCOVER_BASE_LIGHT, brightness_command_topic, state_topic, stemp3, channel_num); - } - if ((ind_light && !PwmMulti) || LightControl) { - - if (Light.subtype >= LST_RGB) { - char *rgb_command_topic = stemp1; - - GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - 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); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); - } - if (LST_RGBW <= Light.subtype) { wt_light = true; } - if (LST_RGBCW == Light.subtype) { ct_light = true; } - } - - if ((!ind_light && ct_light) || (LST_COLDWARM == Light.subtype && - !PwmMulti && LightControl)) { - char *color_temp_command_topic = stemp1; - - GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); - ct_light = false; - } - if ((!ind_light && wt_light) || (LST_RGBW <= Light.subtype && - !PwmMulti && LightControl)) { - char *white_temp_command_topic = stemp1; - - GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); - wt_light = false; - } - ind_light = false; - max_lights--; - } - #endif - TryResponseAppend_P(PSTR("}")); - } - } - masterlog_level = ShowTopic; - MqttPublish(stopic, true); - } -} - -void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t toggle, uint8_t hold, uint8_t single, uint8_t trg_start, uint8_t trg_end) -{ - - - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - char trigger2[8]; - uint8_t ShowTopic; - mqtt_data[0] = '\0'; - - for (uint8_t i = trg_start; i <= trg_end; i++) { - GetTextIndexed(trigger2, sizeof(trigger2), i, kHAssTriggerStringButtons); - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d_%s"), ESP_getChipId(), key ? "SW" : "BTN", device + 1, key ? GetStateText(i) : trigger2); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/device_automation/%s/config"), unique_id); - - masterlog_level = ShowTopic = 4; - - if (Settings.flag.hass_discovery && present) { - char name[TOPSZ]; - char value_template[33]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - char jsoname[8]; - ShowTopic = 0; - - GetPowerDevice(value_template, device + 1, sizeof(value_template), key + Settings.flag.device_index_enable); - snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); - GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - char param[21]; - char subtype[9]; - uint8_t pload = toggle; - if (key) { - if ((i == 2 && toggle != 0) || (i == 3 && hold != 0)) { - if (i == 3) { pload = hold; } - GetTextIndexed(param, sizeof(param), pload, kHAssTriggerType); - snprintf_P(subtype, sizeof(subtype), PSTR("switch_%d"), device + 1); - Response_P(HASS_TRIGGER_TYPE, state_topic, GetStateText(i), param, subtype, ESP_getChipId()); - } else { mqtt_data[0] = '\0'; } - } else { - char trigger1[24]; - GetTextIndexed(trigger1, sizeof(trigger1), i, kHAssTriggerTypeButtons); - snprintf_P(subtype, sizeof(subtype), PSTR("button_%d"), device + 1); - if (i > 1 && single) { - mqtt_data[0] = '\0'; - } else { - Response_P(HASS_TRIGGER_TYPE, state_topic, trigger2, trigger1, subtype, ESP_getChipId()); - } - } - } - masterlog_level = ShowTopic; - MqttPublish(stopic, true); - } -} - -void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint8_t toggle, uint8_t pir) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - uint8_t ShowTopic; - - mqtt_data[0] = '\0'; - masterlog_level = 4; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SW_%d"), ESP_getChipId(), device + 1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); - - masterlog_level = ShowTopic = 4; - - if (Settings.flag.hass_discovery && present ) { - if (!toggle || dual) { - char name[TOPSZ]; - char value_template[33]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - char jsoname[8]; - - ShowTopic = 0; - - GetPowerDevice(value_template, device + 1, sizeof(value_template), 1 + Settings.flag.device_index_enable); - snprintf_P(jsoname, sizeof(jsoname), PSTR("SWITCH%d"), device + 1); - GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - snprintf_P(name, sizeof(name), PSTR("%s Switch%d"), SettingsText(SET_DEVICENAME), device + 1); - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - if (!pir) { - TryResponseAppend_P(HASS_DISCOVER_BIN_SWITCH, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); - } else { - TryResponseAppend_P(HASS_DISCOVER_BIN_PIR, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2)); - } - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); -#ifdef DEEPSLEEP_LWT_HA_DISCOVERY - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); -#else - if (Settings.deepsleep == 0) - { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); - } -#endif - TryResponseAppend_P(PSTR("}")); - } - } - masterlog_level = ShowTopic; - MqttPublish(stopic, true); - -} - -void HAssAnnounceSwitches(void) -{ - for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) - { - uint8_t switch_present = 0; - uint8_t dual = 0; - uint8_t toggle = 1; - uint8_t hold = 0; - uint8_t pir = 0; - - if (PinUsed(GPIO_SWT1, switch_index)) { switch_present = 1; } - - if (KeyTopicActive(1) && strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic)) - { -# 696 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" - uint8_t swmode = Settings.switchmode[switch_index]; - - switch (swmode) { - case FOLLOW: - case FOLLOW_INV: - toggle = 0; - break; - case PUSHBUTTON: - case PUSHBUTTON_INV: - dual = 1; - break; - case PUSHBUTTONHOLD: - case PUSHBUTTONHOLD_INV: - dual = 1; - hold = 2; - break; - case TOGGLEMULTI: - hold = 3; - break; - case FOLLOWMULTI: - case FOLLOWMULTI_INV: - dual = 1; - toggle = 0; - hold = 3; - break; - case PUSHON: - case PUSHON_INV: - toggle = 0; - pir = 1; - } - - } else { switch_present = 0;} - - HAssAnnouncerTriggers(switch_index, switch_present, 1, toggle, hold, 0, 2, 3); - HAssAnnouncerBinSensors(switch_index, switch_present, dual, toggle, pir); - } -} - -void HAssAnnounceButtons(void) -{ - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) - { - uint8_t button_present = 0; - uint8_t single = 0; - -#ifdef ESP8266 - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) - { - button_present = 1; - } else -#endif - { - if (PinUsed(GPIO_KEY1, button_index)) { - button_present = 1; - } - } -# 766 "/workspace/Tasmota/tasmota/xdrv_12_home_assistant.ino" - if (!Settings.flag3.mqtt_buttons) { - button_present = 0; - } else { - if (Settings.flag.button_single) { - single = 1; - } - } - HAssAnnouncerTriggers(button_index, button_present, 0, 0, 0, single, 1, 6); - } -} - -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, bool nested, const char* SubKey) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - char subname[20]; - - mqtt_data[0] = '\0'; - - - NoAlNumToUnderscore(subname, MultiSubName); - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP_getChipId(), sensorname, subname); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - if (Settings.flag.hass_discovery) - { - char name[TOPSZ]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - masterlog_level = 0; - - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); - snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_DEVICENAME), sensorname, MultiSubName); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic); -#ifdef DEEPSLEEP_LWT_HA_DISCOVERY - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); -#else - if (Settings.deepsleep == 0) - { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); - } -#endif - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); - - - char jname[32]; - int sensor_index = GetCommandCode(jname, sizeof(jname), SubKey, kHAssJsonSensorTypes); - if (sensor_index > -1) { - - char param1[20]; - GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); - switch (sensor_index) { - case 0: - case 1: - snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); - break; - case 2: - case 3: - snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); - break; - } - char param2[50]; - GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); - TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); - - } else { - TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); - } - - if (nested) { TryResponseAppend_P(PSTR("['%s']"), SubKey); } - - if (subqty != 0) { TryResponseAppend_P(PSTR("[%d]"), subqty -1); } - - 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; - size_t sensordata_len = strlen(mqtt_data); - char sensordata[sensordata_len+2]; - strcpy(sensordata, mqtt_data); - - - - - - - - if (sensordata_len > 0) - { - - sensordata[0] = '{'; - - sensordata[sensordata_len] = '}'; - sensordata[sensordata_len+1] = '\0'; - - JsonParser parser(sensordata); - JsonParserObject root = parser.getRootObject(); - if (!root) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s '%s' (ERR1)"), kHAssError3, sensordata); - continue; - } - for (auto sensor_key : root) - { - - const char *sensorname = sensor_key.getStr(); - JsonParserObject sensors = sensor_key.getValue().getObject(); - - if (!sensors) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s '%s' (ERR2)"), kHAssError3, sensorname); - continue; - } - - for (auto subsensor_key_token : sensors) - { - const char * subsensor_key = subsensor_key_token.getStr(); - JsonParserToken subsensor = subsensor_key_token.getValue(); - if (subsensor.isObject()) { - - JsonParserObject subsensors = subsensor.getObject(); - char NewSensorName[20]; - for (auto subsensor2_key : subsensors) { - snprintf_P(NewSensorName, sizeof(NewSensorName), PSTR("%s %s"), subsensor_key, subsensor2_key.getStr()); - HAssAnnounceSensor(sensorname, subsensor_key, NewSensorName, 0, 1, subsensor2_key.getStr()); - } - } else if (subsensor.isArray()) { - - JsonParserArray subsensors = subsensor.getArray(); - uint8_t subqty = subsensors.size(); - char MultiSubName[20]; - for (int i = 1; i <= subqty; i++) { - snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor_key, i); - HAssAnnounceSensor(sensorname, subsensor_key, MultiSubName, i, 0, subsensor_key); - } - } else { - HAssAnnounceSensor(sensorname, subsensor_key, subsensor_key, 0, 0, subsensor_key);} - } - } - } - yield(); - } while (hass_xsns_index != 0); -} - -void HAssAnnounceShutters(void) -{ -#ifdef USE_SHUTTER - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - uint8_t ShowTopic; - - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - mqtt_data[0] = '\0'; - masterlog_level = ShowTopic = 4; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SHT_%d"), ESP_getChipId(), i + 1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/cover/%s/config"), unique_id); - - if (Settings.flag.hass_discovery && Settings.flag3.shutter_mode && Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_RELAYS) { - ShowTopic = 0; - if (i > MAX_FRIENDLYNAMES) { - snprintf_P(stemp1, sizeof(stemp1), PSTR("%s Shutter %d"), SettingsText(SET_DEVICENAME), i + 1); - } else { - snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), SettingsText(SET_FRIENDLYNAME1 + i)); - } - GetTopic_P(stemp2, TELE, mqtt_topic, D_RSLT_STATE); - Response_P(HASS_DISCOVER_BASE, stemp1, stemp2); - - GetTopic_P(stemp1, TELE, mqtt_topic, S_LWT); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, stemp1); - - GetTopic_P(stemp1, CMND, mqtt_topic, PSTR("Backlog")); - TryResponseAppend_P(HASS_DISCOVER_SHUTTER_BASE, stemp1, i + 1, i + 1, i + 1); - - GetTopic_P(stemp1, STAT, mqtt_topic, PSTR("SHUTTER")); - GetTopic_P(stemp2, CMND, mqtt_topic, PSTR("ShutterPosition")); - TryResponseAppend_P(HASS_DISCOVER_SHUTTER_POS, stemp1, i + 1, stemp2, i + 1); - - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); - TryResponseAppend_P(PSTR("}")); - } - - masterlog_level = ShowTopic; - MqttPublish(stopic, true); - } -#endif -} - -void HAssAnnounceDeviceInfoAndStatusSensor(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - uint8_t ShowTopic; - - - mqtt_data[0] = '\0'; - masterlog_level = ShowTopic = 4; - - 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[TOPSZ]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - ShowTopic = 0; - snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_DEVICENAME)); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME), - ModuleName().c_str(), my_version, my_image); - TryResponseAppend_P(PSTR("}")); - } - masterlog_level = ShowTopic; - MqttPublish(stopic, true); - - if (!Settings.flag.hass_discovery) { - masterlog_level = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG "Home Assistant MQTT Discovery disabled.")); - } -} - -void HAssPublishStatus(void) -{ - Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_CMND_MODULE " or " D_CMND_TEMPLATE"\":\"%s\"," - "\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\"," - "\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\"," - "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"), - my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(), - GetUptime().c_str(), my_hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), - WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), 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 (Settings.flag.hass_discovery || (1 == hass_mode)) - { - hass_mode = 2; - - HAssAnnounceButtons(); - - - HAssAnnounceSwitches(); - - - HAssAnnounceSensors(); - - - HAssAnnounceShutters(); - - - HAssAnnounceRelayLight(); - - - HAssAnnounceDeviceInfoAndStatusSensor(); - masterlog_level = 0; - hass_mode = 3; - } -} - -void HAssDiscover(void) -{ - hass_mode = 1; - hass_init_step = 1; -} - -void HAssAnyKey(void) -{ - if (!Settings.flag.hass_discovery) { return; } - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; - - if (!key && KeyTopicActive(0)) { - device = (XdrvMailbox.payload >> 24) & 0xFF; - } - - char scommand[CMDSZ]; - char sw_topic[TOPSZ]; - char key_topic[TOPSZ]; - char trg_state[8]; - char *tmpbtn = SettingsText(SET_MQTT_BUTTON_TOPIC); - char *tmpsw = SettingsText(SET_MQTT_SWITCH_TOPIC); - uint8_t evkey = 0; - Format(sw_topic, tmpsw, sizeof(sw_topic)); - Format(key_topic, tmpbtn, sizeof(key_topic)); - - if (state >= 2) { evkey = 1;} - snprintf_P(scommand, sizeof(scommand), PSTR("%s%d%s"), (key) ? "SWITCH" : "BUTTON", device, (evkey) ? "T" : ""); - - char stopic[TOPSZ]; - - if (!key) { - if (state == 3) { - snprintf_P(trg_state, sizeof(trg_state), GetStateText(3)); - } else { - if (state == 2) { state = 10; } - GetTextIndexed(trg_state, sizeof(trg_state), state -9, kHAssTriggerStringButtons); - } - } - - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, (evkey) ? "TRIG" : PSTR(D_RSLT_STATE), (key) ? GetStateText(state) : trg_state); - MqttPublish(stopic); -} - -bool HAssMqttLWT(void) -{ - if (strncasecmp_P(XdrvMailbox.topic, PSTR(HOME_ASSISTANT_LWT_TOPIC), strlen(HOME_ASSISTANT_LWT_TOPIC)) != 0) { - return false; - } - if (Settings.flag.hass_discovery && (strncasecmp_P(XdrvMailbox.data, PSTR("online"), strlen("online")) == 0) && (XdrvMailbox.data_len == 6)) { - MqttPublishTeleState(); - return true; - } else { return false; } -} - -void HassLwtSubscribe(bool hasslwt) -{ - char htopic[TOPSZ]; - snprintf_P(htopic, sizeof(htopic), PSTR(HOME_ASSISTANT_LWT_TOPIC)); - if (hasslwt && (Settings.flag.hass_discovery)) { - MqttSubscribe(htopic); - } else { MqttUnsubscribe(htopic); } -} - - - - - -bool Xdrv12(uint8_t function) -{ - bool result = false; - bool hasslwt = HOME_ASSISTANT_LWT_SUBSCRIBE; - if (Settings.flag.mqtt_enabled) - { - switch (function) - { - case FUNC_EVERY_SECOND: - if (hass_init_step) - { - hass_init_step--; - if (!hass_init_step) - { - HAssDiscovery(); - NewHAssDiscovery(); - } - } - 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; - case FUNC_ANY_KEY: - HAssAnyKey(); - break; - case FUNC_MQTT_INIT: - hass_mode = 0; - hass_init_step = 2; - - - - break; - - case FUNC_MQTT_SUBSCRIBE: - HassLwtSubscribe(hasslwt); - break; - case FUNC_MQTT_DATA: - result = HAssMqttLWT(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" -#if defined(USE_I2C) || defined(USE_SPI) -#ifdef USE_DISPLAY - -#define XDRV_13 13 - -#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 = 64; -const uint8_t DISPLAY_MAX_ROWS = 64; - -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 }; - -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]; -char disp_pres[5]; - -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) -{ - ExecuteCommandPower(disp_device, on, SRC_DISPLAY); -} - - - - -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 '~' - - -uint32_t decode_te(char *line) { - uint32_t skip = 0; - 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)); - skip++; - } else { - - if (strlen(cp)<2) { - - return skip; - } - - sbuf[0]=*(cp); - sbuf[1]=*(cp+1); - sbuf[2]=0; - *line=strtol(sbuf,0,16); - - memmove(cp,cp+2,strlen(cp)-1); - skip += 2; - } - } - line++; - } - return skip; -} - - - -#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': - DisplayOnOff(0); - break; - case 'O': - DisplayOnOff(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': { - uint8_t param1 = RtcTime.day_of_month; - uint8_t param2 = RtcTime.month; - if (*cp=='U') { - cp++; - param1 = RtcTime.month; - param2 = RtcTime.day_of_month; - } - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), param1, param2, 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; uint8_t dflg=1; - if (*cp=='e' || *cp=='d') { - - uint8_t dis=0; - if (*cp=='d') dis=1; - cp++; - var=atoiv(cp,&num); - num=num%MAXBUTTONS; - cp+=var; - if (buttons[num]) { - buttons[num]->vpower.disable=dis; - if (!dis) { - if (buttons[num]->vpower.is_virtual) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); - else buttons[num]->xdrawButton(bitRead(power,num)); - } - } - break; - } - if (*cp=='-') { - cp++; - dflg=0; - } - 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]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ - renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); - if (!bflags) { - - if (dflg) buttons[num]->xdrawButton(bitRead(power,num)); - buttons[num]->vpower.is_virtual=0; - } else { - - buttons[num]->vpower.is_virtual=1; - if (bflags==2) { - - buttons[num]->vpower.is_pushbutton=1; - } else { - - buttons[num]->vpower.is_pushbutton=0; - } - if (dflg) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); - buttons[num]->vpower.disable=!dflg; - } - } - } - } - break; -#endif - default: - - Response_P(PSTR("Unknown Escape")); - goto exit; - break; - } - } - } - } - exit: - - dp -= decode_te(linebuf); - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { - *dp = 0; - } else { - linebuf[abs(int(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()); - snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); - - 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"), NetworkHostname()); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), NetworkMacAddress().c_str()); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), NetworkAddress().toString().c_str()); - DisplayLogBufferAdd(buffer); - if (!global_state.wifi_down) { - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); - 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%s"), value, disp_pres); - } - 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) -{ -# 1168 "/workspace/Tasmota/tasmota/xdrv_13_display.ino" - String jsonStr = json; - JsonParser parser((char*)jsonStr.c_str()); - JsonParserObject root = parser.getRootObject(); - if (root) { - - const char *unit = root.getStr(PSTR(D_JSON_TEMPERATURE_UNIT), nullptr); - if (unit) { - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); - } - unit = root.getStr(PSTR(D_JSON_PRESSURE_UNIT), nullptr); - if (unit) { - snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); - } - for (auto key1 : root) { - JsonParserToken value1 = key1.getValue(); - if (value1.isObject()) { - JsonParserObject Object2 = value1.getObject(); - for (auto key2 : Object2) { - JsonParserToken value2 = key2.getValue(); - if (value2.isObject()) { - JsonParserObject Object3 = value2.getObject(); - for (auto key3 : Object3) { - const char* value3 = key3.getValue().getStr(nullptr); - if (value3 != nullptr) { - DisplayJsonValue(topic, key1.getStr(), key3.getStr(), value3); - } - } - } else { - const char* value = value2.getStr(nullptr); - if (value != nullptr) { - DisplayJsonValue(topic, key1.getStr(), key2.getStr(), value); - } - } - } - } else { - const char* value = value1.getStr(nullptr); - if (value != nullptr) { - DisplayJsonValue(topic, key1.getStr(), key1.getStr(), value); - } - } - } - } -} - -void DisplayMqttSubscribe(void) -{ - - - - - - - if (Settings.display_model && (Settings.display_mode &0x04)) { - - char stopic[TOPSZ]; - char ntopic[TOPSZ]; - - ntopic[0] = '\0'; - strlcpy(stopic, SettingsText(SET_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, SettingsText(SET_MQTTPREFIX3), 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/"), SettingsText(SET_MQTTPREFIX3)); - 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++; - if (!PinUsed(GPIO_BACKLIGHT)) { - if (light_type && (4 == 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); - - - - 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) { -# 1453 "/workspace/Tasmota/tasmota/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); -} - - - - -#ifdef ESP32 -#ifdef JPEG_PICTS -#include "img_converters.h" -#include "esp_jpg_decode.h" -bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); -char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height); -void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len); -#endif -#endif - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -extern FS *fsp; -#define XBUFF_LEN 128 -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { - if (!renderer) return; - File fp; - char *ending = strrchr(file,'.'); - if (!ending) return; - ending++; - char estr[8]; - memset(estr,0,sizeof(estr)); - for (uint32_t cnt=0; cntopen(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 - renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); - uint16_t rgb[xsize]; - for (int16_t j=0; jpushColors(rgb,xsize,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(); - } else if (!strcmp(estr,"jpg")) { - -#ifdef ESP32 -#ifdef JPEG_PICTS - if (psramFound()) { - fp=fsp->open(file,FILE_READ); - if (!fp) return; - uint32_t size = fp.size(); - uint8_t *mem = (uint8_t *)heap_caps_malloc(size+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (mem) { - uint8_t res=fp.read(mem, size); - if (res) { - uint16_t xsize; - uint16_t ysize; - if (mem[0]==0xff && mem[1]==0xd8) { - get_jpeg_size(mem, size, &xsize, &ysize); - - if (xsize && ysize) { - uint8_t *out_buf = (uint8_t *)heap_caps_malloc((xsize*ysize*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (out_buf) { - uint8_t *ob=out_buf; - jpg2rgb888(mem, size, out_buf, (jpg_scale_t)JPG_SCALE_NONE); - uint16_t pixels=xsize*ysize/XBUFF_LEN; - renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); - for(int32_t j=0; jpushColors(rbuff,XBUFF_LEN,true); - OsWatchLoop(); - } - renderer->setAddrWindow(0,0,0,0); - free(out_buf); - } - } - } - } - free(mem); - } - fp.close(); - } -#endif -#endif - } -} -#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) -#ifdef ESP32 -#include -#endif - -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; - fsp->remove(path); - fp=fsp->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=fsp->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 - -#ifdef USE_FT5206 - -#include - -#undef FT5206_address -#define FT5206_address 0x38 - -FT5206_Class *touchp; -TP_Point pLoc; -bool FT5206_found; - -bool Touch_Init(TwoWire &i2c) { - FT5206_found = false; - touchp = new FT5206_Class(); - if (touchp->begin(i2c, FT5206_address)) { - I2cSetActiveFound(FT5206_address, "FT5206"); - FT5206_found = true; - } - return FT5206_found; -} - -uint32_t Touch_Status(uint32_t sel) { - if (FT5206_found) { - switch (sel) { - case 0: - return touchp->touched(); - case 1: - return pLoc.x; - case 2: - return pLoc.y; - } - return 0; - } else { - return 0; - } -} - - -#ifdef USE_TOUCH_BUTTONS -void Touch_MQTT(uint8_t index, const char *cp) { - ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, buttons[index]->vpower.on_off); - MqttPublishTeleSensor(); -} - -void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower.on_off = 1; - else buttons[count]->vpower.on_off = 0; -} - - -void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { -uint16_t temp; -uint8_t rbutt=0; -uint8_t vbutt=0; - - - if (touchp->touched()) { - - pLoc = touchp->getPoint(0); - - if (renderer) { - - rotconvert(&pLoc.x, &pLoc.y); - - - - for (uint8_t count=0; countvpower.disable) { - if (buttons[count]->contains(pLoc.x, pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!buttons[count]->vpower.is_virtual) { - uint8_t pwr=bitRead(power, rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - Touch_RDW_BUTT(count, !pwr); - } - } else { - - const char *cp; - if (!buttons[count]->vpower.is_pushbutton) { - - buttons[count]->vpower.on_off ^= 1; - cp="TBT"; - } else { - - buttons[count]->vpower.on_off = 1; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower.on_off); - Touch_MQTT(count,cp); - } - } - } - if (!buttons[count]->vpower.is_virtual) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countpress(false); - if (buttons[count]->justReleased()) { - if (buttons[count]->vpower.is_virtual) { - if (buttons[count]->vpower.is_pushbutton) { - - buttons[count]->vpower.on_off = 0; - Touch_MQTT(count,"PBT"); - buttons[count]->xdrawButton(buttons[count]->vpower.on_off); - } - } - } - if (!buttons[count]->vpower.is_virtual) { - - uint8_t pwr = bitRead(power, rbutt); - uint8_t vpwr = buttons[count]->vpower.on_off; - if (pwr != vpwr) { - Touch_RDW_BUTT(count, pwr); - } - rbutt++; - } - } - } - pLoc.x = 0; - pLoc.y = 0; - } -} - -#endif -#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 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_MP3_DFR562)) { - switch (function) { - case FUNC_PRE_INIT: - MP3PlayerInit(); - break; - case FUNC_COMMAND: - result = MP3PlayerCmd(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_15_pca9685.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_15_pca9685.ino" -#ifdef USE_I2C -#ifdef USE_PCA9685 - - - - - - -#define XDRV_15 15 -#define XI2C_01 1 - -#define PCA9685_REG_MODE1 0x00 -#define PCA9685_REG_LED0_ON_L 0x06 -#define PCA9685_REG_PRE_SCALE 0xFE - -#ifndef USE_PCA9685_ADDR - #define USE_PCA9685_ADDR 0x40 -#endif -#ifndef USE_PCA9685_FREQ - #define USE_PCA9685_FREQ 50 -#endif - -bool pca9685_detected = false; -uint16_t pca9685_freq = USE_PCA9685_FREQ; -uint16_t pca9685_pin_pwm_value[16]; - -void PCA9685_Detect(void) -{ - if (I2cActive(USE_PCA9685_ADDR)) { 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 = true; - I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); - 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) -{ - 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) { - MqttPublishTeleSensor(); - } -} - -bool Xdrv15(uint8_t function) -{ - if (!I2cEnabled(XI2C_01)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PCA9685_Detect(); - } - else if (pca9685_detected) { - switch (function) { - case FUNC_EVERY_SECOND: - if (tele_period == 0) { - PCA9685_OutputTelemetry(true); - } - break; - case FUNC_COMMAND_DRIVER: - if (XDRV_15 == XdrvMailbox.index) { - result = PCA9685_Command(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -#ifdef USE_LIGHT -#ifdef USE_TUYA_MCU - -#define XDRV_16 16 -#define XNRG_32 32 - -#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_CMD_SET_TIME 0x1C - -#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 -#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 -#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 -#define TUYA_LOW_POWER_CMD_STATE 0x05 - -#define TUYA_TYPE_BOOL 0x01 -#define TUYA_TYPE_VALUE 0x02 -#define TUYA_TYPE_STRING 0x03 -#define TUYA_TYPE_ENUM 0x04 - -#define TUYA_BUFFER_SIZE 256 - -#include - -TasmotaSerial *TuyaSerial = nullptr; - -struct TUYA { - uint16_t Levels[5] = {0,0,0,0,0}; - uint16_t Snapshot[5] = {0,0,0,0,0}; - char HSBColor[13]; - uint16_t CTMin = 153; - uint16_t CTMax = 500; - bool ModeSet = false; - uint8_t FanState = 0; - bool SuspendTopic = false; - uint32_t ignore_topic_timeout = 0; - bool ignore_dim = false; - uint8_t cmd_status = 0; - uint8_t cmd_checksum = 0; - uint8_t data_len = 0; - uint8_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; - bool low_power_mode = false; - bool send_success_next_second = false; - uint32_t ignore_dimmer_cmd_timeout = 0; - bool ignore_tuyareceived = false; -} Tuya; - -const char kTuyaCommand[] PROGMEM = "|" - D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; - -void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu, &CmndTuyaSend -}; - - - - -bool IsModuleTuya(void) -{ - return ((TUYA_DIMMER == my_module_type) || (SK03_TUYA == my_module_type)); -} - -bool AsModuleTuyaMS(void) -{ - return ((light_type > LT_RGB) && TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0); -} - -bool IsTuyaFanCtrl(void) -{ - return ((TuyaGetDpId(TUYA_MCU_FUNC_FAN3) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN4) != 0) || - (TuyaGetDpId(TUYA_MCU_FUNC_FAN5) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_FAN6) != 0)); -} - -bool TuyaModeSet(void) -{ - return Tuya.ModeSet; -} - -uint8_t TuyaFanSpeeds(void) -{ - uint8_t FanSpeeds = 0; - for (uint32_t i = 0; i <= 3; i++) { - if (TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i) != 0) { - FanSpeeds = i + 2; - } - } - return FanSpeeds; -} - -uint8_t TuyaFanState(void) -{ - return Tuya.FanState; -} -# 143 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -void CmndTuyaSend(void) { - if (XdrvMailbox.index > 4 && XdrvMailbox.index < 8) { - return; - } - if (XdrvMailbox.index == 0) { - TuyaRequestState(0); - } else if (XdrvMailbox.index == 8) { - TuyaRequestState(8); - } else if (XdrvMailbox.index == 9) { - if (Settings.tuyamcu_topic) { Settings.tuyamcu_topic = 0; } else { Settings.tuyamcu_topic = 1; } - AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: TuyaMCU Stat Topic %s"), (Settings.tuyamcu_topic ? PSTR("enabled") : PSTR("disabled"))); - - } else { - if (XdrvMailbox.data_len > 0) { - char *p; - char *data; - uint8_t i = 0; - uint8_t dpId = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - if ( i == 0) { - dpId = strtoul(str, nullptr, 0); - } else { - data = str; - } - i++; - } - - if (1 == XdrvMailbox.index) { - TuyaSendBool(dpId, strtoul(data, nullptr, 0)); - } else if (2 == XdrvMailbox.index) { - TuyaSendValue(dpId, strtoull(data, nullptr, 0)); - } else if (3 == XdrvMailbox.index) { - TuyaSendString(dpId, data); - } else if (4 == XdrvMailbox.index) { - TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); - } - } - } - ResponseCmndDone(); -} - - - -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])) { - - - - - - bool DualDim; - if (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { DualDim = true; } - } else if (TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { DualDim = true; } - } else if ((TUYA_MCU_FUNC_DIMMER == parm[0] && parm[1] == 0) || (TUYA_MCU_FUNC_DIMMER2 == parm[0] && parm[1] == 0)) { DualDim = false; }; - if (DualDim) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_CT, 0); } - if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_RGB, 0); } - if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_WHITE, 0); } - Settings.flag3.pwm_multi_channels = 1; - } else { Settings.flag3.pwm_multi_channels = 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("{\"" D_CMND_TUYA_MCU "\":[")); - 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_REPORT2) || - (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_BATTERY_PERCENTAGE) || - (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || - (fnId >= TUYA_MCU_FUNC_FAN3 && fnId <= TUYA_MCU_FUNC_FAN6) || - (fnId >= TUYA_MCU_FUNC_MOTOR_DIR && fnId <= TUYA_MCU_FUNC_DUMMY) || - (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); -} - -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: - case TUYA_TYPE_ENUM: - 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)); -} - -void TuyaSendEnum(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); -} - -void TuyaSendString(uint8_t id, char data[]) { - - uint16_t len = strlen(data); - uint16_t payload_len = 4 + len; - uint8_t payload_buffer[payload_len]; - payload_buffer[0] = id; - payload_buffer[1] = TUYA_TYPE_STRING; - payload_buffer[2] = len >> 8; - payload_buffer[3] = len & 0xFF; - - for (uint16_t i = 0; i < len; i++) { - payload_buffer[4+i] = data[i]; - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -bool TuyaSetPower(void) -{ - bool status = false; - - uint8_t rpower = XdrvMailbox.index; - int16_t source = XdrvMailbox.payload; - - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); - if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); - - if (source != SRC_SWITCH && TuyaSerial) { - TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); - delay(20); - status = true; - } - return status; -} - -bool TuyaSetChannels(void) -{ - uint16_t hue, TuyaData; - uint8_t sat, bri; - uint8_t TuyaIdx = 0; - char hex_char[13]; - bool noupd = false; - bool LightMode = TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0; - uint8_t idx = 0; - snprintf_P(hex_char, sizeof(hex_char), PSTR("000000000000")); - - if (LT_SERIAL1 == light_type) { - Tuya.Snapshot[0] = light_state.getDimmer(); - } - if (LT_SERIAL2 == light_type || LT_RGBWC == light_type) { - idx = 1; - if (LT_SERIAL2 == light_type && Settings.flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) { - - Tuya.Snapshot[0] = changeUIntScale(Light.current_color[0], 0, 255, 0, 100); - Tuya.Snapshot[1] = changeUIntScale(Light.current_color[1], 0, 255, 0, 100); - } else { - light_state.getCTRange(&Tuya.CTMin, &Tuya.CTMax); - Tuya.Snapshot[0] = light_state.getDimmer(); - Tuya.Snapshot[1] = light_state.getCT(); - } - } - if (LT_RGBW == light_type) { - idx = 1; - Tuya.Snapshot[0] = light_state.getDimmer(1); - Tuya.Snapshot[1] = light_state.getDimmer(2); - } - - if (light_type > LT_BASIC) { - - if (LT_RGB != light_type) { - for (uint8_t i = 0; i <= idx; i++) { - if (Tuya.Snapshot[i] != Tuya.Levels[i]) { - if (i == 0 && LightMode && Tuya.ModeSet ) { noupd = true;} - if (!noupd) { - LightSerialDuty(Tuya.Snapshot[i], &hex_char[0], i+1); - Tuya.Levels[i] = Tuya.Snapshot[i]; - } - noupd = false; - } - } - } - - if (light_type >= LT_RGB) { - - light_state.getHSB(&hue, &sat, &bri); - sat = changeUIntScale(sat, 0, 255, 0, 100); - bri = changeUIntScale(bri, 0, 255, 0, 100); - if (hue != Tuya.Snapshot[2] || sat != Tuya.Snapshot[3] || bri != Tuya.Snapshot[4]) { - if ((LightMode && Tuya.ModeSet) || LT_RGB == light_type) { - snprintf_P(hex_char, sizeof(hex_char), PSTR("%04X%04X%04X"), hue, sat * 10, bri * 10); - LightSerialDuty(0, &hex_char[0], 3); - memcpy_P(Tuya.HSBColor, hex_char, strlen(hex_char)); - Tuya.Snapshot[2] = hue; - Tuya.Snapshot[3] = sat; - Tuya.Snapshot[4] = bri; - } - } - } - } - return true; -} - -void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) -{ - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); - bool CTLight = false; - - if (TuyaIdx > 0 && TuyaIdx <= 2) { - - if (TuyaIdx == 2) { - if (!Settings.flag3.pwm_multi_channels) { - CTLight = true; - dpid = TuyaGetDpId(TUYA_MCU_FUNC_CT); - } else { dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2); } - } - - if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - if (TuyaIdx == 2 && CTLight) { - duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0); - } else { duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max); } - - if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } - Tuya.ignore_dimmer_cmd_timeout = millis() + 250; - if (Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { - TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 0); - } - TuyaSendValue(dpid, duty); - - } else if (dpid > 0 && TuyaIdx <= 2) { - - Tuya.ignore_dim = false; - - if (TuyaIdx == 2 && CTLight) { - duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0); - } else { - duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value %d for dpid %d"), duty, dpid); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); - } - } - - if (TuyaIdx == 3) { - dpid = TuyaGetDpId(TUYA_MCU_FUNC_RGB); - if (!Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { - TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 1); - } - TuyaSendString(dpid, hex_char); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: TX RGB hex %s to dpId %d"), hex_char, dpid); - } -} - -void TuyaRequestState(uint8_t state_type) -{ - if (TuyaSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); - Tuya.SuspendTopic = true; - Tuya.ignore_topic_timeout = millis() + 1000; - switch (state_type) { - case 0: - TuyaSendCmd(TUYA_CMD_QUERY_STATE); - break; - case 8: - TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); - break; - } - } -} - -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 TuyaProcessStatePacket(void) { - char scmnd[20]; - uint8_t dpidStart = 6; - uint8_t fnId; - uint16_t dpDataLen; - - while (dpidStart + 4 < Tuya.byte_counter) { - dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); - - if (Tuya.buffer[dpidStart + 1] == 1) { - - 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[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], 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[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 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[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); - - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); - SwitchHandler(1); - } - } - } - else if (Tuya.buffer[dpidStart + 1] == 2) { - bool tuya_energy_enabled = (XNRG_32 == energy_flg); - uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; - uint8_t dimIndex; - if ((fnId == TUYA_MCU_FUNC_FAN3) || (fnId == TUYA_MCU_FUNC_FAN4) || - (fnId == TUYA_MCU_FUNC_FAN5) || (fnId == TUYA_MCU_FUNC_FAN6)) { - Tuya.FanState = packetValue; - } - - if (fnId == TUYA_MCU_FUNC_DIMMER || fnId == TUYA_MCU_FUNC_REPORT1) { dimIndex = 0; } - - if (fnId == TUYA_MCU_FUNC_DIMMER2 || fnId == TUYA_MCU_FUNC_REPORT2 || fnId == TUYA_MCU_FUNC_CT) { dimIndex = 1; } - - if (dimIndex == 1 && !Settings.flag3.pwm_multi_channels) { - Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, Tuya.CTMax, Tuya.CTMin); - } else { - Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX value %d from dpId %d "), packetValue, Tuya.buffer[dpidStart]); - - if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1) || - (fnId == TUYA_MCU_FUNC_DIMMER2) || (fnId == TUYA_MCU_FUNC_REPORT2) || - (fnId == TUYA_MCU_FUNC_CT) || (fnId == TUYA_MCU_FUNC_WHITE)) { - - if (Tuya.ignore_dimmer_cmd_timeout < millis()) { - - if ((power || Settings.flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { - - Tuya.ignore_dim = true; - skip_light_fade = true; - - scmnd[0] = '\0'; - if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1)) { - if (Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[0] - changeUIntScale(Light.current_color[0], 0, 255, 0, 100))) > 1) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "1 %d"), Tuya.Levels[0]); - } - else if ((abs(Tuya.Levels[0] - light_state.getDimmer())) > 1) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER "3 %d"), Tuya.Levels[0]); - } - } - if (((fnId == TUYA_MCU_FUNC_DIMMER2) || (fnId == TUYA_MCU_FUNC_REPORT2)) && - Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[1] - changeUIntScale(Light.current_color[1], 0, 255, 0, 100))) > 1) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "2 %d"), Tuya.Levels[1]); - } - if ((fnId == TUYA_MCU_FUNC_CT) && (abs(Tuya.Levels[1] - light_state.getCT())) > 1) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLORTEMPERATURE " %d"), Tuya.Levels[1]); - } - if ((fnId == TUYA_MCU_FUNC_WHITE) && (abs(Tuya.Levels[1] - light_state.getDimmer(2))) > 1) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WHITE " %d"), Tuya.Levels[1]); - } - if (scmnd[0] != '\0') { - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - } - } - #ifdef USE_ENERGY_SENSOR - else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)packetValue / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); - - 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 - } - else if (Tuya.buffer[dpidStart + 1] == 3) { - const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - if ((TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) && dpDataLen == 12) { - - - char RgbData[13]; - snprintf_P(RgbData, sizeof(RgbData), PSTR("%.*s"), dpDataLen, dpData); - char HSB1[5], HSB2[5], HSB3[5]; - snprintf_P(HSB1, sizeof(HSB1), PSTR("%.4s\n"), &RgbData[0]); - snprintf_P(HSB2, sizeof(HSB2), PSTR("%.4s\n"), &RgbData[4]); - snprintf_P(HSB3, sizeof(HSB3), PSTR("%.4s\n"), &RgbData[8]); - - if ((Tuya.Snapshot[2] != ((int)strtol(HSB1, NULL, 16)) || - Tuya.Snapshot[3] != ((int)strtol(HSB2, NULL, 16)) / 10 || Tuya.Snapshot[4] !=((int)strtol(HSB3, NULL, 16)) / 10)) { - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_HSBCOLOR " %d,%d,%d"), ((int)strtol(HSB1, NULL, 16)), - ((int)strtol(HSB2, NULL, 16)) / 10, ((int)strtol(HSB3, NULL, 16)) / 10); - ExecuteCommand(scmnd, SRC_SWITCH); - - memcpy_P(Tuya.HSBColor, RgbData, strlen(RgbData)); - } - } - } - else if (Tuya.buffer[dpidStart + 1] == 4) { - const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - if (fnId == TUYA_MCU_FUNC_MODESET) { - Tuya.ModeSet = dpData[0]; - Tuya.Levels[3] = dpData[0]; - } - } - dpidStart += dpDataLen + 4; - } -} -void TuyaLowPowerModePacketProcess(void) { - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSetWifiLed(); - break; - - case TUYA_LOW_POWER_CMD_STATE: - TuyaProcessStatePacket(); - Tuya.send_success_next_second = true; - break; - } - -} - -void TuyaHandleProductInfoPacket(void) { - uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - char *data = &Tuya.buffer[6]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); -} - -void TuyaSendLowPowerSuccessIfNeeded(void) { - uint8_t success = 1; - - if (Tuya.send_success_next_second) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); - Tuya.send_success_next_second = false; - } -} - -void TuyaNormalPowerModePacketProcess(void) -{ - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSendCmd(TUYA_CMD_MCU_CONF); - break; - - 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: - TuyaProcessStatePacket(); - 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 = TuyaGetTuyaWifiState(); - 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 < ARRAY_SIZE(Settings.my_gp.io); i++) { - if (Settings.my_gp.io[i] == AGPIO(GPIO_LED1)) led1_set = true; - else if (Settings.my_gp.io[i] == AGPIO(GPIO_KEY1)) key1_set = true; - } - if (!Settings.my_gp.io[led1_gpio] && !led1_set) { - Settings.my_gp.io[led1_gpio] = AGPIO(GPIO_LED1); - restart_flag = 2; - } - if (!Settings.my_gp.io[key1_gpio] && !key1_set) { - Settings.my_gp.io[key1_gpio] = AGPIO(GPIO_KEY1); - restart_flag = 2; - } - } - TuyaRequestState(0); - break; - - default: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); - } -} - - - - - -bool TuyaModuleSelected(void) -{ - if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { - SetPin(1, AGPIO(GPIO_TUYA_TX)); - SetPin(3, AGPIO(GPIO_TUYA_RX)); - Settings.my_gp.io[1] = AGPIO(GPIO_TUYA_TX); - Settings.my_gp.io[3] = AGPIO(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; - - 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 && TuyaGetDpId(TUYA_MCU_FUNC_DUMMY) == 0) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - devices_present++; - SettingsSaveAll(); - } -# 831 "/workspace/Tasmota/tasmota/xdrv_16_tuyamcu.ino" - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { - light_type = LT_RGBWC; - } else if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { - light_type = LT_RGBW; - } else { light_type = LT_RGB; } - } else if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { - light_type = LT_RGBWC; - } else { light_type = LT_SERIAL2; } - } else { light_type = LT_SERIAL1; } - } else { - light_type = LT_BASIC; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { - Tuya.low_power_mode = true; - Settings.flag3.fast_power_cycle_disable = true; - } - - UpdateDevices(); - return true; -} - -void TuyaInit(void) -{ - int baudrate = 9600; - if (Settings.flag4.tuyamcu_baudrate) { baudrate = 115200; } - - 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(baudrate)) { - if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } - - Tuya.SuspendTopic = true; - Tuya.ignore_topic_timeout = millis() + 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration at %d bps"), baudrate); - TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); - - } - } - 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; - - char hex_char[(Tuya.byte_counter * 2) + 2]; - uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - - Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); - - uint16_t DataVal = 0; - uint8_t dpId = 0; - uint8_t dpDataType = 0; - char DataStr[13]; - - if (len > 0) { - ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); - if (TUYA_CMD_STATE == Tuya.buffer[3]) { - - - uint8_t dpidStart = 6; - - while (dpidStart + 4 < Tuya.byte_counter) { - dpId = Tuya.buffer[dpidStart]; - dpDataType = Tuya.buffer[dpidStart + 1]; - uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); - - if (TUYA_CMD_STATE == Tuya.buffer[3]) { - ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); - if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("%u"), dpData[0]); - DataVal = dpData[0]; - } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { - uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; - ResponseAppend_P(PSTR("%u"), dpValue); - DataVal = dpValue; - } else if (TUYA_TYPE_STRING == dpDataType) { - ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); - snprintf_P(DataStr, sizeof(DataStr), PSTR("%.*s"), dpDataLen, dpData); - } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("%u"), dpData[0]); - DataVal = dpData[0]; - } else { - ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); - snprintf_P(DataStr, sizeof(DataStr), PSTR("%s"), dpHexData); - } - } - - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); - if (TUYA_TYPE_STRING == dpDataType) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); - } - ResponseAppend_P(PSTR("}")); - dpidStart += dpDataLen + 4; - } - } - } - ResponseAppend_P(PSTR("}}")); - - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); - } else { - AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); - } - XdrvRulesProcess(); - - if (dpId != 0 && Settings.tuyamcu_topic) { - if (!Tuya.SuspendTopic) { - char scommand[10]; - snprintf_P(scommand, sizeof(scommand), PSTR("TuyaSend%d"), dpDataType); - - if (dpDataType != 3 && dpDataType != 5) { Response_P(PSTR("%d,%u"), dpId, DataVal); } - else { Response_P(PSTR("%d,%s"), dpId, DataStr); } - MqttPublishPrefixTopic_P(STAT, (PSTR("%s"), scommand)); - } - } - - if (!Tuya.low_power_mode) { - TuyaNormalPowerModePacketProcess(); - } else { - TuyaLowPowerModePacketProcess(); - } - - 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; -} - -uint8_t TuyaGetTuyaWifiState(void) { - - uint8_t wifi_state = 0x02; - switch(WifiState()){ - case WIFI_MANAGER: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - if (MqttIsConnected()) { - wifi_state = 0x04; - } - - return wifi_state; -} - -void TuyaSetWifiLed(void) -{ - Tuya.wifi_state = TuyaGetTuyaWifiState(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); - - if (Tuya.low_power_mode) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } else { - TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } -} - -#ifdef USE_TUYA_TIME -void TuyaSetTime(void) { - if (!RtcTime.valid) { return; } - - uint16_t payload_len = 8; - uint8_t payload_buffer[8]; - payload_buffer[0] = 0x01; - payload_buffer[1] = RtcTime.year %100; - payload_buffer[2] = RtcTime.month; - payload_buffer[3] = RtcTime.day_of_month; - payload_buffer[4] = RtcTime.hour; - payload_buffer[5] = RtcTime.minute; - payload_buffer[6] = RtcTime.second; - payload_buffer[7] = RtcTime.day_of_week; - - TuyaSendCmd(TUYA_CMD_SET_TIME, payload_buffer, payload_len); -} -#endif - -#ifdef USE_ENERGY_SENSOR - - - - - -bool Xnrg32(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_32; - } - } - } - 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_PRE_INIT: - TuyaInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = TuyaSetPower(); - break; - case FUNC_BUTTON_PRESSED: - result = TuyaButtonPressed(); - break; - case FUNC_EVERY_SECOND: - TuyaSetChannels(); - if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } - if (!Tuya.low_power_mode) { - Tuya.heartbeat_timer++; - if (Tuya.heartbeat_timer > 10) { - Tuya.heartbeat_timer = 0; - TuyaSendCmd(TUYA_CMD_HEARTBEAT); - } -#ifdef USE_TUYA_TIME - if (!(uptime % 60)) { - TuyaSetTime(); - } -#endif - } else { - TuyaSendLowPowerSuccessIfNeeded(); - } - if (Tuya.ignore_topic_timeout < millis()) { Tuya.SuspendTopic = false; } - break; - - - - case FUNC_COMMAND: - result = DecodeCommand(kTuyaCommand, TuyaCommand); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_17_rcswitch.ino" -# 20 "/workspace/Tasmota/tasmota/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); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, data); -#endif - } - mySwitch.resetAvailable(); - } -} - -void RfInit(void) -{ - if (PinUsed(GPIO_RFSEND)) { - mySwitch.enableTransmit(Pin(GPIO_RFSEND)); - } - if (PinUsed(GPIO_RFRECV)) { - pinMode( Pin(GPIO_RFRECV), INPUT); - 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; - - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (root) { - - char parm_uc[10]; - data = root.getUInt(PSTR(D_JSON_RF_DATA), data); - bits = root.getUInt(PSTR(D_JSON_RF_BITS), bits); - protocol = root.getInt(PSTR(D_JSON_RF_PROTOCOL), protocol); - repeat = root.getInt(PSTR(D_JSON_RF_REPEAT), repeat); - pulse = root.getInt(PSTR(D_JSON_RF_PULSE), 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 (PinUsed(GPIO_RFSEND) || PinUsed(GPIO_RFRECV)) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (PinUsed(GPIO_RFRECV)) { - RfReceiveCheck(); - } - break; - case FUNC_COMMAND: - if (PinUsed(GPIO_RFSEND)) { - result = DecodeCommand(kRfSendCommands, RfSendCommand); - } - break; - case FUNC_INIT: - RfInit(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" -# 20 "/workspace/Tasmota/tasmota/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) -{ - devices_present++; - 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_MANAGER: - 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 "/workspace/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_PS_16_DZ - - - - -#define XDRV_19 19 - -#define PS16DZ_BUFFER_SIZE 80 - -#include - -TasmotaSerial *PS16DZSerial = nullptr; - -struct PS16DZ { - char *rx_buffer = nullptr; - int byte_counter = 0; - uint8_t dimmer = 0; -} Ps16dz; - - - - - -void PS16DZSerialSend(const char *tx_buffer) -{ - - - PS16DZSerial->print(tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); -} - -void PS16DZSerialSendOk(void) -{ - char tx_buffer[16]; - snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); - PS16DZSerialSend(tx_buffer); -} - - - - -void PS16DZSerialSendUpdateCommand(void) -{ - uint8_t light_state_dimmer = light_state.getDimmer(); - - 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; - - 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); - - PS16DZSerialSend(tx_buffer); -} - - - - - -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; - - - - - if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { - - } - else 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 is_switch_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)) { - bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - is_switch_change = (switch_state != power); - if (is_switch_change) { - ExecuteCommandPower(1, switch_state, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"bright\"", 8)) { - Ps16dz.dimmer = atoi(token3); - - - - 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)) { - - - - } - token = strtok_r(nullptr, ",", &end_str); - } - - if (!is_brightness_change) { - - - - PS16DZSerialSendOk(); - } - } - 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 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; -} - - - - - -bool Xdrv19(uint8_t function) -{ - bool result = false; - - if (PS_16_DZ == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); - break; - case FUNC_INIT: - PS16DZInit(); - break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -# 31 "/workspace/Tasmota/tasmota/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.24.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); - bridgeid += "FFFE"; - bridgeid += 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); - String uuid = HueUuid(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST1, uuid.c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST2, uuid.c_str(), uuid.c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST3, uuid.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)); - } - - PrepLog_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 size_t HUE_DESCRIPTION_XML_SIZE = 626; -const char HUE_DESCRIPTION_XML_COMPRESSED[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" - "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\xF0\x62\x98\xDB\xF1\xD6\x2C" - "\x67\x0C\x3A\xF3\xE3\xC7\x98\x8C\xCF\x43\x67\x59\xC8\x75\xB3\xD8\x7E\x1E\x85\xE1" - "\x8C\x32\x33\x04\x1C\x78\xFC\x3D\x06\xD9\xAF\x3E\x7E\x1C\x87\xA1\xD8\x40\x83\x14" - "\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x8F\x85\x1E\xC3\xD0" - "\x85\x97\xC8\x22\x1D\x7E\x67\xE0\xAA\xA1\x87\x99\xD8\x76\x1E\xD3\x61\xC8\x79\xFD" - "\x9D\x87\xA1\xD8\x40\x87\x50\xF4\x04\x1D\x18\x10\xE2\x15\x19\x0C\x67\xE0\x2B\x6D" - "\xC7\x99\x0E\xBF\x68\x67\x99\xC8\x7A\x1D\x84\x08\xD8\x61\xE8\x63\xFA\xF8\x40\x8C" - "\x8B\xAC\x6B\x3F\x0A\xC6\xD9\xB7\x38\xEB\x26\x18\xAC\x3A\xC8\x51\x59\xD6\x43\xBF" - "\xA2\x0F\x34\x77\x4F\x69\xB0\xE4\x3B\xC7\xA1\xD8\x40\x91\x83\x1E\x83\x6F\x85\x98" - "\xB0\xE8\x5F\xDF\xCF\xC2\xFE\x19\x58\x48\x86\x0A\xD0\xB4\x67\x91\x30\x98\x75\xFC" - "\xED\x0F\xC7\xA1\xD8\x09\x18\x20\x24\x62\x44\x2C\xBE\x41\x02\x1F\x06\xE3\xE3\xE3" - "\xE7\x41\x80\x83\x8D\x1D\x03\xC1\xA0\x93\x89\x10\xB2\xF9\x04\x7E\x1E\x83\x70\x46" - "\x11\x08\xFC\x1F\xF4\x65\x6E\x71\xF8\x08\x7A\x48\xA1\x6D\x10\xC7\xFF\x67\x58\x48" - "\x87\xF7\xEC\x27\xEF\x22\x0B\x47\x85\x56\xF0\xF1\xE8\x76\x02\x66\x2A\x2B\x08\x39" - "\x39\x75\x8D\x60\x91\x90\x0E\x04\x1E\x12\x0E\x53\x94\x40\x85\x88\x82\x17\x08\x98" - "\x23\x08\xB8\x58\xD1\xCF\xE7\xE1\xC5\x49\xB7\x55\xDA\xEC\x81\x0F\x01\x04\x1A\xC7" - "\xA7\x9F\xF6\xC1\x0E\x51\xED\x36\x1C\xB3\xD0\xEC\x20\x48\x9C\x7A\x10\xB2\x10\xB8" - "\xFC\x16\x2F\x44\x3C\xCF\x69\xB0\xE5\x1E\x87\x61\x10\xB2\x10\xB8\xFC\x04\x3E\x38" - "\xCF\xC3\xD0\xEC\xFE\x65\x1F\x93\x85\x23\x74\xE1\x48\xDC"; -# 167 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" -const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM = - "%s\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}"; -# 179 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" -const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = - ",\"type\":\"Extended color light\"," - "\"name\":\"%s\"," - "\"modelid\":\"%s\"," - "\"manufacturername\":\"%s\"," - "\"uniqueid\":\"%s\"}"; - - - -const char HUE_GROUP0_STATUS_JSON[] PROGMEM = - "{\"name\":\"Group 0\"," - "\"lights\":[{l1]," - "\"type\":\"LightGroup\"," - "\"action\":"; -# 214 "/workspace/Tasmota/tasmota/xdrv_20_hue.ino" -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_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -String GetHueDeviceId(uint16_t id) -{ - String deviceid = WiFi.macAddress(); - deviceid += F(":00:11-"); - deviceid += 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 = Decompress(HUE_DESCRIPTION_XML_COMPRESSED,HUE_DESCRIPTION_XML_SIZE); - 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; - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; - } -#endif - - if (light_type) { - light_state.getHSB(&hue, &sat, nullptr); - if (sat > 254) sat = 254; - hue = changeUIntScale(hue, 0, 360, 0, 65535); - - if ((sat != prev_sat) || (hue != prev_hue)) { - 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; } - } - - const size_t buf_size = 256; - char * buf = (char*) malloc(buf_size); - - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (power & (1 << (device-1))) ? "true" : "false"); - - if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { - snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); - } - if (LST_COLDWARM <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, g_gotct ? "ct" : "hs"); - } - if (LST_RGB <= local_light_subtype) { - if (prev_x_str[0] && prev_y_str[0]) { - snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, prev_x_str, prev_y_str); - } else { - float x, y; - light_state.getXY(&x, &y); - snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, String(x, 5).c_str(), String(y, 5).c_str()); - } - snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue, sat); - } - if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); - } - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX, buf); - - *response += buf; - free(buf); -} - - - -bool HueActive(uint8_t device) { - if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } - return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); -} - -void HueLightStatus2(uint8_t device, String *response) -{ - const size_t buf_size = 300; - char * buf = (char*) malloc(buf_size); - const size_t max_name_len = 32; - char fname[max_name_len + 1]; - - strlcpy(fname, SettingsText(device <= MAX_FRIENDLYNAMES ? SET_FRIENDLYNAME1 + device -1 : SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1), max_name_len + 1); - - if (device > MAX_FRIENDLYNAMES) { - uint32_t fname_len = strlen(fname); - if (fname_len > max_name_len - 2) { fname_len = max_name_len - 2; } - fname[fname_len++] = '-'; - 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; - } - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2, - EscapeJSONString(fname).c_str(), - EscapeJSONString(Settings.user_template_name).c_str(), - PSTR("Tasmota"), - GetHueDeviceId(device).c_str()); - *response += buf; - free(buf); -} - - - - - -#ifndef USE_ZIGBEE -uint32_t EncodeLightId(uint8_t relay_id) -#else -uint32_t EncodeLightId(uint8_t relay_id, uint16_t z_shortaddr = 0) -#endif -{ - uint8_t mac[6]; - WiFi.macAddress(mac); - uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4); - - if (relay_id >= 32) { - relay_id = 0; - } - if (relay_id > 15) { - id |= (1 << 28); - } - id |= (relay_id & 0xF); -#ifdef USE_ZIGBEE - if ((z_shortaddr) && (!relay_id)) { - - id = (1 << 29) | z_shortaddr; - } -#endif - - return id; -} - - - - - - - -#ifndef USE_ZIGBEE -uint32_t DecodeLightId(uint32_t hue_id) -#else -uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr) -#endif -{ - uint8_t relay_id = hue_id & 0xF; - if (hue_id & (1 << 28)) { - relay_id += 16; - } - if (0 == relay_id) { - relay_id = 32; - } -#ifdef USE_ZIGBEE - if (hue_id & (1 << 29)) { - - if (shortaddr) { *shortaddr = hue_id & 0xFFFF; } - relay_id = 0; - } -#endif - return relay_id; -} - - -inline uint32_t findEchoGeneration(void) { - - return Settings.flag4.alexa_gen_1 ? 1 : 2; -} - -void HueGlobalConfig(String *path) { - String response; - - path->remove(0,1); - response = F("{\"lights\":{"); - bool appending = false; - CheckHue(&response, appending); -#ifdef USE_ZIGBEE - ZigbeeCheckHue(&response, appending); -#endif - 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); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Authentication Result (%s)"), response); -} - - -void CheckHue(String * response, bool &appending) { - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - for (uint32_t i = 1; i <= maxhue; i++) { - if (HueActive(i)) { - if (appending) { *response += ","; } - *response += "\""; - *response += EncodeLightId(i); - *response += F("\":{\"state\":"); - HueLightStatus1(i, response); - HueLightStatus2(i, response); - appending = true; - } - } -} - -void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool on = false; - bool resp = false; - bool change = false; - uint8_t local_light_subtype = getLocalLightSubtype(device); - - const size_t buf_size = 100; - char * buf = (char*) malloc(buf_size); - - if (Webserver->args()) { - response = "["; - - JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); - JsonParserObject root = parser.getRootObject(); - - JsonParserToken hue_on = root[PSTR("on")]; - if (hue_on) { - on = hue_on.getBool(); - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"), - device_id, on ? "true" : "false"); - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - if (!change) { - bri = on ? 1.0f : 0.0f; - change = true; - resp = true; - response += buf; - } - } else { -#endif - ExecuteCommandPower(device, (on) ? POWER_ON : POWER_OFF, SRC_HUE); - response += buf; - resp = true; -#ifdef USE_SHUTTER - } -#endif - } - - 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; - - parser.setCurrent(); - JsonParserToken hue_bri = root[PSTR("bri")]; - if (hue_bri) { - bri = hue_bri.getUInt(); - prev_bri = bri; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "bri", bri); - response += buf; - if (LST_SINGLE <= Light.subtype) { - - if (254 <= bri) { bri = 255; } - change = true; - } - resp = true; - } - - - - parser.setCurrent(); - JsonParserToken hue_xy = root[PSTR("xy")]; - if (hue_xy) { - JsonParserArray arr_xy = JsonParserArray(hue_xy); - JsonParserToken tok_x = arr_xy[0]; - JsonParserToken tok_y = arr_xy[1]; - float x = tok_x.getFloat(); - float y = tok_y.getFloat(); - strlcpy(prev_x_str, tok_x.getStr(), sizeof(prev_x_str)); - strlcpy(prev_y_str, tok_y.getStr(), 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, 360, 0, 65535); - prev_sat = (sat > 254 ? 254 : sat); - - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/xy\":[%s,%s]}}"), - device_id, prev_x_str, prev_y_str); - response += buf; - g_gotct = false; - resp = true; - change = true; - } - - parser.setCurrent(); - JsonParserToken hue_hue = root[PSTR("hue")]; - if (hue_hue) { - hue = hue_hue.getUInt(); - prev_hue = hue; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "hue", hue); - response += buf; - if (LST_RGB <= Light.subtype) { - - hue = changeUIntScale(hue, 0, 65535, 0, 360); - g_gotct = false; - change = true; - } - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_sat = root[PSTR("sat")]; - if (hue_sat) { - sat = hue_sat.getUInt(); - prev_sat = sat; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "sat", sat); - response += buf; - if (LST_RGB <= Light.subtype) { - - if (254 <= sat) { sat = 255; } - g_gotct = false; - change = true; - } - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_ct = root[PSTR("ct")]; - if (hue_ct) { - ct = hue_ct.getUInt(); - prev_ct = ct; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "ct", ct); - response += buf; - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - g_gotct = true; - change = true; - } - resp = true; - } - - if (change) { -#ifdef USE_SHUTTER - if (ShutterState(device)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); - ShutterSetPosition(device, bri * 100.0f ); - } else -#endif - 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); - } - free(buf); -} - -void HueLights(String *path) -{ - - - - String response; - int code = 200; - uint8_t device = 1; - uint32_t device_id; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,path->indexOf(F("/lights"))); - if (path->endsWith(F("/lights"))) { - response = "{"; - bool appending = false; - CheckHue(&response, appending); -#ifdef USE_ZIGBEE - ZigbeeCheckHue(&response, appending); -#endif -#ifdef USE_SCRIPT_HUE - Script_Check_Hue(&response); -#endif - response += "}"; - } - else if (path->endsWith(F("/state"))) { - path->remove(0,8); - path->remove(path->indexOf(F("/state"))); - device_id = atoi(path->c_str()); - device = DecodeLightId(device_id); -#ifdef USE_ZIGBEE - uint16_t shortaddr; - device = DecodeLightId(device_id, &shortaddr); - if (shortaddr) { - return ZigbeeHandleHue(shortaddr, device_id, response); - } -#endif - -#ifdef USE_SCRIPT_HUE - if (device > devices_present) { - return Script_Handle_Hue(path); - } -#endif - if ((device >= 1) || (device <= maxhue)) { - HueLightsCommand(device, device_id, response); - } - - } - else if(path->indexOf(F("/lights/")) >= 0) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("/lights path=%s"), path->c_str()); - path->remove(0,8); - device_id = atoi(path->c_str()); - device = DecodeLightId(device_id); -#ifdef USE_ZIGBEE - uint16_t shortaddr; - device = DecodeLightId(device_id, &shortaddr); - if (shortaddr) { - ZigbeeHueStatus(&response, shortaddr); - goto exit; - } -#endif - -#ifdef USE_SCRIPT_HUE - 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); -} - -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 += "\""; - } - -#ifdef USE_ZIGBEE - ZigbeeHueGroups(&response); -#endif - response.replace("{l1", lights); - HueLightStatus1(1, &response); - response += F("}"); - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups Result (%s)"), path->c_str()); - WSSend(200, CT_JSON, response); -} - -void HandleHueApi(String *path) -{ -# 861 "/workspace/Tasmota/tasmota/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) from %s"), path->c_str(), Webserver->client().remoteIP().toString().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(F("/invalid/"))) {} - else if (!apilen) HueAuthentication(path); - else if (path->endsWith(F("/"))) HueAuthentication(path); - else if (path->endsWith(F("/config"))) HueConfig(path); - else if (path->indexOf(F("/lights")) >= 0) HueLights(path); - else if (path->indexOf(F("/groups")) >= 0) HueGroups(path); - else if (path->endsWith(F("/schedules"))) HueNotImplemented(path); - else if (path->endsWith(F("/sensors"))) HueNotImplemented(path); - else if (path->endsWith(F("/scenes"))) HueNotImplemented(path); - else if (path->endsWith(F("/rules"))) HueNotImplemented(path); - else if (path->endsWith(F("/resourcelinks"))) HueNotImplemented(path); - else HueGlobalConfig(path); -} - - - - - -bool Xdrv20(uint8_t function) -{ - bool result = false; - -#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) - 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(PSTR("/description.xml"), HandleUpnpSetupHue); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_21_wemo.ino" -# 20 "/workspace/Tasmota/tasmota/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)); - } - - PrepLog_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; -} - - - - - -#ifdef USE_UNISHOX_COMPRESSION - - - -const size_t WEMO_EVENTSERVICE_XML_SIZE = 779; -const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" - "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0A\xC3\xAD\xCE\x20\xB7\xD4\x08" - "\x72\x0F\xC3\xD3\xAC\x6B\x3F\x0B\xCE\x88\x76\xF5\xFC\xC8\xBD\x57\x4C\xF4\x3B\x3A" - "\xC6\xB3\xF0\xF4\xBF\x8F\x0B\x1A\xFA\x81\x0B\x0D\x04\x29\x47\xE1\xE9\xF7\x46\x76" - "\x11\xD8\x08\x58\xC0\x27\x62\xBF\x61\x5D\x31\x0B\xD5\x74\xC8\xCE\xFF\xB6\x38\x20" - "\x4A\xC1\x01\x42\xF1\xE8\x26\xFD\x82\x0E\xE7\xBC\x7A\x1D\x80\x8B\x28\xF4\x3B\x01" - "\x17\x59\x04\x48\xE0\x83\xB9\x1D\x80\x87\xC1\x20\x24\x70\x58\x43\xC0\xDA\xF8\x2C" - "\xC1\x74\x0C\x2F\x82\xD0\x42\x8A\x08\x34\x81\x0B\x92\x42\xF5\x5D\x32\xA0\x41\xCE" - "\x7C\x08\xFA\x42\xF3\xE1\x09\x99\xBE\xAF\x1F\x0F\x61\x93\xF1\xEC\x05\x5E\x0A\x44" - "\xBA\xB2\xA3\x21\x8C\xFC\x1D\x98\x11\xE8\x76\x02\x24\xB3\xD0\x46\x62\xC5\x85\x44" - "\x67\x61\x0B\x67\xE1\xC6\x7A\x1D\x84\x09\x13\x0F\x43\xB0\x12\x34\xC0\x60\x5A\xD8" - "\x4C\xCD\x84\x09\x9A\xAF\xAB\xFB\xC3\xC0\xC5\x75\x73\xB0\x13\xB8\x6A\x3B\x3C\x18" - "\xC1\x0F\xC9\xC2\x91\xBA\x70\xA4\x6E"; - - - -const size_t WEMO_METASERVICE_XML_SIZE = 479; -const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" - "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0B\xC3\x18\x64\x66\xFF\xED\xCE" - "\x3F\x0F\x41\xB6\x6B\xCF\x9F\x87\x21\xE8\x76\x10\x20\xC5\x3D\x06\xEF\x67\xCF\xC3" - "\x8C\xF4\x3B\x08\x10\x62\x9E\x87\x60\x24\x61\x56\x1D\x6E\x71\x05\xBE\xA0\x43\x90" - "\x7E\x1E\x9D\x63\x59\xF8\x43\xCE\x88\x6B\xAB\x2D\xE3\x18\x7A\x1D\x9D\x63\x59\xF8" - "\x7A\x5F\xC7\x85\x8D\x7D\x40\x83\x85\x7D\xD1\x9D\x84\x8E\xC0\x55\xC3\x3E\xC2\xBA" - "\x62\x17\xAA\xE9\x91\x9D\xFF\x6C\x70\x4C\xFC\x04\x5C\x04\x14\x2D\x9E\x82\x6F\xD8" - "\x20\xEC\x9B\xC7\xA1\xD8\x08\xB2\x8F\x43\xB0\x12\x75\xB3\xB0\x10\xF8\x0A\x04\x28" - "\xA0\x83\x48\x10\xB8\x74\x2F\x55\xD3\x2A\x2B\x04\x1C\xB7\xC0\x8F\x9E\x2F\x3E\x10" - "\x99\x9B\xEA\xF1\xF0\xF6\x19\x3F\x1E\xC0\x42\xE0\x68\x12\xF8\x17\x12\xEA\xCA\x8C" - "\x86\x33\xF3\xD5\xFD\xE1\xE3\xD0\xEC\x04\x49\xA7\xA0\x8C\xC5\x8B\x0A\x88\xCE\xC2" - "\x16\xCF\xC3\x8C\xF4\x3B\x08\x12\x26\x1E\x87\x60\x24\x69\x67\xE1\xE8\x76\x02\x76" - "\xDC\x76\x78\x31\x82\x1F\x93\x85\x23\x74\xE1\x48\xDC"; - - - -const size_t WEMO_RESPONSE_STATE_SOAP_SIZE = 282; -const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0C\x68\xD8\x34\x2E\xF1\xE7\xE3\xE1\xEC\x15\x54\x30" - "\xF3\x3B\x0E\xCF\x06\x29\x8D\xBF\x1D\x0D\x83\x42\xF6\x58\xC3\xA6\x7C\x78\xEC\xF6" - "\x58\xC3\xB1\x82\x16\x1C\x76\x1E\xC5\xE3\xCD\xF0\x78\x26\xF0\xF1\x7A\x8C\x82\x60" - "\xBF\x8C\x02\x0E\x16\x76\x1E\xC3\xF0\xF4\xF1\xE6\x43\xB0\x43\x23\xF0\xF4\x16\x79" - "\x9F\x41\xBA\x21\xDB\xD7\xF3\x22\xF5\x5D\x32\xFB\xF0\xCC\xEF\x02\x1E\xDE\x2C\xF8" - "\x7B\x05\xFF\x8F\x32\x1C\xC2\x34\xDE\x3C\xFC\xFE\x67\xA1\xB3\xCC\x75\xFB\x43\x66" - "\x6F\xA8\xF3\x39\x0F\x61\xF8\x7A\x10\x23\x63\x67\xE1\xF4\x21\xE8\x76\x02\x3C\xC3" - "\xD0\xEC\x05\x4C\xFC\xFC\x3D\x0E\xC0\x43\xD8\xCE\xC0\x45\xE1\xA0\xFC\x9C\x29\x1B" - "\x8D"; - - - -const size_t WEMO_SETUP_XML_SIZE = 923; -const char WEMO_SETUP_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" - "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\x21\xCC\x23\x4D\xE3\xCC\x46" - "\x67\xA1\xB3\xAC\xE4\x3A\xD9\xEC\x3F\x0F\x42\x04\x19\x20\x87\x10\xA8\xC8\x63\x3F" - "\x01\x33\x07\x3C\xC3\xCE\xAF\xE0\x41\x36\x79\x9C\x87\xA1\xD8\x40\x8D\x83\x9E\x86" - "\x3F\xAF\x84\x08\xC8\xBA\xC6\xB3\xF0\xF6\x9B\x0E\x43\xD0\xEC\x20\x48\x9C\x7A\x0D" - "\xBE\x16\x62\xC3\xA1\x7F\x7F\x3F\x01\x07\x31\x45\xBD\x4F\xFD\x75\xB9\xD6\x12\x2D" - "\xE0\xCE\x87\xA1\xD8\x09\x18\x21\xE8\x37\x04\x61\x17\x58\xD6\x7E\x17\xB0\x33\x47" - "\x47\xA1\xD8\x08\xB3\x81\x0A\xC8\xB1\xA3\x9F\xCF\xC3\x96\x74\x99\x34\x81\x0E\xD8" - "\x20\xD0\x3D\x08\x59\x08\x5C\x7E\x0B\x17\xA2\x1E\x67\xB4\xD8\x72\x8F\x43\xB0\x88" - "\x59\x08\x5C\x7E\x1E\x9E\x7F\xDB\x04\x3B\xA7\xB4\xD8\x72\xCF\x43\xB0\x81\x22\x71" - "\xE8\x3B\x7A\xFE\x64\x5E\xAB\xA6\x7E\x1C\x67\xA1\xD8\x40\x8F\x2C\xF4\xF3\xF9\x9E" - "\x86\xC8\x2D\xF5\x02\x24\x90\x44\x8A\x09\x7C\x46\x82\x15\x33\xCC\x75\xFB\x43\x66" - "\x6F\xA8\xF3\x39\x0F\x43\xB0\x81\x1F\x09\x04\x3C\x58\xB4\x40\x4E\xC5\x0B\x44\x04" - "\x6C\x58\x11\x71\x52\xD1\x0F\xC3\xD0\x10\xB8\xE0\x21\x65\xF2\x08\xFC\x3B\x05\x8C" - "\xE1\x87\x60\x21\x4D\x3B\x01\x23\x0D\x04\x6C\x08\xF4\x66\x6F\xA8\xBC\x2C\x70\x22" - "\xE1\xEC\xCD\xF5\x02\x4E\x1A\x08\xF8\x09\xE8\x45\xE0\xC6\x08\x2F\xE1\x11\xF8\x08" - "\x34\x81\x0B\x59\x3A\x1B\x06\x84\x7A\x1D\x80\x87\x5C\x11\x37\x2A\x01\x60\xBC\x34" - "\x0D\x75\x7B\xC6\x30\x18\x5F\x0C\xC0\x87\x8A\x03\x02\xE1\x90\x11\xB0\xB0\x5F\xE1" - "\x88\x11\xB0\xB0\x51\xE1\x80\x10\xEE\x82\xDF\x0C\x60\x87\x18\x10\x79\x7D\x04\x2E" - "\x83\xD1\xF8\x7A\x1D\x9F\xCC\xA3\xF2\x70\xA4\x6E"; -#else -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"; -#endif - - - -void LogUpnpWithClient(const char *msg) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "%s from %s"), msg, Webserver->client().remoteIP().toString().c_str()); -} - -void HandleUpnpEvent(void) -{ - LogUpnpWithClient(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>10> 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((action) ? action : 1, (action) ? 1 : 4); -#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(4, 1); -#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) { return false; } - - 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) { -# 177 "/workspace/Tasmota/tasmota/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) { - SetSerial(9600, TS_SERIAL_8N1); - } - 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 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -#ifdef USE_ZIGBEE - -#if defined(USE_ZIGBEE_ZNP) && defined(USE_ZIGBEE_EZSP) - #error "#define USE_ZIGBEE_ZNP and #define USE_ZIGBEE_EZSP are mutually incompatible" -#endif -#if !defined(USE_ZIGBEE_ZNP) && !defined(USE_ZIGBEE_EZSP) - #error "You must select one of: #define USE_ZIGBEE_ZNP or #define USE_ZIGBEE_EZSP" -#endif - - - -#define OCCUPANCY "Occupancy" -#define ZIGBEE_EZSP_RESET_LED 4 - -typedef uint64_t Z_IEEEAddress; -typedef uint16_t Z_ShortAddress; - -const uint16_t BAD_SHORTADDR = 0xFFFE; - -#ifdef USE_ZIGBEE_ZNP -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 -}; -#endif - -#ifdef USE_ZIGBEE_EZSP - -enum EZSPNodeType { - EMBER_UNKNOWN_DEVICE = 0x00, - EMBER_COORDINATOR = 0x01, - EMBER_ROUTER = 0x02, - EMBER_END_DEVICE = 0x03, - EMBER_SLEEPY_END_DEVICE = 0x04 -}; - -enum EZSPDeviceUpdate { - EMBER_STANDARD_SECURITY_SECURED_REJOIN = 0x00, - EMBER_STANDARD_SECURITY_UNSECURED_JOIN = 0x01, - EMBER_DEVICE_LEFT = 0x02, - EMBER_STANDARD_SECURITY_UNSECURED_REJOIN = 0x03, -}; - -enum EZSPJoinDecision { - EMBER_USE_PRECONFIGURED_KEY = 0x00, - EMBER_SEND_KEY_IN_THE_CLEAR = 0x01, - EMBER_DENY_JOIN = 0x02, - EMBER_NO_ACTION = 0x03 -}; - -enum EZSPCurrentSecurytBitMask { - EMBER_STANDARD_SECURITY_MODE = 0x0000, - EMBER_DISTRIBUTED_TRUST_CENTER_MODE = 0x0002, - EMBER_GLOBAL_LINK_KEY = 0x0004, - EMBER_TRUST_CENTER_GLOBAL_LINK_KEY = 0x0004, - EMBER_PRECONFIGURED_NETWORK_KEY_MODE = 0x0008, - EMBER_HAVE_TRUST_CENTER_LINK_KEY = 0x0010, - EMBER_TRUST_CENTER_USES_HASHED_LINK_KEY = 0x0084, - EMBER_HAVE_PRECONFIGURED_KEY = 0x0100, - EMBER_HAVE_NETWORK_KEY = 0x0200, - EMBER_GET_LINK_KEY_WHEN_JOINING = 0x0400, - EMBER_REQUIRE_ENCRYPTED_KEY = 0x0800, - EMBER_NO_FRAME_COUNTER_RESET = 0x1000, - EMBER_GET_PRECONFIGURED_KEY_FROM_INSTALL_CODE = 0x2000, - EMBER_HAVE_TRUST_CENTER_EUI64 = 0x0040 -}; - -enum EZSPJoinMethod { - EMBER_USE_MAC_ASSOCIATION = 0x0, - EMBER_USE_NWK_REJOIN = 0x1, - EMBER_USE_NWK_REJOIN_HAVE_NWK_KEY = 0x2, - EMBER_USE_CONFIGURED_NWK_STATE = 0x3 -}; - -enum EZSPConfigId { - EZSP_CONFIG_PACKET_BUFFER_COUNT = 0x01, - EZSP_CONFIG_NEIGHBOR_TABLE_SIZE = 0x02, - EZSP_CONFIG_APS_UNICAST_MESSAGE_COUNT = 0x03, - EZSP_CONFIG_BINDING_TABLE_SIZE = 0x04, - EZSP_CONFIG_ADDRESS_TABLE_SIZE = 0x05, - EZSP_CONFIG_MULTICAST_TABLE_SIZE = 0x06, - EZSP_CONFIG_ROUTE_TABLE_SIZE = 0x07, - EZSP_CONFIG_DISCOVERY_TABLE_SIZE = 0x08, - EZSP_CONFIG_STACK_PROFILE = 0x0C, - EZSP_CONFIG_SECURITY_LEVEL = 0x0D, - EZSP_CONFIG_MAX_HOPS = 0x10, - EZSP_CONFIG_MAX_END_DEVICE_CHILDREN = 0x11, - EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT = 0x12, - EZSP_CONFIG_END_DEVICE_POLL_TIMEOUT = 0x13, - EZSP_CONFIG_TX_POWER_MODE = 0x17, - EZSP_CONFIG_DISABLE_RELAY = 0x18, - EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE = 0x19, - EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE = 0x1A, - EZSP_CONFIG_FRAGMENT_WINDOW_SIZE = 0x1C, - EZSP_CONFIG_FRAGMENT_DELAY_MS = 0x1D, - EZSP_CONFIG_KEY_TABLE_SIZE = 0x1E, - EZSP_CONFIG_APS_ACK_TIMEOUT = 0x1F, - EZSP_CONFIG_BEACON_JITTER_DURATION = 0x20, - EZSP_CONFIG_END_DEVICE_BIND_TIMEOUT = 0x21, - EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD = 0x22, - EZSP_CONFIG_REQUEST_KEY_TIMEOUT = 0x24, - EZSP_CONFIG_CERTIFICATE_TABLE_SIZE = 0x29, - EZSP_CONFIG_APPLICATION_ZDO_FLAGS = 0x2A, - EZSP_CONFIG_BROADCAST_TABLE_SIZE = 0x2B, - EZSP_CONFIG_MAC_FILTER_TABLE_SIZE = 0x2C, - EZSP_CONFIG_SUPPORTED_NETWORKS = 0x2D, - EZSP_CONFIG_SEND_MULTICASTS_TO_SLEEPY_ADDRESS = 0x2E, - EZSP_CONFIG_ZLL_GROUP_ADDRESSES = 0x2F, - EZSP_CONFIG_ZLL_RSSI_THRESHOLD = 0x30, - EZSP_CONFIG_MTORR_FLOW_CONTROL = 0x33, - EZSP_CONFIG_RETRY_QUEUE_SIZE = 0x34, - EZSP_CONFIG_NEW_BROADCAST_ENTRY_THRESHOLD = 0x35, - EZSP_CONFIG_BROADCAST_MIN_ACKS_NEEDED = 0x37, - EZSP_CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S = 0x38, - EZSP_CONFIG_CTUNE_VALUE = 0x39 -}; - -enum EZSPValueId { - EZSP_VALUE_TOKEN_STACK_NODE_DATA = 0x00, - EZSP_VALUE_MAC_PASSTHROUGH_FLAGS = 0x01, - EZSP_VALUE_EMBERNET_PASSTHROUGH_SOURCE_ADDRESS = 0x02, - EZSP_VALUE_FREE_BUFFERS = 0x03, - EZSP_VALUE_UART_SYNCH_CALLBACKS = 0x04, - EZSP_VALUE_MAXIMUM_INCOMING_TRANSFER_SIZE = 0x05, - EZSP_VALUE_MAXIMUM_OUTGOING_TRANSFER_SIZE = 0x06, - EZSP_VALUE_STACK_TOKEN_WRITING = 0x07, - EZSP_VALUE_STACK_IS_PERFORMING_REJOIN = 0x08, - EZSP_VALUE_MAC_FILTER_LIST = 0x09, - EZSP_VALUE_EXTENDED_SECURITY_BITMASK = 0x0A, - EZSP_VALUE_NODE_SHORT_ID = 0x0B, - EZSP_VALUE_DESCRIPTOR_CAPABILITY = 0x0C, - EZSP_VALUE_STACK_DEVICE_REQUEST_SEQUENCE_NUMBER = 0x0D, - EZSP_VALUE_RADIO_HOLD_OFF = 0x0E, - EZSP_VALUE_ENDPOINT_FLAGS = 0x0F, - EZSP_VALUE_MFG_SECURITY_CONFIG = 0x10, - EZSP_VALUE_VERSION_INFO = 0x11, - EZSP_VALUE_NEXT_HOST_REJOIN_REASON = 0x12, - EZSP_VALUE_LAST_REJOIN_REASON = 0x13, - EZSP_VALUE_NEXT_ZIGBEE_SEQUENCE_NUMBER = 0x14, - EZSP_VALUE_CCA_THRESHOLD = 0x15, - EZSP_VALUE_SET_COUNTER_THRESHOLD = 0x17, - EZSP_VALUE_RESET_COUNTER_THRESHOLDS = 0x18, - EZSP_VALUE_CLEAR_COUNTERS = 0x19, - EZSP_VALUE_CERTIFICATE_283K1 = 0x1A, - EZSP_VALUE_PUBLIC_KEY_283K1 = 0x1B, - EZSP_VALUE_PRIVATE_KEY_283K1 = 0x1C, - EZSP_VALUE_NWK_FRAME_COUNTER = 0x23, - EZSP_VALUE_APS_FRAME_COUNTER = 0x24, - EZSP_VALUE_RETRY_DEVICE_TYPE = 0x25, - EZSP_VALUE_ENABLE_R21_BEHAVIOR = 0x29, - EZSP_VALUE_ANTENNA_MODE = 0x30, - EZSP_VALUE_ENABLE_PTA = 0x31, - EZSP_VALUE_PTA_OPTIONS = 0x32, - EZSP_VALUE_MFGLIB_OPTIONS = 0x33, - EZSP_VALUE_USE_NEGOTIATED_POWER_BY_LPD = 0x34, - EZSP_VALUE_PTA_PWM_OPTIONS = 0x35, - EZSP_VALUE_PTA_DIRECTIONAL_PRIORITY_PULSE_WIDTH = 0x36, - EZSP_VALUE_PTA_PHY_SELECT_TIMEOUT = 0x37, - EZSP_VALUE_ANTENNA_RX_MODE = 0x38, - EZSP_VALUE_NWK_KEY_TIMEOUT = 0x39, - EZSP_VALUE_FORCE_TX_AFTER_FAILED_CCA_ATTEMPTS = 0x3A, - EZSP_VALUE_TRANSIENT_KEY_TIMEOUT_S = 0x3B, - ZSP_VALUE_COULOMB_COUNTER_USAGE = 0x3C, - EZSP_VALUE_MAX_BEACONS_TO_STORE = 0x3D, - EZSP_VALUE_END_DEVICE_TIMEOUT_OPTIONS_MASK = 0x3E, - EZSP_VALUE_END_DEVICE_KEEP_ALIVE_SUPPORT_MODE = 0x3F, - EZSP_VALUE_GPIO_RADIO_POWER_MASK = 0x40, - EZSP_VALUE_ACTIVE_RADIO_CONFIG = 0x41 -}; - -enum EZSPEmberStatusId { - EMBER_SUCCESS = 0x00, - EMBER_ERR_FATAL = 0x01, - EMBER_BAD_ARGUMENT = 0x02, - EMBER_EEPROM_MFG_STACK_VERSION_MISMATCH = 0x04, - EMBER_INCOMPATIBLE_STATIC_MEMORY_DEFINITIONS = 0x05, - EMBER_EEPROM_MFG_VERSION_MISMATCH = 0x06, - EMBER_EEPROM_STACK_VERSION_MISMATCH = 0x07, - EMBER_NO_BUFFERS = 0x18, - EMBER_SERIAL_INVALID_BAUD_RATE = 0x20, - EMBER_SERIAL_INVALID_PORT = 0x21, - EMBER_SERIAL_TX_OVERFLOW = 0x22, - EMBER_SERIAL_RX_OVERFLOW = 0x23, - EMBER_SERIAL_RX_FRAME_ERROR = 0x24, - EMBER_SERIAL_RX_PARITY_ERROR = 0x25, - EMBER_SERIAL_RX_EMPTY = 0x26, - EMBER_SERIAL_RX_OVERRUN_ERROR = 0x27, - EMBER_MAC_TRANSMIT_QUEUE_FULL = 0x39, - EMBER_MAC_UNKNOWN_HEADER_TYPE = 0x3A, - EMBER_MAC_SCANNING = 0x3D, - EMBER_MAC_NO_DATA = 0x31, - EMBER_MAC_JOINED_NETWORK = 0x32, - EMBER_MAC_BAD_SCAN_DURATION = 0x33, - EMBER_MAC_INCORRECT_SCAN_TYPE = 0x34, - EMBER_MAC_INVALID_CHANNEL_MASK = 0x35, - EMBER_MAC_COMMAND_TRANSMIT_FAILURE = 0x36, - EMBER_MAC_NO_ACK_RECEIVED = 0x40, - EMBER_MAC_INDIRECT_TIMEOUT = 0x42, - EMBER_SIM_EEPROM_ERASE_PAGE_GREEN = 0x43, - EMBER_SIM_EEPROM_ERASE_PAGE_RED = 0x44, - EMBER_SIM_EEPROM_FULL = 0x45, - EMBER_ERR_FLASH_WRITE_INHIBITED = 0x46, - EMBER_ERR_FLASH_VERIFY_FAILED = 0x47, - EMBER_SIM_EEPROM_INIT_1_FAILED = 0x48, - EMBER_SIM_EEPROM_INIT_2_FAILED = 0x49, - EMBER_SIM_EEPROM_INIT_3_FAILED = 0x4A, - EMBER_ERR_FLASH_PROG_FAIL = 0x4B, - EMBER_ERR_FLASH_ERASE_FAIL = 0x4C, - EMBER_ERR_BOOTLOADER_TRAP_TABLE_BAD = 0x58, - EMBER_ERR_BOOTLOADER_TRAP_UNKNOWN = 0x59, - EMBER_ERR_BOOTLOADER_NO_IMAGE = 0x5A, - EMBER_DELIVERY_FAILED = 0x66, - EMBER_BINDING_INDEX_OUT_OF_RANGE = 0x69, - EMBER_ADDRESS_TABLE_INDEX_OUT_OF_RANGE = 0x6A, - EMBER_INVALID_BINDING_INDEX = 0x6C, - EMBER_INVALID_CALL = 0x70, - EMBER_COST_NOT_KNOWN = 0x71, - EMBER_MAX_MESSAGE_LIMIT_REACHED = 0x72, - EMBER_MESSAGE_TOO_LONG = 0x74, - EMBER_BINDING_IS_ACTIVE = 0x75, - EMBER_ADDRESS_TABLE_ENTRY_IS_ACTIVE = 0x76, - EMBER_ADC_CONVERSION_DONE = 0x80, - EMBER_ADC_CONVERSION_BUSY = 0x81, - EMBER_ADC_CONVERSION_DEFERRED = 0x82, - EMBER_ADC_NO_CONVERSION_PENDING = 0x84, - EMBER_SLEEP_INTERRUPTED = 0x85, - EMBER_PHY_TX_UNDERFLOW = 0x88, - EMBER_PHY_TX_INCOMPLETE = 0x89, - EMBER_PHY_INVALID_CHANNEL = 0x8A, - EMBER_PHY_INVALID_POWER = 0x8B, - EMBER_PHY_TX_BUSY = 0x8C, - EMBER_PHY_TX_CCA_FAIL = 0x8D, - EMBER_PHY_OSCILLATOR_CHECK_FAILED = 0x8E, - EMBER_PHY_ACK_RECEIVED = 0x8F, - EMBER_NETWORK_UP = 0x90, - EMBER_NETWORK_DOWN = 0x91, - EMBER_JOIN_FAILED = 0x94, - EMBER_MOVE_FAILED = 0x96, - EMBER_CANNOT_JOIN_AS_ROUTER = 0x98, - EMBER_NODE_ID_CHANGED = 0x99, - EMBER_PAN_ID_CHANGED = 0x9A, - EMBER_NO_BEACONS = 0xAB, - EMBER_RECEIVED_KEY_IN_THE_CLEAR = 0xAC, - EMBER_NO_NETWORK_KEY_RECEIVED = 0xAD, - EMBER_NO_LINK_KEY_RECEIVED = 0xAE, - EMBER_PRECONFIGURED_KEY_REQUIRED = 0xAF, - EMBER_NOT_JOINED = 0x93, - EMBER_INVALID_SECURITY_LEVEL = 0x95, - EMBER_NETWORK_BUSY = 0xA1, - EMBER_INVALID_ENDPOINT = 0xA3, - EMBER_BINDING_HAS_CHANGED = 0xA4, - EMBER_INSUFFICIENT_RANDOM_DATA = 0xA5, - EMBER_APS_ENCRYPTION_ERROR = 0xA6, - EMBER_SECURITY_STATE_NOT_SET = 0xA8, - EMBER_KEY_TABLE_INVALID_ADDRESS = 0xB3, - EMBER_SECURITY_CONFIGURATION_INVALID = 0xB7, - EMBER_TOO_SOON_FOR_SWITCH_KEY = 0xB8, - EMBER_KEY_NOT_AUTHORIZED = 0xBB, - EMBER_SECURITY_DATA_INVALID = 0xBD, - EMBER_SOURCE_ROUTE_FAILURE = 0xA9, - EMBER_MANY_TO_ONE_ROUTE_FAILURE = 0xAA, - EMBER_STACK_AND_HARDWARE_MISMATCH = 0xB0, - EMBER_INDEX_OUT_OF_RANGE = 0xB1, - EMBER_TABLE_FULL = 0xB4, - EMBER_TABLE_ENTRY_ERASED = 0xB6, - EMBER_LIBRARY_NOT_PRESENT = 0xB5, - EMBER_OPERATION_IN_PROGRESS = 0xBA, -}; - -enum EZSPStatusId { - EZSP_SUCCESS = 0x00, - EZSP_SPI_ERR_FATAL = 0x10, - EZSP_SPI_ERR_NCP_RESET = 0x11, - EZSP_SPI_ERR_OVERSIZED_EZSP_FRAME = 0x12, - EZSP_SPI_ERR_ABORTED_TRANSACTION = 0x13, - EZSP_SPI_ERR_MISSING_FRAME_TERMINATOR = 0x14, - EZSP_SPI_ERR_WAIT_SECTION_TIMEOUT = 0x15, - EZSP_SPI_ERR_NO_FRAME_TERMINATOR = 0x16, - EZSP_SPI_ERR_EZSP_COMMAND_OVERSIZED = 0x17, - EZSP_SPI_ERR_EZSP_RESPONSE_OVERSIZED = 0x18, - EZSP_SPI_WAITING_FOR_RESPONSE = 0x19, - EZSP_SPI_ERR_HANDSHAKE_TIMEOUT = 0x1A, - EZSP_SPI_ERR_STARTUP_TIMEOUT = 0x1B, - EZSP_SPI_ERR_STARTUP_FAIL = 0x1C, - EZSP_SPI_ERR_UNSUPPORTED_SPI_COMMAND = 0x1D, - EZSP_ASH_IN_PROGRESS = 0x20, - EZSP_HOST_FATAL_ERROR = 0x21, - EZSP_ASH_NCP_FATAL_ERROR = 0x22, - EZSP_DATA_FRAME_TOO_LONG = 0x23, - EZSP_DATA_FRAME_TOO_SHORT = 0x24, - EZSP_NO_TX_SPACE = 0x25, - EZSP_NO_RX_SPACE = 0x26, - EZSP_NO_RX_DATA = 0x27, - EZSP_NOT_CONNECTED = 0x28, - EZSP_ERROR_VERSION_NOT_SET = 0x30, - EZSP_ERROR_INVALID_FRAME_ID = 0x31, - EZSP_ERROR_WRONG_DIRECTION = 0x32, - EZSP_ERROR_TRUNCATED = 0x33, - EZSP_ERROR_OVERFLOW = 0x34, - EZSP_ERROR_OUT_OF_MEMORY = 0x35, - EZSP_ERROR_INVALID_VALUE = 0x36, - EZSP_ERROR_INVALID_ID = 0x37, - EZSP_ERROR_INVALID_CALL = 0x38, - EZSP_ERROR_NO_RESPONSE = 0x39, - EZSP_ERROR_COMMAND_TOO_LONG = 0x40, - EZSP_ERROR_QUEUE_FULL = 0x41, - EZSP_ERROR_COMMAND_FILTERED = 0x42, - EZSP_ERROR_SECURITY_KEY_ALREADY_SET = 0x43, - EZSP_ERROR_SECURITY_TYPE_INVALID = 0x44, - EZSP_ERROR_SECURITY_PARAMETERS_INVALID = 0x45, - EZSP_ERROR_SECURITY_PARAMETERS_ALREADY_SET = 0x46, - EZSP_ERROR_SECURITY_KEY_NOT_SET = 0x47, - EZSP_ERROR_SECURITY_PARAMETERS_NOT_SET = 0x48, - EZSP_ERROR_UNSUPPORTED_CONTROL = 0x49, - EZSP_ERROR_UNSECURE_FRAME = 0x4A, - EZSP_NO_ERROR = 0xFF -}; - -enum EZSPPolicyId { - EZSP_TRUST_CENTER_POLICY = 0x00, - EZSP_BINDING_MODIFICATION_POLICY = 0x01, - EZSP_UNICAST_REPLIES_POLICY = 0x02, - EZSP_POLL_HANDLER_POLICY = 0x03, - EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY = 0x04, - EZSP_TC_KEY_REQUEST_POLICY = 0x05, - EZSP_APP_KEY_REQUEST_POLICY = 0x06, - EZSP_PACKET_VALIDATE_LIBRARY_POLICY = 0x07, - EZSP_ZLL_POLICY = 0x08, - EZSP_TC_REJOINS_USING_WELL_KNOWN_KEY_POLICY = 0x09 -}; - -enum EZSPDecisionBitmask { - EZSP_DECISION_BITMASK_DEFAULT_CONFIGURATION = 0x0000, - EZSP_DECISION_ALLOW_JOINS = 0x0001, - EZSP_DECISION_ALLOW_UNSECURED_REJOINS = 0x0002, - EZSP_DECISION_SEND_KEY_IN_CLEAR = 0x0004, - EZSP_DECISION_IGNORE_UNSECURED_REJOINS = 0x0008, - EZSP_DECISION_JOINS_USE_INSTALL_CODE_KEY = 0x0010, - EZSP_DECISION_DEFER_JOINS = 0x0020 -}; - -enum EZSPDecisionId { - EZSP_DEFER_JOINS_REJOINS_HAVE_LINK_KEY = 0x07, - EZSP_DISALLOW_BINDING_MODIFICATION = 0x10, - EZSP_ALLOW_BINDING_MODIFICATION = 0x11, - EZSP_CHECK_BINDING_MODIFICATIONS_ARE_VALID_ENDPOINT_CLUSTERS = 0x12, - EZSP_HOST_WILL_NOT_SUPPLY_REPLY = 0x20, - EZSP_HOST_WILL_SUPPLY_REPLY = 0x21, - EZSP_POLL_HANDLER_IGNORE = 0x30, - EZSP_POLL_HANDLER_CALLBACK = 0x31, - EZSP_MESSAGE_TAG_ONLY_IN_CALLBACK = 0x40, - EZSP_MESSAGE_TAG_AND_CONTENTS_IN_CALLBACK = 0x41, - EZSP_DENY_TC_KEY_REQUESTS = 0x50, - EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY = 0x51, - EZSP_ALLOW_TC_KEY_REQUEST_AND_GENERATE_NEW_KEY = 0x52, - EZSP_DENY_APP_KEY_REQUESTS = 0x60, - EZSP_ALLOW_APP_KEY_REQUESTS = 0x61, - EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_ENABLED = 0x62, - EZSP_PACKET_VALIDATE_LIBRARY_CHECKS_DISABLED = 0x63 -}; - -enum EZSP_ZdoConfigurationFlags { - EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS = 0x01, - EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS = 0x02, - EMBER_APP_HANDLES_ZDO_ENDPOINT_REQUESTS = 0x04, - EMBER_APP_HANDLES_ZDO_BINDING_REQUESTS = 0x08 -}; - -enum EZSP_EmberIncomingMessageType { - EMBER_INCOMING_UNICAST = 0x00, - EMBER_INCOMING_UNICAST_REPLY = 0x01, - EMBER_INCOMING_MULTICAST = 0x02, - EMBER_INCOMING_MULTICAST_LOOPBACK = 0x03, - EMBER_INCOMING_BROADCAST = 0x04, - EMBER_INCOMING_BROADCAST_LOOPBACK = 0x05, - EMBER_INCOMING_MANY_TO_ONE_ROUTE_REQUEST = 0x06 -}; - -enum EZSP_EmberApsOption { - EMBER_APS_OPTION_NONE = 0x0000, - EMBER_APS_OPTION_ENCRYPTION = 0x0020, - EMBER_APS_OPTION_RETRY = 0x0040, - EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY = 0x0100, - EMBER_APS_OPTION_FORCE_ROUTE_DISCOVERY = 0x0200, - EMBER_APS_OPTION_SOURCE_EUI64 = 0x0400, - EMBER_APS_OPTION_DESTINATION_EUI64 = 0x0800, - EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY = 0x1000, - EMBER_APS_OPTION_POLL_RESPONSE = 0x2000, - EMBER_APS_OPTION_ZDO_RESPONSE_REQUIRED = 0x4000, - EMBER_APS_OPTION_FRAGMENT = 0x8000 -}; - -enum EZSP_EmberOutgoingMessageType { - EMBER_OUTGOING_DIRECT = 0x00, - EMBER_OUTGOING_VIA_ADDRESS_TABLE = 0x01, - EMBER_OUTGOING_VIA_BINDING = 0x02, - EMBER_OUTGOING_MULTICAST = 0x03, - EMBER_OUTGOING_MULTICAST_WITH_ALIAS = 0x04, - EMBER_OUTGOING_BROADCAST_WITH_ALIAS = 0x05, - EMBER_OUTGOING_BROADCAST = 0x06 -}; - -enum EZSP_EmberKeyStructBitmask { - EMBER_KEY_HAS_SEQUENCE_NUMBER = 0x0001, - EMBER_KEY_HAS_OUTGOING_FRAME_COUNTER = 0x0002, - EMBER_KEY_HAS_INCOMING_FRAME_COUNTER = 0x0004, - EMBER_KEY_HAS_PARTNER_EUI64 = 0x0008, - EMBER_KEY_IS_AUTHORIZED = 0x0010, - EMBER_KEY_PARTNER_IS_SLEEPY = 0x0020, - EMBER_UNCONFIRMED_TRANSIENT_KEY = 0x0040 -}; - -enum EZSP_EmberKeyType { - EMBER_TRUST_CENTER_LINK_KEY = 1, - EMBER_CURRENT_NETWORK_KEY = 3, - EMBER_NEXT_NETWORK_KEY = 4, - EMBER_APPLICATION_LINK_KEY = 5 -}; - - -enum EZSP_ZDO { - ZDO_NWK_addr_req = 0x0000, - ZDO_IEEE_addr_req = 0x0001, - ZDO_Node_Desc_req = 0x0002, - ZDO_Power_Desc_req = 0x0003, - ZDO_Simple_Desc_req = 0x0004, - ZDO_Active_EP_req = 0x0005, - ZDO_Match_Desc_req = 0x0006, - ZDO_Complex_Desc_req = 0x0010, - ZDO_User_Desc_req = 0x0011, - ZDO_Discovery_Cache_req = 0x0012, - ZDO_Device_annce = 0x0013, - ZDO_User_Desc_set = 0x0014, - ZDO_System_Server_Discovery_req = 0x0015, - ZDO_Discovery_store_req = 0x0016, - ZDO_Node_Desc_store_req = 0x0017, - ZDO_Active_EP_store_req = 0x0019, - ZDO_Simple_Desc_store_req = 0x001A, - ZDO_Remove_node_cache_req = 0x001B, - ZDO_Find_node_cache_req = 0x001C, - ZDO_Extended_Simple_Desc_req = 0x001D, - ZDO_Extended_Active_EP_req = 0x001E, - ZDO_Parent_annce = 0x001F, - - ZDO_End_Device_Bind_req = 0x0020, - ZDO_Bind_req = 0x0021, - ZDO_Unbind_req = 0x0022, - - ZDO_Mgmt_Lqi_req = 0x0031, - ZDO_Mgmt_Rtg_req = 0x0032, - ZDO_Mgmt_Bind_req = 0x0033, - ZDO_Mgmt_Leave_req = 0x0034, - ZDO_Mgmt_Permit_Joining_req = 0x0036, - ZDO_Mgmt_NWK_Update_req = 0x0038, - - - - ZDO_NWK_addr_rsp = 0x8000, - ZDO_IEEE_addr_rsp = 0x8001, - ZDO_Node_Desc_rsp = 0x8002, - ZDO_Power_Desc_rsp = 0x8003, - ZDO_Simple_Desc_rsp = 0x8004, - ZDO_Active_EP_rsp = 0x8005, - ZDO_Match_Desc_rsp = 0x8006, - ZDO_Complex_Desc_rsp = 0x8010, - ZDO_User_Desc_rsp = 0x8011, - ZDO_Discovery_Cache_rsp = 0x8012, - ZDO_User_Desc_conf = 0x8014, - ZDO_System_Server_Discovery_rsp = 0x8015, - ZDO_Discovery_Store_rsp = 0x8016, - ZDO_Node_Desc_store_rsp = 0x8017, - ZDO_Power_Desc_store_rsp = 0x8018, - ZDO_Active_EP_store_rsp = 0x8019, - ZDO_Simple_Desc_store_rsp = 0x801A, - ZDO_Remove_node_cache_rsp = 0x801B, - ZDO_Find_node_cache_rsp = 0x801C, - ZDO_Extended_Simple_Desc_rsp = 0x801D, - ZDO_Extended_Active_EP_rsp = 0x801E, - ZDO_Parent_annce_rsp = 0x801F, - - ZDO_End_Device_Bind_rsp = 0x8020, - ZDO_Bind_rsp = 0x8021, - ZDO_Unbind_rsp = 0x8022, - - ZDO_Mgmt_Lqi_rsp = 0x8031, - ZDO_Mgmt_Rtg_rsp = 0x8032, - ZDO_Mgmt_Bind_rsp = 0x8033, - ZDO_Mgmt_Leave_rsp = 0x8034, - ZDO_Mgmt_Permit_Joining_rsp = 0x8036, - ZDO_Mgmt_NWK_Update_rsp = 0x8038, -}; - -enum EZSP_Commands { - EZSP_version = 0x0000, - EZSP_getLibraryStatus = 0x0001, - EZSP_addEndpoint = 0x0002, - EZSP_getExtendedValue = 0x0003, - EZSP_getNextBeacon = 0x0004, - EZSP_nop = 0x0005, - EZSP_callback = 0x0006, - EZSP_noCallbacks = 0x0007, - EZSP_getNumStoredBeacons = 0x0008, - EZSP_setToken = 0x0009, - EZSP_getToken = 0x000A, - EZSP_getMfgToken = 0x000B, - EZSP_setMfgToken = 0x000C, - EZSP_stackTokenChangedHandler = 0x000D, - EZSP_setTimer = 0x000E, - EZSP_timerHandler = 0x000F, - EZSP_setConcentrator = 0x0010, - EZSP_setBrokenRouteErrorCode = 0x0011, - EZSP_debugWrite = 0x0012, - EZSP_getXncpInfo = 0x0013, - EZSP_requestLinkKey = 0x0014, - EZSP_setManufacturerCode = 0x0015, - EZSP_setPowerDescriptor = 0x0016, - EZSP_networkInit = 0x0017, - EZSP_networkState = 0x0018, - EZSP_stackStatusHandler = 0x0019, - EZSP_startScan = 0x001A, - EZSP_networkFoundHandler = 0x001B, - EZSP_scanCompleteHandler = 0x001C, - EZSP_stopScan = 0x001D, - EZSP_formNetwork = 0x001E, - EZSP_joinNetwork = 0x001F, - EZSP_leaveNetwork = 0x0020, - EZSP_findAndRejoinNetwork = 0x0021, - EZSP_permitJoining = 0x0022, - EZSP_childJoinHandler = 0x0023, - EZSP_trustCenterJoinHandler = 0x0024, - EZSP_zllClearTokens = 0x0025, - EZSP_getEui64 = 0x0026, - EZSP_getNodeId = 0x0027, - EZSP_getNetworkParameters = 0x0028, - EZSP_getParentChildParameters = 0x0029, - EZSP_clearBindingTable = 0x002A, - EZSP_setBinding = 0x002B, - EZSP_getBinding = 0x002C, - EZSP_deleteBinding = 0x002D, - EZSP_bindingIsActive = 0x002E, - EZSP_getBindingRemoteNodeId = 0x002F, - EZSP_setBindingRemoteNodeId = 0x0030, - EZSP_remoteSetBindingHandler = 0x0031, - EZSP_remoteDeleteBindingHandler = 0x0032, - EZSP_maximumPayloadLength = 0x0033, - EZSP_sendUnicast = 0x0034, - EZSP_getDutyCycleState = 0x0035, - EZSP_sendBroadcast = 0x0036, - EZSP_proxyBroadcast = 0x0037, - EZSP_sendMulticast = 0x0038, - EZSP_sendReply = 0x0039, - EZSP_sendMulticastWithAlias = 0x003A, - EZSP_joinNetworkDirectly = 0x003B, - EZSP_clearStoredBeacons = 0x003C, - EZSP_getFirstBeacon = 0x003D, - EZSP_getNeighborFrameCounter = 0x003E, - EZSP_messageSentHandler = 0x003F, - EZSP_setDutyCycleLimitsInStack = 0x0040, - EZSP_sendManyToOneRouteRequest = 0x0041, - EZSP_pollForData = 0x0042, - EZSP_pollCompleteHandler = 0x0043, - EZSP_pollHandler = 0x0044, - EZSP_incomingMessageHandler = 0x0045, - EZSP_macFilterMatchMessageHandler = 0x0046, - EZSP_customFrame = 0x0047, - EZSP_energyScanResultHandler = 0x0048, - EZSP_getRandomNumber = 0x0049, - EZSP_getChildData = 0x004A, - EZSP_getDutyCycleLimits = 0x004B, - EZSP_getCurrentDutyCycle = 0x004C, - EZSP_dutyCycleHandler = 0x004D, - EZSP_getTimer = 0x004E, - EZSP_getTrueRandomEntropySource = 0x004F, - EZSP_unicastCurrentNetworkKey = 0x0050, - EZSP_sendRawMessageExtended = 0x0051, - EZSP_getConfigurationValue = 0x0052, - EZSP_setConfigurationValue = 0x0053, - EZSP_customFrameHandler = 0x0054, - EZSP_setPolicy = 0x0055, - EZSP_getPolicy = 0x0056, - EZSP_invalidCommand = 0x0058, - EZSP_setSourceRouteDiscoveryMode = 0x005A, - EZSP_addressTableEntryIsActive = 0x005B, - EZSP_setAddressTableRemoteEui64 = 0x005C, - EZSP_setAddressTableRemoteNodeId = 0x005D, - EZSP_getAddressTableRemoteEui64 = 0x005E, - EZSP_getAddressTableRemoteNodeId = 0x005F, - EZSP_lookupNodeIdByEui64 = 0x0060, - EZSP_lookupEui64ByNodeId = 0x0061, - EZSP_incomingSenderEui64Handler = 0x0062, - EZSP_getMulticastTableEntry = 0x0063, - EZSP_setMulticastTableEntry = 0x0064, - EZSP_readAndClearCounters = 0x0065, - EZSP_addOrUpdateKeyTableEntry = 0x0066, - EZSP_sendTrustCenterLinkKey = 0x0067, - EZSP_setInitialSecurityState = 0x0068, - EZSP_getCurrentSecurityState = 0x0069, - EZSP_getKey = 0x006A, - EZSP_clearTransientLinkKeys = 0x006B, - EZSP_updateTcLinkKey = 0x006C, - EZSP_getTransientKeyTableEntry = 0x006D, - EZSP_switchNetworkKeyHandler = 0x006E, - EZSP_aesMmoHash = 0x006F, - EZSP_gpSinkTableInit = 0x0070, - EZSP_getKeyTableEntry = 0x0071, - EZSP_setKeyTableEntry = 0x0072, - EZSP_broadcastNextNetworkKey = 0x0073, - EZSP_broadcastNetworkKeySwitch = 0x0074, - EZSP_findKeyTableEntry = 0x0075, - EZSP_eraseKeyTableEntry = 0x0076, - EZSP_becomeTrustCenter = 0x0077, - EZSP_dsaVerifyHandler = 0x0078, - EZSP_getNeighbor = 0x0079, - EZSP_neighborCount = 0x007A, - EZSP_getRouteTableEntry = 0x007B, - EZSP_idConflictHandler = 0x007C, - EZSP_incomingManyToOneRouteRequestHandler = 0x007D, - EZSP_setExtendedTimeout = 0x007E, - EZSP_getExtendedTimeout = 0x007F, - EZSP_incomingRouteErrorHandler = 0x0080, - EZSP_echo = 0x0081, - EZSP_replaceAddressTableEntry = 0x0082, - EZSP_mfglibStart = 0x0083, - EZSP_mfglibEnd = 0x0084, - EZSP_mfglibStartTone = 0x0085, - EZSP_mfglibStopTone = 0x0086, - EZSP_mfglibStartStream = 0x0087, - EZSP_mfglibStopStream = 0x0088, - EZSP_mfglibSendPacket = 0x0089, - EZSP_mfglibSetChannel = 0x008A, - EZSP_mfglibGetChannel = 0x008B, - EZSP_mfglibSetPower = 0x008C, - EZSP_mfglibGetPower = 0x008D, - EZSP_mfglibRxHandler = 0x008E, - EZSP_launchStandaloneBootloader = 0x008F, - EZSP_sendBootloadMessage = 0x0090, - EZSP_getStandaloneBootloaderVersionPlatMicroPhy = 0x0091, - EZSP_incomingBootloadMessageHandler = 0x0092, - EZSP_bootloadTransmitCompleteHandler = 0x0093, - EZSP_aesEncrypt = 0x0094, - EZSP_overrideCurrentChannel = 0x0095, - EZSP_sendRawMessage = 0x0096, - EZSP_macPassthroughMessageHandler = 0x0097, - EZSP_rawTransmitCompleteHandler = 0x0098, - EZSP_setRadioPower = 0x0099, - EZSP_setRadioChannel = 0x009A, - EZSP_zigbeeKeyEstablishmentHandler = 0x009B, - EZSP_energyScanRequest = 0x009C, - EZSP_delayTest = 0x009D, - EZSP_generateCbkeKeysHandler = 0x009E, - EZSP_calculateSmacs = 0x009F, - EZSP_calculateSmacsHandler = 0x00A0, - EZSP_clearTemporaryDataMaybeStoreLinkKey = 0x00A1, - EZSP_setPreinstalledCbkeData = 0x00A2, - EZSP_dsaVerify = 0x00A3, - EZSP_generateCbkeKeys = 0x00A4, - EZSP_getCertificate = 0x00A5, - EZSP_dsaSign = 0x00A6, - EZSP_dsaSignHandler = 0x00A7, - EZSP_removeDevice = 0x00A8, - EZSP_unicastNwkKeyUpdate = 0x00A9, - EZSP_getValue = 0x00AA, - EZSP_setValue = 0x00AB, - EZSP_setGpioCurrentConfiguration = 0x00AC, - EZSP_setGpioPowerUpDownConfiguration = 0x00AD, - EZSP_setGpioRadioPowerMask = 0x00AE, - EZSP_addTransientLinkKey = 0x00AF, - EZSP_dsaVerify283k1 = 0x00B0, - EZSP_clearKeyTable = 0x00B1, - EZSP_zllNetworkOps = 0x00B2, - EZSP_zllSetInitialSecurityState = 0x00B3, - EZSP_zllStartScan = 0x00B4, - EZSP_zllSetRxOnWhenIdle = 0x00B5, - EZSP_zllNetworkFoundHandler = 0x00B6, - EZSP_zllScanCompleteHandler = 0x00B7, - EZSP_zllAddressAssignmentHandler = 0x00B8, - EZSP_setLogicalAndRadioChannel = 0x00B9, - EZSP_getLogicalChannel = 0x00BA, - EZSP_zllTouchLinkTargetHandler = 0x00BB, - EZSP_zllGetTokens = 0x00BC, - EZSP_zllSetDataToken = 0x00BD, - EZSP_isZllNetwork = 0x00BE, - EZSP_zllSetNonZllNetwork = 0x00BF, - EZSP_gpProxyTableLookup = 0x00C0, - EZSP_getSourceRouteTableEntry = 0x00C1, - EZSP_getSourceRouteTableFilledSize = 0x00C2, - EZSP_getSourceRouteTableTotalSize = 0x00C3, - EZSP_gpepIncomingMessageHandler = 0x00C5, - EZSP_dGpSend = 0x00C6, - EZSP_dGpSentHandler = 0x00C7, - EZSP_gpProxyTableGetEntry = 0x00C8, - EZSP_gpProxyTableProcessGpPairing = 0x00C9, - EZSP_setSecurityKey = 0x00CA, - EZSP_setSecurityParameters = 0x00CB, - EZSP_resetToFactoryDefaults = 0x00CC, - EZSP_getSecurityKeyStatus = 0x00CD, - EZSP_getTransientLinkKey = 0x00CE, - EZSP_zllSetSecurityStateWithoutKey = 0x00CF, - EZSP_setRoutingShortcutThreshold = 0x00D0, - EZSP_getRoutingShortcutThreshold = 0x00D1, - EZSP_unusedPanIdFoundHandler = 0x00D2, - EZSP_findUnusedPanId = 0x00D3, - EZSP_zllSetRadioIdleMode = 0x00D4, - EZSP_setZllNodeType = 0x00D5, - EZSP_setZllAdditionalState = 0x00D6, - EZSP_zllOperationInProgress = 0x00D7, - EZSP_zllRxOnWhenIdleGetActive = 0x00D8, - EZSP_getZllPrimaryChannelMask = 0x00D9, - EZSP_getZllSecondaryChannelMask = 0x00DA, - EZSP_setZllPrimaryChannelMask = 0x00DB, - EZSP_setZllSecondaryChannelMask = 0x00DC, - EZSP_gpSinkTableGetEntry = 0x00DD, - EZSP_gpSinkTableLookup = 0x00DE, - EZSP_gpSinkTableSetEntry = 0x00DF, - EZSP_gpSinkTableRemoveEntry = 0x00E0, - EZSP_gpSinkTableFindOrAllocateEntry = 0x00E1, - EZSP_gpSinkTableClearAll = 0x00E2, - EZSP_setLongUpTime = 0x00E3, - EZSP_setHubConnectivity = 0x00E4, - EZSP_isUpTimeLong = 0x00E5, - EZSP_isHubConnected = 0x00E6, - EZSP_setParentClassificationEnabled = 0x00E7, - EZSP_generateCbkeKeys283k1 = 0x00E8, - EZSP_generateCbkeKeysHandler283k1 = 0x00E9, - EZSP_calculateSmacs283k1 = 0x00EA, - EZSP_calculateSmacsHandler283k1 = 0x00EB, - EZSP_getCertificate283k1 = 0x00EC, - EZSP_savePreinstalledCbkeData283k1 = 0x00ED, - EZSP_clearTemporaryDataMaybeStoreLinkKey283k1 = 0x00EE, - EZSP_setBeaconClassificationParams = 0x00EF, - EZSP_getParentClassificationEnabled = 0x00F0, - EZSP_readCounters = 0x00F1, - EZSP_counterRolloverHandler = 0x00F2, - EZSP_getBeaconClassificationParams = 0x00F3, - EZSP_setMacPollFailureWaitTime = 0x00F4, - EZSP_sendLinkPowerDeltaRequest = 0x00F7, - EZSP_multiPhyStart = 0x00F8, - EZSP_multiPhyStop = 0x00F9, - EZSP_multiPhySetRadioPower = 0x00FA, - EZSP_multiPhySetRadioChannel = 0x00FB, - EZSP_getPhyInterfaceCount = 0x00FC, - EZSP_getRadioParameters = 0x00FD, - EZSP_writeNodeData = 0x00FE, - - EZSP_rstAck = 0xFFFE, -}; - -#endif - - -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 -}; - - -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, -# 962 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -}; - - enum Z_AddrMode : uint8_t { - Z_Addr_NotPresent = 0, - Z_Addr_Group = 1, - Z_Addr_ShortAddress = 2, - Z_Addr_IEEEAddress = 3, - Z_Addr_Broadcast = 0xFF -}; - - -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 -}; - -#define Z_(s) Zo_ ## s - - -String getZDPStatusMessage(uint8_t status) { - static const char StatusMsg[] PROGMEM = "SUCCESS|INV_REQUESTTYPE|DEVICE_NOT_FOUND|INVALID_EP|NOT_ACTIVE|NOT_SUPPORTED" - "|TIMEOUT|NO_MATCH|NO_ENTRY|NO_DESCRIPTOR|INSUFFICIENT_SPACE|NOT_PERMITTED" - "|TABLE_FULL|NOT_AUTHORIZED|DEVICE_BINDING_TABLE_FULL" - ; - static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x80, 0x81, 0x82, 0x83, 0x84, - 0x85, 0x86, 0x88, 0x89, 0x8A, 0x8B, - 0x8C, 0x8D, 0x8E }; - - char msg[32]; - int32_t idx = -1; - for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { - if (status == pgm_read_byte(&StatusIdx[i])) { - idx = i; - break; - } - } - if (idx >= 0) { - GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); - } else { - *msg = 0x00; - } - return String(msg); -} - -String getEmberStatus(uint8_t status) { - static const char StatusMsg[] PROGMEM = "SUCCESS|ERR_FATAL|BAD_ARGUMENT|EEPROM_MFG_STACK_VERSION_MISMATCH|INCOMPATIBLE_STATIC_MEMORY_DEFINITIONS|EEPROM_MFG_VERSION_MISMATCH|EEPROM_STACK_VERSION_MISMATCH" - "|NO_BUFFERS|SERIAL_INVALID_BAUD_RATE|SERIAL_INVALID_PORT|SERIAL_TX_OVERFLOW|SERIAL_RX_OVERFLOW|SERIAL_RX_FRAME_ERROR|SERIAL_RX_PARITY_ERROR|SERIAL_RX_EMPTY|SERIAL_RX_OVERRUN_ERROR" - "|MAC_TRANSMIT_QUEUE_FULL|MAC_UNKNOWN_HEADER_TYPE|MAC_SCANNING|MAC_NO_DATA|MAC_JOINED_NETWORK|MAC_BAD_SCAN_DURATION|MAC_INCORRECT_SCAN_TYPE|MAC_INVALID_CHANNEL_MASK|MAC_COMMAND_TRANSMIT_FAILURE" - "|MAC_NO_ACK_RECEIVED|MAC_INDIRECT_TIMEOUT|SIM_EEPROM_ERASE_PAGE_GREEN|SIM_EEPROM_ERASE_PAGE_RED|SIM_EEPROM_FULL|ERR_FLASH_WRITE_INHIBITED|ERR_FLASH_VERIFY_FAILED|SIM_EEPROM_INIT_1_FAILED|SIM_EEPROM_INIT_2_FAILED|SIM_EEPROM_INIT_3_FAILED|ERR_FLASH_PROG_FAIL|ERR_FLASH_ERASE_FAIL" - "|ERR_BOOTLOADER_TRAP_TABLE_BAD|ERR_BOOTLOADER_TRAP_UNKNOWN|ERR_BOOTLOADER_NO_IMAGE|DELIVERY_FAILED|BINDING_INDEX_OUT_OF_RANGE|ADDRESS_TABLE_INDEX_OUT_OF_RANGE|INVALID_BINDING_INDEX" - "|INVALID_CALL|COST_NOT_KNOWN|MAX_MESSAGE_LIMIT_REACHED|MESSAGE_TOO_LONG|BINDING_IS_ACTIVE|ADDRESS_TABLE_ENTRY_IS_ACTIVE" - "|ADC_CONVERSION_DONE|ADC_CONVERSION_BUSY|ADC_CONVERSION_DEFERRED|ADC_NO_CONVERSION_PENDING|SLEEP_INTERRUPTED|PHY_TX_UNDERFLOW|PHY_TX_INCOMPLETE|PHY_INVALID_CHANNEL|PHY_INVALID_POWER|PHY_TX_BUSY|PHY_TX_CCA_FAIL|PHY_OSCILLATOR_CHECK_FAILED|PHY_ACK_RECEIVED" - "|NETWORK_UP|NETWORK_DOWN|JOIN_FAILED|MOVE_FAILED|CANNOT_JOIN_AS_ROUTER|NODE_ID_CHANGED|PAN_ID_CHANGED|NO_BEACONS|RECEIVED_KEY_IN_THE_CLEAR|NO_NETWORK_KEY_RECEIVED|NO_LINK_KEY_RECEIVED|PRECONFIGURED_KEY_REQUIRED" - "|NOT_JOINED|INVALID_SECURITY_LEVEL|NETWORK_BUSY|INVALID_ENDPOINT|BINDING_HAS_CHANGED|INSUFFICIENT_RANDOM_DATA|APS_ENCRYPTION_ERROR|SECURITY_STATE_NOT_SET" - "|KEY_TABLE_INVALID_ADDRESS|SECURITY_CONFIGURATION_INVALID|TOO_SOON_FOR_SWITCH_KEY|KEY_NOT_AUTHORIZED|SECURITY_DATA_INVALID|SOURCE_ROUTE_FAILURE|MANY_TO_ONE_ROUTE_FAILURE" - "|STACK_AND_HARDWARE_MISMATCH|INDEX_OUT_OF_RANGE|TABLE_FULL|TABLE_ENTRY_ERASED|LIBRARY_NOT_PRESENT|OPERATION_IN_PROGRESS" - ; - static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, - 0x18, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x39, 0x3A, 0x3D, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x40, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, - 0x58, 0x59, 0x5A, 0x66, 0x69, 0x6A, 0x6C, - 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, - 0x80, 0x81, 0x82, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, - 0x90, 0x91, 0x94, 0x96, 0x98, 0x99, 0x9A, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, - 0x93, 0x95, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA8, - 0xB3, 0xB7, 0xB8, 0xBB, 0xBD, 0xA9, 0xAA, - 0xB0, 0xB1, 0xB4, 0xB6, 0xB5, 0xBA }; - - char msg[32]; - int32_t idx = -1; - for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { - if (status == pgm_read_byte(&StatusIdx[i])) { - idx = i; - break; - } - } - if (idx >= 0) { - GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); - } else { - *msg = 0x00; - } - return String(msg); -} - - - -String getZigbeeStatusMessage(uint8_t status) { - static const char StatusMsg[] PROGMEM = "SUCCESS|FAILURE|NOT_AUTHORIZED|RESERVED_FIELD_NOT_ZERO|MALFORMED_COMMAND|UNSUP_CLUSTER_COMMAND|UNSUP_GENERAL_COMMAND" - "|UNSUP_MANUF_CLUSTER_COMMAND|UNSUP_MANUF_GENERAL_COMMAND|INVALID_FIELD|UNSUPPORTED_ATTRIBUTE|INVALID_VALE|READ_ONLY" - "|INSUFFICIENT_SPACE|DUPLICATE_EXISTS|NOT_FOUND|UNREPORTABLE_ATTRIBUTE|INVALID_DATA_TYPE|INVALID_SELECTOR|WRITE_ONLY" - "|INCONSISTENT_STARTUP_STATE|DEFINED_OUT_OF_BAND|INCONSISTENT|ACTION_DENIED|TIMEOUT|ABORT|INVALID_IMAGE|WAIT_FOR_DATA" - "|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER|NO_ROUTE" - "|CHANNEL_ACCESS_FAILURE|NO_ACK|NO_APP_ACK|NO_ROUTE" - ; - static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x7E, 0x7F, 0x80, 0x81, 0x82, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, 0xCD, - 0xE1, 0xE9, 0xA7, 0xD0}; - - char msg[32]; - int32_t idx = -1; - for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { - if (status == pgm_read_byte(&StatusIdx[i])) { - idx = i; - break; - } - } - if (idx >= 0) { - GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); - } else { - *msg = 0x00; - } - return String(msg); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -#ifdef USE_ZIGBEE - - - - - - -class ZigbeeZCLSendMessage { -public: - uint16_t shortaddr; - uint16_t groupaddr; - uint16_t cluster; - uint8_t endpoint; - uint8_t cmd; - uint16_t manuf; - bool clusterSpecific; - bool needResponse; - bool direct; - uint8_t transacId; - const uint8_t *msg; - size_t len; -}; - -typedef int32_t (*ZB_Func)(uint8_t value); -typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); - - -const uint8_t ZIGBEE_LABEL_RESTART = 1; -const uint8_t ZIGBEE_LABEL_INIT_COORD = 10; -const uint8_t ZIGBEE_LABEL_START_COORD = 11; -const uint8_t ZIGBEE_LABEL_INIT_ROUTER = 12; -const uint8_t ZIGBEE_LABEL_START_ROUTER = 13; -const uint8_t ZIGBEE_LABEL_INIT_DEVICE = 14; -const uint8_t ZIGBEE_LABEL_START_DEVICE = 15; -const uint8_t ZIGBEE_LABEL_START_ROUTER_DEVICE = 16; -const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; -const uint8_t ZIGBEE_LABEL_READY = 20; -const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; -const uint8_t ZIGBEE_LABEL_NETWORK_CONFIGURED = 22; -const uint8_t ZIGBEE_LABEL_BAD_CONFIG = 23; -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_FACT_RESET_COORD = 50; -const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER = 51; -const uint8_t ZIGBEE_LABEL_FACT_RESET_DEVICE = 52; -const uint8_t ZIGBEE_LABEL_CONFIGURE_EZSP = 53; - -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; - bool init_phase = true; - bool recv_until = false; - - uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; - uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; - uint8_t *recv_filter = nullptr; - uint8_t recv_filter_len = 0; - int16_t pc = 0; - uint32_t next_timeout = 0; - - ZB_RecvMsgFunc recv_func = nullptr; - ZB_RecvMsgFunc recv_unexpected = nullptr; - - uint32_t permit_end_time = 0; -}; -struct ZigbeeStatus zigbee; -SBuffer *zigbee_buffer = nullptr; - -void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl); -bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok = false); - - -uint32_t parseHex(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(**data); - if (v < 0) { break; } - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" -#ifdef USE_ZIGBEE - - - - - - - -int strcmp_PP(const char *p1, const char *p2) { - if (p1 == p2) { return 0; } - if (!p1) { return -1; } - if (!p2) { return 1; } - const unsigned char *s1 = (const unsigned char *) p1; - const unsigned char *s2 = (const unsigned char *) p2; - unsigned char c1, c2; - do { - c1 = (unsigned char) pgm_read_byte(s1); - s1++; - c2 = (unsigned char) pgm_read_byte(s2); - s2++; - if (c1 == '\0') - return c1 - c2; - } - while (c1 == c2); - return c1 - c2; -} - - - - - - - -typedef struct Z_LastMessageVars { - uint16_t device; - uint16_t groupaddr; - uint16_t cluster; - uint8_t endpoint; -} Z_LastMessageVars; - -Z_LastMessageVars gZbLastMessage; - -uint16_t Z_GetLastDevice(void) { return gZbLastMessage.device; } -uint16_t Z_GetLastGroup(void) { return gZbLastMessage.groupaddr; } -uint16_t Z_GetLastCluster(void) { return gZbLastMessage.cluster; } -uint8_t Z_GetLastEndpoint(void) { return gZbLastMessage.endpoint; } -# 74 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" -class Z_json_array { -public: - - Z_json_array(): val("[]") {} - void add(uint32_t uval32) { - - val.remove(val.length()-1); - if (val.length() > 1) { - val += ','; - } - val += uval32; - val += ']'; - } - void addStrRaw(const char * sval) { - - val.remove(val.length()-1); - if (val.length() > 1) { - val += ','; - } - val += sval; - val += ']'; - } - void addStr(const char * sval) { - addStrRaw(EscapeJSONString(sval).c_str()); - } - String &toString(void) { - return val; - } - -private : - String val; -}; - - - - - - - -enum class Za_type : uint8_t { - Za_none, - - Za_bool, - Za_uint, - Za_int, - Za_float, - - Za_raw, - Za_str, - - Za_obj, - Za_arr, -}; - -class Z_attribute { -public: - - - union { - struct { - uint16_t cluster; - uint16_t attr_id; - } id; - char * key; - } key; - - union { - uint32_t uval32; - int32_t ival32; - float fval; - SBuffer* bval; - char* sval; - class Z_attribute_list * objval; - class Z_json_array * arrval; - } val; - Za_type type; - bool key_is_str; - bool key_is_pmem; - bool val_str_raw; - uint8_t key_suffix; - uint8_t attr_type; - uint8_t attr_multiplier; - - - Z_attribute(): - key{ .id = { 0x0000, 0x0000 } }, - val{ .uval32 = 0x0000 }, - type(Za_type::Za_none), - key_is_str(false), - key_is_pmem(false), - val_str_raw(false), - key_suffix(1), - attr_type(0xFF), - attr_multiplier(1) - {}; - - Z_attribute(const Z_attribute & rhs) { - deepCopy(rhs); - } - - Z_attribute & operator = (const Z_attribute & rhs) { - freeKey(); - freeVal(); - deepCopy(rhs); - } - - - ~Z_attribute() { - freeKey(); - freeVal(); - } - - - void freeVal(void); - - - void freeKey(void); - - - void setKeyName(const char * _key, bool pmem = false); - - void setKeyName(const char * _key, const char * _key2); - - void setKeyId(uint16_t cluster, uint16_t attr_id); - - - void setNone(void); - void setUInt(uint32_t _val); - void setBool(bool _val); - void setInt(int32_t _val); - void setFloat(float _val); - - void setBuf(const SBuffer &buf, size_t index, size_t len); - - - - - - - void setStr(const char * _val); - inline void setStrRaw(const char * _val) { - setStr(_val); - val_str_raw = true; - } - - Z_attribute_list & newAttrList(void); - Z_json_array & newJsonArray(void); - - inline bool isNum(void) const { return (type >= Za_type::Za_bool) && (type <= Za_type::Za_float); } - inline bool isNone(void) const { return (type == Za_type::Za_none);} - - float getFloat(void) const; - int32_t getInt(void) const; - uint32_t getUInt(void) const; - bool getBool(void) const; - const SBuffer * getRaw(void) const; - - - - const char * getStr(void) const; - - bool equalsKey(const Z_attribute & attr2, bool ignore_key_suffix = false) const; - bool equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; - bool equalsKey(const char * name, uint8_t suffix = 0) const; - bool equalsVal(const Z_attribute & attr2) const; - bool equals(const Z_attribute & attr2) const; - - String toString(bool prefix_comma = false) const; - - - void copyVal(const Z_attribute & rhs); - -protected: - void deepCopy(const Z_attribute & rhs); -}; -# 261 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" -class Z_attribute_list : public LList { -public: - uint8_t src_ep; - uint8_t lqi; - uint16_t group_id; - - Z_attribute_list(): - LList(), - src_ep(0xFF), - lqi(0xFF), - group_id(0xFFFF) - {}; - - - - - - void reset(void) { - LList::reset(); - src_ep = 0xFF; - lqi = 0xFF; - group_id = 0xFFFF; - } - - inline bool isValidSrcEp(void) const { return 0xFF != src_ep; } - inline bool isValidLQI(void) const { return 0xFF != lqi; } - inline bool isValidGroupId(void) const { return 0xFFFF != group_id; } - - - - Z_attribute & addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); - - - Z_attribute & addAttribute(const char * name, bool pmem = false, uint8_t suffix = 0); - Z_attribute & addAttribute(const char * name, const char * name2, uint8_t suffix = 0); - inline Z_attribute & addAttribute(const __FlashStringHelper * name, uint8_t suffix = 0) { - return addAttribute((const char*) name, true, suffix); - } - - - inline void removeAttribute(const Z_attribute * attr) { remove(attr); } - - - - - String toString(bool enclose_brackets = false) const; - - - const Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) const; - const Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) const; - const Z_attribute * findAttribute(const Z_attribute &attr) const; - - inline Z_attribute * findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0) { - return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(cluster, attr_id, suffix); - } - inline Z_attribute * findAttribute(const char * name, uint8_t suffix = 0) { - return (Z_attribute*) (((const Z_attribute_list*)this)->findAttribute(name, suffix)); - } - inline Z_attribute * findAttribute(const Z_attribute &attr) { - return (Z_attribute*) ((const Z_attribute_list*)this)->findAttribute(attr); - } - - - size_t countAttribute(uint16_t cluster, uint16_t attr_id) const ; - size_t countAttribute(const char * name) const ; - - - Z_attribute & findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); - Z_attribute & findOrCreateAttribute(const char * name, uint8_t suffix = 0); - - Z_attribute & findOrCreateAttribute(const Z_attribute &attr); - - Z_attribute & replaceOrCreate(const Z_attribute &attr); - - - bool mergeList(const Z_attribute_list &list2); -}; -# 346 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_1z_libs.ino" -void Z_attribute::freeKey(void) { - if (key_is_str && key.key && !key_is_pmem) { delete[] key.key; } - key.key = nullptr; -} - - -void Z_attribute::setKeyName(const char * _key, bool pmem) { - freeKey(); - key_is_str = true; - key_is_pmem = pmem; - if (pmem) { - key.key = (char*) _key; - } else { - setKeyName(_key, nullptr); - } -} - -void Z_attribute::setKeyName(const char * _key, const char * _key2) { - freeKey(); - key_is_str = true; - key_is_pmem = false; - if (_key) { - size_t key_len = strlen_P(_key); - if (_key2) { - key_len += strlen_P(_key2); - } - key.key = new char[key_len+1]; - strcpy_P(key.key, _key); - if (_key2) { - strcat_P(key.key, _key2); - } - } -} - -void Z_attribute::setKeyId(uint16_t cluster, uint16_t attr_id) { - freeKey(); - key_is_str = false; - key.id.cluster = cluster; - key.id.attr_id = attr_id; -} - - -void Z_attribute::setNone(void) { - freeVal(); - val.uval32 = 0; - type = Za_type::Za_none; -} -void Z_attribute::setUInt(uint32_t _val) { - freeVal(); - val.uval32 = _val; - type = Za_type::Za_uint; -} -void Z_attribute::setBool(bool _val) { - freeVal(); - val.uval32 = _val; - type = Za_type::Za_bool; -} -void Z_attribute::setInt(int32_t _val) { - freeVal(); - val.ival32 = _val; - type = Za_type::Za_int; -} -void Z_attribute::setFloat(float _val) { - freeVal(); - val.fval = _val; - type = Za_type::Za_float; -} - -void Z_attribute::setBuf(const SBuffer &buf, size_t index, size_t len) { - freeVal(); - if (len) { - val.bval = new SBuffer(len); - val.bval->addBuffer(buf.buf(index), len); - } - type = Za_type::Za_raw; -} - - - - - - -void Z_attribute::setStr(const char * _val) { - freeVal(); - val_str_raw = false; - - if (_val) { - size_t len = strlen_P(_val); - if (len) { - val.sval = new char[len+1]; - strcpy_P(val.sval, _val); - } - } - type = Za_type::Za_str; -} - -Z_attribute_list & Z_attribute::newAttrList(void) { - freeVal(); - val.objval = new Z_attribute_list(); - type = Za_type::Za_obj; - return *val.objval; -} - -Z_json_array & Z_attribute::newJsonArray(void) { - freeVal(); - val.arrval = new Z_json_array(); - type = Za_type::Za_arr; - return *val.arrval; -} - - -float Z_attribute::getFloat(void) const { - switch (type) { - case Za_type::Za_bool: - case Za_type::Za_uint: return (float) val.uval32; - case Za_type::Za_int: return (float) val.ival32; - case Za_type::Za_float: return val.fval; - default: return 0.0f; - } -} - -int32_t Z_attribute::getInt(void) const { - switch (type) { - case Za_type::Za_bool: - case Za_type::Za_uint: return (int32_t) val.uval32; - case Za_type::Za_int: return val.ival32; - case Za_type::Za_float: return (int32_t) val.fval; - default: return 0; - } -} - -uint32_t Z_attribute::getUInt(void) const { - switch (type) { - case Za_type::Za_bool: - case Za_type::Za_uint: return val.uval32; - case Za_type::Za_int: return (uint32_t) val.ival32; - case Za_type::Za_float: return (uint32_t) val.fval; - default: return 0; - } -} - -bool Z_attribute::getBool(void) const { - switch (type) { - case Za_type::Za_bool: - case Za_type::Za_uint: return val.uval32 ? true : false; - case Za_type::Za_int: return val.ival32 ? true : false; - case Za_type::Za_float: return val.fval ? true : false; - default: return false; - } -} - -const SBuffer * Z_attribute::getRaw(void) const { - if (Za_type::Za_raw == type) { return val.bval; } - return nullptr; -} - - - -const char * Z_attribute::getStr(void) const { - if (Za_type::Za_str == type) { return val.sval; } - return ""; -} - -bool Z_attribute::equalsKey(const Z_attribute & attr2, bool ignore_key_suffix) const { - - if (key_is_str != attr2.key_is_str) { return false; } - if (key_is_str) { - if (strcmp_PP(key.key, attr2.key.key)) { return false; } - } else { - if ((key.id.cluster != attr2.key.id.cluster) || - (key.id.attr_id != attr2.key.id.attr_id)) { return false; } - } - if (!ignore_key_suffix) { - if (key_suffix != attr2.key_suffix) { return false; } - } - return true; -} - -bool Z_attribute::equalsKey(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { - if (!key_is_str) { - if ((key.id.cluster == cluster) && (key.id.attr_id == attr_id)) { - if (suffix) { - if (key_suffix == suffix) { return true; } - } else { - return true; - } - } - } - return false; -} - -bool Z_attribute::equalsKey(const char * name, uint8_t suffix) const { - if (key_is_str) { - if (0 == strcmp_PP(key.key, name)) { - if (suffix) { - if (key_suffix == suffix) { return true; } - } else { - return true; - } - } - } - return false; -} - -bool Z_attribute::equalsVal(const Z_attribute & attr2) const { - if (type != attr2.type) { return false; } - if ((type >= Za_type::Za_bool) && (type <= Za_type::Za_float)) { - - if (val.uval32 != attr2.val.uval32) { return false; } - } else if (type == Za_type::Za_raw) { - - return equalsSBuffer(val.bval, attr2.val.bval); - } else if (type == Za_type::Za_str) { - - if (strcmp_PP(val.sval, attr2.val.sval)) { return false; } - } else if (type == Za_type::Za_obj) { - return false; - } else if (type == Za_type::Za_arr) { - return false; - } - return true; -} - -bool Z_attribute::equals(const Z_attribute & attr2) const { - return equalsKey(attr2) && equalsVal(attr2); -} - -String Z_attribute::toString(bool prefix_comma) const { - String res(""); - if (prefix_comma) { res += ','; } - res += '"'; - - if (key_is_str) { - if (key.key) { res += EscapeJSONString(key.key); } - else { res += F("null"); } - if (key_suffix > 1) { - res += key_suffix; - } - } else { - char attr_name[12]; - snprintf_P(attr_name, sizeof(attr_name), PSTR("%04X/%04X"), key.id.cluster, key.id.attr_id); - res += attr_name; - if (key_suffix > 1) { - res += '+'; - res += key_suffix; - } - } - res += F("\":"); - - switch (type) { - case Za_type::Za_none: - res += "null"; - break; - case Za_type::Za_bool: - res += val.uval32 ? F("true") : F("false"); - break; - case Za_type::Za_uint: - res += val.uval32; - break; - case Za_type::Za_int: - res += val.ival32; - break; - case Za_type::Za_float: - { - String fstr(val.fval, 2); - size_t last = fstr.length() - 1; - - while (fstr[last] == '0') { - fstr.remove(last--); - } - - if (fstr[last] == '.') { - fstr.remove(last); - } - res += fstr; - } - break; - case Za_type::Za_raw: - res += '"'; - if (val.bval) { - size_t blen = val.bval->len(); - - char hex[2*blen+1]; - ToHex_P(val.bval->getBuffer(), blen, hex, sizeof(hex)); - res += hex; - } - res += '"'; - break; - case Za_type::Za_str: - if (val_str_raw) { - if (val.sval) { res += val.sval; } - } else { - res += '"'; - if (val.sval) { - res += EscapeJSONString(val.sval); - } - res += '"'; - } - break; - case Za_type::Za_obj: - res += '{'; - if (val.objval) { - res += val.objval->toString(); - } - res += '}'; - break; - case Za_type::Za_arr: - if (val.arrval) { - res += val.arrval->toString(); - } else { - res += "[]"; - } - break; - } - - return res; -} - - -void Z_attribute::copyVal(const Z_attribute & rhs) { - freeVal(); - - val.uval32 = 0x00000000; - type = rhs.type; - if (rhs.isNum()) { - val.uval32 = rhs.val.uval32; - } else if (rhs.type == Za_type::Za_raw) { - if (rhs.val.bval) { - val.bval = new SBuffer(rhs.val.bval->len()); - val.bval->addBuffer(*(rhs.val.bval)); - } - } else if (rhs.type == Za_type::Za_str) { - if (rhs.val.sval) { - size_t s_len = strlen_P(rhs.val.sval); - val.sval = new char[s_len+1]; - strcpy_P(val.sval, rhs.val.sval); - } - } - val_str_raw = rhs.val_str_raw; -} - - -void Z_attribute::freeVal(void) { - switch (type) { - case Za_type::Za_raw: - if (val.bval) { delete val.bval; val.bval = nullptr; } - break; - case Za_type::Za_str: - if (val.sval) { delete[] val.sval; val.sval = nullptr; } - break; - case Za_type::Za_obj: - if (val.objval) { delete val.objval; val.objval = nullptr; } - break; - case Za_type::Za_arr: - if (val.arrval) { delete val.arrval; val.arrval = nullptr; } - break; - } -} - -void Z_attribute::deepCopy(const Z_attribute & rhs) { - - if (!rhs.key_is_str) { - key.id.cluster = rhs.key.id.cluster; - key.id.attr_id = rhs.key.id.attr_id; - } else { - if (rhs.key_is_pmem) { - key.key = rhs.key.key; - } else { - key.key = nullptr; - if (rhs.key.key) { - size_t key_len = strlen_P(rhs.key.key); - if (key_len) { - key.key = new char[key_len+1]; - strcpy_P(key.key, rhs.key.key); - } - } - } - } - key_is_str = rhs.key_is_str; - key_is_pmem = rhs.key_is_pmem; - key_suffix = rhs.key_suffix; - attr_type = rhs.attr_type; - attr_multiplier = rhs.attr_multiplier; - - copyVal(rhs); - -} - - - - - - - -Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { - Z_attribute & attr = addToLast(); - attr.key.id.cluster = cluster; - attr.key.id.attr_id = attr_id; - attr.key_is_str = false; - if (!suffix) { attr.key_suffix = countAttribute(attr.key.id.cluster, attr.key.id.attr_id); } - else { attr.key_suffix = suffix; } - return attr; -} - - -Z_attribute & Z_attribute_list::addAttribute(const char * name, bool pmem, uint8_t suffix) { - Z_attribute & attr = addToLast(); - attr.setKeyName(name, pmem); - if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } - else { attr.key_suffix = suffix; } - return attr; -} - -Z_attribute & Z_attribute_list::addAttribute(const char * name, const char * name2, uint8_t suffix) { - Z_attribute & attr = addToLast(); - attr.setKeyName(name, name2); - if (!suffix) { attr.key_suffix = countAttribute(attr.key.key); } - else { attr.key_suffix = suffix; } - return attr; -} - -String Z_attribute_list::toString(bool enclose_brackets) const { - String res = ""; - if (enclose_brackets) { res += '{'; } - bool prefix_comma = false; - for (const auto & attr : *this) { - res += attr.toString(prefix_comma); - prefix_comma = true; - } - - if (0xFF != src_ep) { - if (prefix_comma) { res += ','; } - prefix_comma = true; - res += F("\"" D_CMND_ZIGBEE_ENDPOINT "\":"); - res += src_ep; - } - - if (0xFFFF != group_id) { - if (prefix_comma) { res += ','; } - prefix_comma = true; - res += F("\"" D_CMND_ZIGBEE_GROUP "\":"); - res += group_id; - } - - if (0xFF != lqi) { - if (prefix_comma) { res += ','; } - prefix_comma = true; - res += F("\"" D_CMND_ZIGBEE_LINKQUALITY "\":"); - res += lqi; - } - if (enclose_brackets) { res += '}'; } - - return res; -} - - -const Z_attribute * Z_attribute_list::findAttribute(const Z_attribute &attr) const { - uint8_t suffix = attr.key_suffix; - if (attr.key_is_str) { - return findAttribute(attr.key.key, suffix); - } else { - return findAttribute(attr.key.id.cluster, attr.key.id.attr_id, suffix); - } -} - -const Z_attribute * Z_attribute_list::findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { - for (const auto & attr : *this) { - if (attr.equalsKey(cluster, attr_id, suffix)) { return &attr; } - } - return nullptr; -} -size_t Z_attribute_list::countAttribute(uint16_t cluster, uint16_t attr_id) const { - size_t count = 0; - for (const auto & attr : *this) { - if (attr.equalsKey(cluster, attr_id, 0)) { count++; } - } - return count; -} - - -Z_attribute & Z_attribute_list::findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { - Z_attribute * found = findAttribute(cluster, attr_id, suffix); - return found ? *found : addAttribute(cluster, attr_id, suffix); -} - -const Z_attribute * Z_attribute_list::findAttribute(const char * name, uint8_t suffix) const { - for (const auto & attr : *this) { - if (attr.equalsKey(name, suffix)) { return &attr; } - } - return nullptr; -} -size_t Z_attribute_list::countAttribute(const char * name) const { - size_t count = 0; - for (const auto & attr : *this) { - if (attr.equalsKey(name, 0)) { count++; } - } - return count; -} - -Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t suffix) { - Z_attribute * found = findAttribute(name, suffix); - return found ? *found : addAttribute(name, suffix); -} - - -Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) { - if (attr.key_is_str) { - return findOrCreateAttribute(attr.key.key, attr.key_suffix); - } else { - return findOrCreateAttribute(attr.key.id.cluster, attr.key.id.attr_id, attr.key_suffix); - } -} - -Z_attribute & Z_attribute_list::replaceOrCreate(const Z_attribute &attr) { - Z_attribute &new_attr = findOrCreateAttribute(attr); - new_attr.copyVal(attr); - return new_attr; -} - - -bool Z_attribute_list::mergeList(const Z_attribute_list &attr_list) { - - if (0xFF == src_ep) { - src_ep = attr_list.src_ep; - } else if (0xFF != attr_list.src_ep) { - if (src_ep != attr_list.src_ep) { return false; } - } - if (0xFF != attr_list.lqi) { - lqi = attr_list.lqi; - } - for (auto & attr : attr_list) { - replaceOrCreate(attr); - } - return true; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" -#ifdef USE_ZIGBEE - -#ifndef ZIGBEE_SAVE_DELAY_SECONDS -#define ZIGBEE_SAVE_DELAY_SECONDS 2 -#endif -const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; - -enum class Z_Data_Type : uint8_t { - Z_Unknown = 0x00, - Z_Light = 1, - Z_Plug = 2, - Z_PIR = 3, - Z_Alarm = 4, - Z_Thermo = 5, - Z_OnOff = 6, - Z_Ext = 0xF, - Z_Device = 0xFF -}; - -class Z_Data_Set; - - - -class Z_Data { -public: - Z_Data(Z_Data_Type type = Z_Data_Type::Z_Unknown, uint8_t endpoint = 0) : _type(type), _endpoint(endpoint), _config(-1), _power(0) {} - inline Z_Data_Type getType(void) const { return _type; } - inline int8_t getConfig(void) const { return _config; } - inline void setConfig(int8_t config) { _config = config; } - - inline uint8_t getEndpoint(void) const { return _endpoint; } - - void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; - - static const Z_Data_Type type = Z_Data_Type::Z_Unknown; - - friend class Z_Data_Set; -protected: - Z_Data_Type _type; - uint8_t _endpoint; - int8_t _config; - uint8_t _power; -}; - - - - - - - -class Z_Data_OnOff : public Z_Data { -public: - Z_Data_OnOff(uint8_t endpoint = 0) : - Z_Data(Z_Data_Type::Z_OnOff, endpoint) - { - _config = 1; - } - - inline bool validPower(uint32_t relay = 0) const { return (_config > relay); } - inline bool getPower(uint32_t relay = 0) const { return bitRead(_power, relay); } - void setPower(bool val, uint32_t relay = 0); - - void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; - - static const Z_Data_Type type = Z_Data_Type::Z_OnOff; -}; - - -void Z_Data_OnOff::setPower(bool val, uint32_t relay) { - if (relay < 8) { - if (_config < relay) { _config = relay; } - bitWrite(_power, relay, val); - } -} - - - - -class Z_Data_Plug : public Z_Data { -public: - Z_Data_Plug(uint8_t endpoint = 0) : - Z_Data(Z_Data_Type::Z_Plug, endpoint), - mains_voltage(0xFFFF), - mains_power(-0x8000) - {} - - inline bool validMainsVoltage(void) const { return 0xFFFF != mains_voltage; } - inline bool validMainsPower(void) const { return -0x8000 != mains_power; } - - inline uint16_t getMainsVoltage(void) const { return mains_voltage; } - inline int16_t getMainsPower(void) const { return mains_power; } - - inline void setMainsVoltage(uint16_t _mains_voltage) { mains_voltage = _mains_voltage; } - inline void setMainsPower(int16_t _mains_power) { mains_power = _mains_power; } - - static const Z_Data_Type type = Z_Data_Type::Z_Plug; - - uint16_t mains_voltage; - int16_t mains_power; -}; - - - - -class Z_Data_Light : public Z_Data { -public: - Z_Data_Light(uint8_t endpoint = 0) : - Z_Data(Z_Data_Type::Z_Light, endpoint), - colormode(0xFF), - dimmer(0xFF), - sat(0xFF), - hue(0xFF), - ct(0xFFFF), - x(0xFFFF), - y(0xFFFF) - {} - - inline bool validColormode(void) const { return 0xFF != colormode; } - inline bool validDimmer(void) const { return 0xFF != dimmer; } - inline bool validSat(void) const { return 0xFF != sat; } - inline bool validHue(void) const { return 0xFFFF != hue; } - inline bool validCT(void) const { return 0xFFFF != ct; } - inline bool validX(void) const { return 0xFFFF != x; } - inline bool validY(void) const { return 0xFFFF != y; } - - inline uint8_t getColorMode(void) const { return colormode; } - inline uint8_t getDimmer(void) const { return dimmer; } - inline uint8_t getSat(void) const { return sat; } - inline uint16_t getHue(void) const { return changeUIntScale(hue, 0, 254, 0, 360); } - inline uint16_t getCT(void) const { return ct; } - inline uint16_t getX(void) const { return x; } - inline uint16_t getY(void) const { return y; } - - inline void setColorMode(uint8_t _colormode) { colormode = _colormode; } - inline void setDimmer(uint8_t _dimmer) { dimmer = _dimmer; } - inline void setSat(uint8_t _sat) { sat = _sat; } - inline void setHue(uint16_t _hue) { hue = changeUIntScale(_hue, 0, 360, 0, 254);; } - inline void setCT(uint16_t _ct) { ct = _ct; } - inline void setX(uint16_t _x) { x = _x; } - inline void setY(uint16_t _y) { y = _y; } - - void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; - - static const Z_Data_Type type = Z_Data_Type::Z_Light; - - uint8_t colormode; - uint8_t dimmer; - uint8_t sat; - uint8_t hue; - uint16_t ct; - uint16_t x, y; -}; - - - - -class Z_Data_Thermo : public Z_Data { -public: - Z_Data_Thermo(uint8_t endpoint = 0) : - Z_Data(Z_Data_Type::Z_Thermo, endpoint), - temperature(-0x8000), - pressure(-0x8000), - humidity(0xFFFF), - th_setpoint(0xFF), - temperature_target(-0x8000) - {} - - inline bool validTemperature(void) const { return -0x8000 != temperature; } - inline bool validPressure(void) const { return -0x8000 != pressure; } - inline bool validHumidity(void) const { return 0xFFFF != humidity; } - inline bool validThSetpoint(void) const { return 0xFF != th_setpoint; } - inline bool validTempTarget(void) const { return -0x8000 != temperature_target; } - - inline int16_t getTemperature(void) const { return temperature; } - inline int16_t getPressure(void) const { return pressure; } - inline uint16_t getHumidity(void) const { return humidity; } - inline uint8_t getThSetpoint(void) const { return th_setpoint; } - inline int16_t getTempTarget(void) const { return temperature_target; } - - inline void setTemperature(int16_t _temperature) { temperature = _temperature; } - inline void setPressure(int16_t _pressure) { pressure = _pressure; } - inline void setHumidity(uint16_t _humidity) { humidity = _humidity; } - inline void setThSetpoint(uint8_t _th_setpoint) { th_setpoint = _th_setpoint; } - inline void setTempTarget(int16_t _temperature_target){ temperature_target = _temperature_target; } - - static const Z_Data_Type type = Z_Data_Type::Z_Thermo; - - - int16_t temperature; - int16_t pressure; - uint16_t humidity; - - uint8_t th_setpoint; - int16_t temperature_target; -}; - - - - -class Z_Data_Alarm : public Z_Data { -public: - Z_Data_Alarm(uint8_t endpoint = 0) : - Z_Data(Z_Data_Type::Z_Alarm, endpoint), - zone_type(0xFFFF) - {} - - static const Z_Data_Type type = Z_Data_Type::Z_Alarm; - - inline bool validZoneType(void) const { return 0xFFFF != zone_type; } - - inline uint16_t getZoneType(void) const { return zone_type; } - - inline void setZoneType(uint16_t _zone_type) { zone_type = _zone_type; } - - - uint16_t zone_type; -# 250 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" -}; - - - - - -class Z_Data_Set : public LList { -public: - - Z_Data & getByType(Z_Data_Type type, uint8_t ep = 0); - const Z_Data & find(Z_Data_Type type, uint8_t ep = 0) const; - - - - - - template - M & get(uint8_t ep = 0); - - template - const M & find(uint8_t ep = 0) const; - - - template - M & addIfNull(M & cur, uint8_t ep = 0); -}; - -Z_Data & Z_Data_Set::getByType(Z_Data_Type type, uint8_t ep) { - switch (type) { - case Z_Data_Type::Z_Light: - return get(ep); - case Z_Data_Type::Z_Plug: - return get(ep); - case Z_Data_Type::Z_Alarm: - return get(ep); - case Z_Data_Type::Z_Thermo: - return get(ep); - case Z_Data_Type::Z_OnOff: - return get(ep); - default: - return *(Z_Data*)nullptr; - } -} - -template -M & Z_Data_Set::get(uint8_t ep) { - M & m = (M&) find(M::type, ep); - return addIfNull(m, ep); -} - -template -const M & Z_Data_Set::find(uint8_t ep) const { - return (M&) find(M::type, ep); -} - - - -template -M & Z_Data_Set::addIfNull(M & cur, uint8_t ep) { - if (nullptr == &cur) { - LList_elt * elt = new LList_elt(); - elt->val()._endpoint = ep; - this->addToLast((LList_elt*)elt); - return elt->val(); - } else { - if (cur._endpoint == 0) { cur._endpoint = ep; } - return cur; - } -} - -const Z_Data & Z_Data_Set::find(Z_Data_Type type, uint8_t ep) const { - for (auto & elt : *this) { - if (elt._type == type) { - - - if ((ep == 0) || (elt._endpoint == 0) || (ep == elt._endpoint)) { - return elt; - } - } - } - return *(Z_Data*)nullptr; -} - - - - -void Z_Data_Light::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { - attr_list.addAttribute(PSTR(D_JSON_ZIGBEE_LIGHT)).setInt(getConfig()); - Z_Data::toAttributes(attr_list, type); -} - -void Z_Data_OnOff::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { - if (validPower()) { attr_list.addAttribute(PSTR("Power")).setUInt(getPower() ? 1 : 0); } -} - - - - - -const size_t endpoints_max = 8; - -class Z_Device { -public: - - uint64_t longaddr; - char * manufacturerId; - char * modelId; - char * friendlyName; - - - uint32_t defer_last_message_sent; - - uint8_t endpoints[endpoints_max]; - - Z_attribute_list attr_list; - - uint16_t shortaddr; - uint8_t seqNumber; - bool hidden; - bool reachable; - - - - Z_Data_Set data; - - uint8_t lqi; - uint8_t batterypercent; - - uint32_t last_seen; - - - Z_Device(uint16_t _shortaddr = BAD_SHORTADDR, uint64_t _longaddr = 0x00): - longaddr(_longaddr), - manufacturerId(nullptr), - modelId(nullptr), - friendlyName(nullptr), - defer_last_message_sent(0), - endpoints{ 0, 0, 0, 0, 0, 0, 0, 0 }, - attr_list(), - shortaddr(_shortaddr), - seqNumber(0), - hidden(false), - reachable(false), - - lqi(0xFF), - batterypercent(0xFF), - last_seen(0) - { }; - - inline bool valid(void) const { return BAD_SHORTADDR != shortaddr; } - - inline bool validLongaddr(void) const { return 0x0000 != longaddr; } - inline bool validManufacturerId(void) const { return nullptr != manufacturerId; } - inline bool validModelId(void) const { return nullptr != modelId; } - inline bool validFriendlyName(void) const { return nullptr != friendlyName; } - - inline bool validPower(uint8_t ep =0) const; - - inline bool validLqi(void) const { return 0xFF != lqi; } - inline bool validBatteryPercent(void) const { return 0xFF != batterypercent; } - inline bool validLastSeen(void) const { return 0x0 != last_seen; } - - inline void setReachable(bool _reachable) { reachable = _reachable; } - inline bool getReachable(void) const { return reachable; } - inline bool getPower(uint8_t ep =0) const; - - - void toAttributes(Z_attribute_list & attr_list) const; - - - void setPower(bool power_on, uint8_t ep = 0); - - - int8_t getLightChannels(void) const { - const Z_Data_Light & light = data.find(0); - if (&light != nullptr) { - return light.getConfig(); - } else { - return -1; - } - } - - - bool setLightChannels(int8_t channels) { - bool dirty = false; - if (channels >= 0) { - - Z_Data_Light & light = data.get(0); - if (channels != light.getConfig()) { - light.setConfig(channels); - dirty = true; - } - } else { - - for (auto & data_elt : data) { - if (data_elt.getType() == Z_Data_Type::Z_Light) { - - data.remove(&data_elt); - dirty = true; - } - } - } - return dirty; - } -}; - - - - - -typedef void (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); - - -typedef enum Z_Def_Category { - Z_CAT_ALWAYS = 0, - - Z_CLEAR_DEVICE = 0x01, - Z_CAT_READ_ATTR, - Z_CAT_VIRTUAL_OCCUPANCY, - Z_CAT_REACHABILITY, - Z_CAT_PERMIT_JOIN, - - Z_CLEAR_DEVICE_CLUSTER, - Z_CAT_READ_CLUSTER, - - Z_CLEAR_DEVICE_CLUSTER_ENDPOINT, - Z_CAT_EP_DESC, - Z_CAT_BIND, - Z_CAT_CONFIG_ATTR, - Z_CAT_READ_ATTRIBUTE, -} Z_Def_Category; - -const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 2000; - -typedef struct Z_Deferred { - - uint32_t timer; - uint16_t shortaddr; - uint16_t groupaddr; - uint16_t cluster; - uint8_t endpoint; - uint8_t category; - uint32_t value; - Z_DeviceTimer func; -} Z_Deferred; -# 505 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2_devices.ino" -class Z_Devices { -public: - Z_Devices() : _deferred() {}; - - - - - - - uint16_t isKnownLongAddr(uint64_t longaddr) const; - uint16_t isKnownIndex(uint32_t index) const; - uint16_t isKnownFriendlyName(const char * name) const; - - Z_Device & findShortAddr(uint16_t shortaddr); - const Z_Device & findShortAddr(uint16_t shortaddr) const; - Z_Device & findLongAddr(uint64_t longaddr); - const Z_Device & findLongAddr(uint64_t longaddr) const; - Z_Device & getShortAddr(uint16_t shortaddr); - Z_Device & getLongAddr(uint64_t longaddr); - - inline bool foundDevice(const Z_Device & device) const { - return (&device != &device_unk); - } - - int32_t findFriendlyName(const char * name) const; - uint64_t getDeviceLongAddr(uint16_t shortaddr) const; - - uint8_t findFirstEndpoint(uint16_t shortaddr) const; - - - - void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); - - - void addEndpoint(uint16_t shortaddr, uint8_t endpoint); - void clearEndpoints(uint16_t shortaddr); - uint32_t countEndpoints(uint16_t shortaddr) const; - - void setManufId(uint16_t shortaddr, const char * str); - void setModelId(uint16_t shortaddr, const char * str); - void setFriendlyName(uint16_t shortaddr, const char * str); - inline const char * getFriendlyName(uint16_t shortaddr) const { - return findShortAddr(shortaddr).friendlyName; - } - inline const char * getModelId(uint16_t shortaddr) const { - return findShortAddr(shortaddr).modelId; - } - inline const char * getManufacturerId(uint16_t shortaddr) const{ - return findShortAddr(shortaddr).manufacturerId; - } - - void setReachable(uint16_t shortaddr, bool reachable); - void setLQI(uint16_t shortaddr, uint8_t lqi); - void setLastSeenNow(uint16_t shortaddr); - - void setBatteryPercent(uint16_t shortaddr, uint8_t bp); - uint8_t getBatteryPercent(uint16_t shortaddr) const; - - - uint8_t getNextSeqNumber(uint16_t shortaddr); - - - static void addLightState(Z_attribute_list & attr_list, const Z_Data_Light & light); - String dumpLightState(uint16_t shortaddr) const; - String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; - int32_t deviceRestore(JsonParserObject json); - - - void setLightProfile(uint16_t shortaddr, uint8_t light_profile); - uint8_t getLightProfile(uint16_t shortaddr) const ; - - - int8_t getHueBulbtype(uint16_t shortaddr) const ; - void hideHueBulb(uint16_t shortaddr, bool hidden); - bool isHueBulbHidden(uint16_t shortaddr) const ; - Z_Data_Light & getLight(uint16_t shortaddr); - - - void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster = 0xFFFF, uint8_t endpoint = 0xFF); - void setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); - void queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func); - void runTimer(void); - - - void jsonAppend(uint16_t shortaddr, const Z_attribute_list &attr_list); - void jsonPublishFlush(uint16_t shortaddr); - bool jsonIsConflict(uint16_t shortaddr, const Z_attribute_list &attr_list) const; - void jsonPublishNow(uint16_t shortaddr, Z_attribute_list &attr_list); - - - size_t devicesSize(void) const { - return _devices.length(); - } - const Z_Device & devicesAt(size_t i) const { - const Z_Device * devp = _devices.at(i); - if (devp) { - return *devp; - } else { - return device_unk; - } - } - - - bool removeDevice(uint16_t shortaddr); - - - void dirty(void); - void clean(void); - void shrinkToFit(uint16_t shortaddr); - - - uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; - -private: - LList _devices; - LList _deferred; - uint32_t _saveTimer = 0; - uint8_t _seqNumber = 0; - - - - const Z_Device device_unk = Z_Device(BAD_SHORTADDR); - - - - Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); - void freeDeviceEntry(Z_Device *device); - - void setStringAttribute(char*& attr, const char * str); -}; - - - - -Z_Devices zigbee_devices = Z_Devices(); - - -uint64_t localIEEEAddr = 0; -uint16_t localShortAddr = 0; - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -#ifdef USE_ZIGBEE -# 30 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { - if ((BAD_SHORTADDR == shortaddr) && !longaddr) { return (Z_Device&) device_unk; } - Z_Device device(shortaddr, longaddr); - - dirty(); - return _devices.addHead(device); -} - -void Z_Devices::freeDeviceEntry(Z_Device *device) { - if (device->manufacturerId) { free(device->manufacturerId); } - if (device->modelId) { free(device->modelId); } - if (device->friendlyName) { free(device->friendlyName); } - free(device); -} -# 53 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) { - for (auto & elem : _devices) { - if (elem.shortaddr == shortaddr) { return elem; } - } - return (Z_Device&) device_unk; -} -const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const { - for (const auto & elem : _devices) { - if (elem.shortaddr == shortaddr) { return elem; } - } - return device_unk; -} -# 73 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) { - if (!longaddr) { return (Z_Device&) device_unk; } - for (auto &elem : _devices) { - if (elem.longaddr == longaddr) { return elem; } - } - return (Z_Device&) device_unk; -} -const Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) const { - if (!longaddr) { return device_unk; } - for (const auto &elem : _devices) { - if (elem.longaddr == longaddr) { return elem; } - } - return device_unk; -} -# 95 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -int32_t Z_Devices::findFriendlyName(const char * name) const { - if (!name) { return -1; } - size_t name_len = strlen(name); - int32_t found = 0; - if (name_len) { - for (auto &elem : _devices) { - if (elem.friendlyName) { - if (strcasecmp(elem.friendlyName, name) == 0) { return found; } - } - found++; - } - } - return -1; -} - -uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { - const Z_Device & device = findLongAddr(longaddr); - if (foundDevice(device)) { - return device.shortaddr; - } else { - return BAD_SHORTADDR; - } -} - -uint16_t Z_Devices::isKnownIndex(uint32_t index) const { - if (index < devicesSize()) { - const Z_Device & device = devicesAt(index); - return device.shortaddr; - } else { - return BAD_SHORTADDR; - } -} - -uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { - if ((!name) || (0 == strlen(name))) { return BAD_SHORTADDR; } - int32_t found = findFriendlyName(name); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - return device.shortaddr; - } else { - return BAD_SHORTADDR; - } -} - -uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { - return findShortAddr(shortaddr).longaddr; -} - - - - -Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { - if (BAD_SHORTADDR == shortaddr) { return (Z_Device&) device_unk; } - Z_Device & device = findShortAddr(shortaddr); - if (foundDevice(device)) { - return device; - } - return createDeviceEntry(shortaddr, 0); -} - - -Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { - if (!longaddr) { return (Z_Device&) device_unk; } - Z_Device & device = findLongAddr(longaddr); - if (foundDevice(device)) { - return device; - } - return createDeviceEntry(0, longaddr); -} - - -bool Z_Devices::removeDevice(uint16_t shortaddr) { - Z_Device & device = findShortAddr(shortaddr); - if (foundDevice(device)) { - _devices.remove(&device); - dirty(); - return true; - } - return false; -} - - - - - - -void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { - Z_Device * s_found = &findShortAddr(shortaddr); - Z_Device * l_found = &findLongAddr(longaddr); - - if (foundDevice(*s_found) && foundDevice(*l_found)) { - if (s_found == l_found) { - } else { - - l_found->shortaddr = shortaddr; - - freeDeviceEntry(s_found); - _devices.remove(s_found); - dirty(); - } - } else if (foundDevice(*s_found)) { - - - s_found->longaddr = longaddr; - dirty(); - } else if (foundDevice(*l_found)) { - - l_found->shortaddr = shortaddr; - dirty(); - } else { - - if ((BAD_SHORTADDR != shortaddr) || longaddr) { - createDeviceEntry(shortaddr, longaddr); - } - } -} - - - - -void Z_Devices::clearEndpoints(uint16_t shortaddr) { - Z_Device &device = getShortAddr(shortaddr); - for (uint32_t i = 0; i < endpoints_max; i++) { - device.endpoints[i] = 0; - - } -} - - - - -void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) { - if (0x00 == endpoint) { return; } - Z_Device &device = getShortAddr(shortaddr); - - for (uint32_t i = 0; i < endpoints_max; i++) { - if (endpoint == device.endpoints[i]) { - return; - } - if (0 == device.endpoints[i]) { - device.endpoints[i] = endpoint; - dirty(); - return; - } - } -} - - - - -uint32_t Z_Devices::countEndpoints(uint16_t shortaddr) const { - uint32_t count_ep = 0; - const Z_Device & device =findShortAddr(shortaddr); - if (!foundDevice(device)) return 0; - - for (uint32_t i = 0; i < endpoints_max; i++) { - if (0 != device.endpoints[i]) { - count_ep++; - } - } - return count_ep; -} - - -uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const { - - if (0x0000 == shortaddr) { return 1; } - return findShortAddr(shortaddr).endpoints[0]; -} - -void Z_Devices::setStringAttribute(char*& attr, const char * str) { - if (nullptr == str) { return; } - size_t str_len = strlen(str); - - if ((nullptr == attr) && (0 == str_len)) { return; } - if (attr) { - - if (strcmp(attr, str) != 0) { - - free(attr); - attr = nullptr; - } else { - return; - } - } - if (str_len) { - attr = (char*) malloc(str_len + 1); - strlcpy(attr, str, str_len + 1); - } - dirty(); -} -# 296 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).manufacturerId, str); -} - -void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).modelId, str); -} - -void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).friendlyName, str); -} - - -void Z_Devices::setReachable(uint16_t shortaddr, bool reachable) { - getShortAddr(shortaddr).setReachable(reachable); -} - -void Z_Devices::setLQI(uint16_t shortaddr, uint8_t lqi) { - if (shortaddr == localShortAddr) { return; } - getShortAddr(shortaddr).lqi = lqi; -} - -void Z_Devices::setLastSeenNow(uint16_t shortaddr) { - if (shortaddr == localShortAddr) { return; } - - - - - if (Rtc.utc_time < 1577836800) { return; } - getShortAddr(shortaddr).last_seen = Rtc.utc_time; -} - - -void Z_Devices::setBatteryPercent(uint16_t shortaddr, uint8_t bp) { - getShortAddr(shortaddr).batterypercent = bp; -} - - -uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { - Z_Device & device = findShortAddr(shortaddr); - if (foundDevice(device)) { - device.seqNumber += 1; - return device.seqNumber; - } else { - _seqNumber += 1; - return _seqNumber; - } -} - - -void Z_Devices::setLightProfile(uint16_t shortaddr, uint8_t light_profile) { - Z_Device &device = getShortAddr(shortaddr); - if (device.setLightChannels(light_profile)) { - dirty(); - } -} - - -uint8_t Z_Devices::getLightProfile(uint16_t shortaddr) const { - const Z_Device &device = findShortAddr(shortaddr); - return device.getLightChannels(); -} - -int8_t Z_Devices::getHueBulbtype(uint16_t shortaddr) const { - int8_t light_profile = getLightProfile(shortaddr); - if (0x00 == (light_profile & 0xF0)) { - return (light_profile & 0x07); - } else { - - return -1; - } -} - -void Z_Devices::hideHueBulb(uint16_t shortaddr, bool hidden) { - Z_Device &device = getShortAddr(shortaddr); - if (device.hidden != hidden) { - device.hidden = hidden; - dirty(); - } -} - -bool Z_Devices::isHueBulbHidden(uint16_t shortaddr) const { - const Z_Device & device = findShortAddr(shortaddr); - if (foundDevice(device)) { - return device.hidden; - } - return true; -} - - - - -void Z_Devices::resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category, uint16_t cluster, uint8_t endpoint) { - - for (auto & defer : _deferred) { - if ((defer.shortaddr == shortaddr) && (defer.groupaddr == groupaddr)) { - if ((0xFF == category) || (defer.category == category)) { - if ((0xFFFF == cluster) || (defer.cluster == cluster)) { - if ((0xFF == endpoint) || (defer.endpoint == endpoint)) { - _deferred.remove(&defer); - } - } - } - } - } -} - - -void Z_Devices::setTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { - - if (category >= Z_CLEAR_DEVICE) { - resetTimersForDevice(shortaddr, groupaddr, category, category >= Z_CLEAR_DEVICE_CLUSTER ? cluster : 0xFFFF, category >= Z_CLEAR_DEVICE_CLUSTER_ENDPOINT ? endpoint : 0xFF); - } - - - Z_Deferred & deferred = _deferred.addHead(); - deferred = { wait_ms + millis(), - shortaddr, - groupaddr, - cluster, - endpoint, - category, - value, - func }; -} - - - -void Z_Devices::queueTimer(uint16_t shortaddr, uint16_t groupaddr, uint32_t wait_ms, uint16_t cluster, uint8_t endpoint, uint8_t category, uint32_t value, Z_DeviceTimer func) { - Z_Device & device = getShortAddr(shortaddr); - uint32_t now_millis = millis(); - if (TimeReached(device.defer_last_message_sent)) { - device.defer_last_message_sent = now_millis; - } - - device.defer_last_message_sent += wait_ms; - - - setTimer(shortaddr, groupaddr, (device.defer_last_message_sent - now_millis), cluster, endpoint, Z_CAT_ALWAYS, value, func); -} - - - -void Z_Devices::runTimer(void) { - - for (auto & defer : _deferred) { - uint32_t timer = defer.timer; - if (TimeReached(timer)) { - (*defer.func)(defer.shortaddr, defer.groupaddr, defer.cluster, defer.endpoint, defer.value); - _deferred.remove(&defer); - } - } - - - if ((_saveTimer) && TimeReached(_saveTimer)) { - saveZigbeeDevices(); - _saveTimer = 0; - } -} - - - - -bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const Z_attribute_list &attr_list) const { - const Z_Device & device = findShortAddr(shortaddr); - - if (!foundDevice(device)) { return false; } - if (attr_list.isEmpty()) { - return false; - } - - - if (device.attr_list.isValidGroupId() && attr_list.isValidGroupId()) { - if (device.attr_list.group_id != attr_list.group_id) { return true; } - } - - - if (device.attr_list.isValidSrcEp() && attr_list.isValidSrcEp()) { - if (device.attr_list.src_ep != attr_list.src_ep) { return true; } - } - - - - - for (const auto & attr : attr_list) { - const Z_attribute * curr_attr = device.attr_list.findAttribute(attr); - if (nullptr != curr_attr) { - if (!curr_attr->equalsVal(attr)) { - return true; - } - } - } - return false; -} - -void Z_Devices::jsonAppend(uint16_t shortaddr, const Z_attribute_list &attr_list) { - Z_Device & device = getShortAddr(shortaddr); - device.attr_list.mergeList(attr_list); -} - -void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (!device.valid()) { return; } - Z_attribute_list &attr_list = device.attr_list; - - if (!attr_list.isEmpty()) { - const char * fname = zigbee_devices.getFriendlyName(shortaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); - - - gZbLastMessage.device = shortaddr; - gZbLastMessage.groupaddr = attr_list.group_id; - gZbLastMessage.endpoint = attr_list.src_ep; - - mqtt_data[0] = 0; - - if (!Settings.flag4.remove_zbreceived) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":")); - } - - if (use_fname) { - Response_P(PSTR("%s{\"%s\":{"), mqtt_data, fname); - } else { - Response_P(PSTR("%s{\"0x%04X\":{"), mqtt_data, shortaddr); - } - - Response_P(PSTR("%s\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\","), mqtt_data, shortaddr); - - if (fname) { - Response_P(PSTR("%s\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), mqtt_data, EscapeJSONString(fname).c_str()); - } - - Response_P(PSTR("%s%s}}"), mqtt_data, attr_list.toString().c_str()); - - if (!Settings.flag4.remove_zbreceived) { - Response_P(PSTR("%s}"), mqtt_data); - } - attr_list.reset(); - - if (Settings.flag4.zigbee_distinct_topics) { - if (Settings.flag4.zb_topic_fname && fname) { - - char stemp[TOPSZ]; - strlcpy(stemp, (!strlen(fname)) ? MQTT_TOPIC : fname, sizeof(stemp)); - MakeValidMqtt(0, stemp); - - char frtopic[TOPSZ]; - snprintf_P(frtopic, sizeof(frtopic), PSTR("%s/%s/" D_RSLT_SENSOR), SettingsText(SET_MQTTPREFIX3), stemp); - MqttPublish(frtopic, Settings.flag.mqtt_sensor_retain); - } else { - char subtopic[16]; - snprintf_P(subtopic, sizeof(subtopic), PSTR("%04X/" D_RSLT_SENSOR), shortaddr); - MqttPublishPrefixTopic_P(TELE, subtopic, Settings.flag.mqtt_sensor_retain); - } - } else { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - } - XdrvRulesProcess(); - } -} - -void Z_Devices::jsonPublishNow(uint16_t shortaddr, Z_attribute_list &attr_list) { - jsonPublishFlush(shortaddr); - jsonAppend(shortaddr, attr_list); - jsonPublishFlush(shortaddr); -} - -void Z_Devices::dirty(void) { - _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); -} -void Z_Devices::clean(void) { - _saveTimer = 0; -} - - - - - - -uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { - if (nullptr == param) { return BAD_SHORTADDR; } - size_t param_len = strlen(param); - char dataBuf[param_len + 1]; - strcpy(dataBuf, param); - RemoveSpace(dataBuf); - uint16_t shortaddr = BAD_SHORTADDR; - - if (strlen(dataBuf) < 4) { - - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { - shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); - } - } else if ((dataBuf[0] == '0') && ((dataBuf[1] == 'x') || (dataBuf[1] == 'X'))) { - - if (strlen(dataBuf) < 18) { - - shortaddr = strtoull(dataBuf, nullptr, 0); - if (short_must_be_known) { - shortaddr = zigbee_devices.findShortAddr(shortaddr).shortaddr; - } - - } else { - - uint64_t longaddr = strtoull(dataBuf, nullptr, 0); - shortaddr = zigbee_devices.isKnownLongAddr(longaddr); - } - } else { - - shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); - } - - return shortaddr; -} - - -String Z_Devices::dumpLightState(uint16_t shortaddr) const { - Z_attribute_list attr_list; - char hex[8]; - - const Z_Device & device = findShortAddr(shortaddr); - const char * fname = getFriendlyName(shortaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - - attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex); - if (fname) { - attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(fname); - } - - if (foundDevice(device)) { - - attr_list.addAttribute(F("Reachable")).setBool(device.getReachable()); - if (device.validPower()) { attr_list.addAttribute(F("Power")).setUInt(device.getPower()); } - const Z_Data_Light & light = device.data.find(0); - if (&light != nullptr) { - light.toAttributes(attr_list, Z_Data_Light::type); - - if (light.validHue()) { - attr_list.findOrCreateAttribute(PSTR("Hue")).setUInt(light.getHue()); - } - } - - } - - Z_attribute_list attr_list_root; - Z_attribute * attr_root; - if (use_fname) { - attr_root = &attr_list_root.addAttribute(fname); - } else { - attr_root = &attr_list_root.addAttribute(hex); - } - attr_root->setStrRaw(attr_list.toString(true).c_str()); - return attr_list_root.toString(true); -} - - - - -String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { - Z_json_array json_arr; - - for (const auto & device : _devices) { - uint16_t shortaddr = device.shortaddr; - char hex[22]; - - - if ((BAD_SHORTADDR != status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } - - Z_attribute_list attr_list; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex); - - if (device.friendlyName > 0) { - attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(device.friendlyName); - } - - if (2 <= dump_mode) { - hex[0] = '0'; - hex[1] = 'x'; - Uint64toHex(device.longaddr, &hex[2], 64); - attr_list.addAttribute(F("IEEEAddr")).setStr(hex); - if (device.modelId) { - attr_list.addAttribute(F(D_JSON_MODEL D_JSON_ID)).setStr(device.modelId); - } - int8_t bulbtype = getHueBulbtype(shortaddr); - if (bulbtype >= 0) { - attr_list.addAttribute(F(D_JSON_ZIGBEE_LIGHT)).setInt(bulbtype); - } - if (device.manufacturerId) { - attr_list.addAttribute(F("Manufacturer")).setStr(device.manufacturerId); - } - Z_json_array arr_ep; - for (uint32_t i = 0; i < endpoints_max; i++) { - uint8_t endpoint = device.endpoints[i]; - if (0x00 == endpoint) { break; } - arr_ep.add(endpoint); - } - attr_list.addAttribute(F("Endpoints")).setStrRaw(arr_ep.toString().c_str()); - } - json_arr.addStrRaw(attr_list.toString(true).c_str()); - } - return json_arr.toString(); -} -# 710 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_2a_devices_impl.ino" -int32_t Z_Devices::deviceRestore(JsonParserObject json) { - - - uint16_t device = 0x0000; - uint64_t ieeeaddr = 0x0000000000000000LL; - const char * modelid = nullptr; - const char * manufid = nullptr; - const char * friendlyname = nullptr; - int8_t bulbtype = -1; - size_t endpoints_len = 0; - - - JsonParserToken val_device = json[PSTR("Device")]; - if (val_device) { - device = (uint32_t) val_device.getUInt(device); - } else { - return -1; - } - - ieeeaddr = json.getULong(PSTR("IEEEAddr"), ieeeaddr); - friendlyname = json.getStr(PSTR("Name"), nullptr); - modelid = json.getStr(PSTR("ModelId"), nullptr); - manufid = json.getStr(PSTR("Manufacturer"), nullptr); - JsonParserToken tok_bulbtype = json[PSTR(D_JSON_ZIGBEE_LIGHT)]; - - - updateDevice(device, ieeeaddr); - if (modelid) { setModelId(device, modelid); } - if (manufid) { setManufId(device, manufid); } - if (friendlyname) { setFriendlyName(device, friendlyname); } - if (tok_bulbtype) { setLightProfile(device, tok_bulbtype.getInt()); } - - - JsonParserToken val_endpoints = json[PSTR("Endpoints")]; - if (val_endpoints.isArray()) { - JsonParserArray arr_ep = JsonParserArray(val_endpoints); - clearEndpoints(device); - for (auto ep_elt : arr_ep) { - uint8_t ep = ep_elt.getUInt(); - if (ep) { addEndpoint(device, ep); } - } - } - - return 0; -} - -Z_Data_Light & Z_Devices::getLight(uint16_t shortaddr) { - return getShortAddr(shortaddr).data.get(); -} - - - - -void Z_Device::toAttributes(Z_attribute_list & attr_list) const { - if (validLqi()) { attr_list.addAttribute(PSTR(D_CMND_ZIGBEE_LINKQUALITY)).setUInt(lqi); } - if (validBatteryPercent()) { attr_list.addAttribute(PSTR("BatteryPercentage")).setUInt(batterypercent); } - if (validLastSeen()) { attr_list.addAttribute(PSTR("LastSeen")).setUInt(last_seen); } -} - - - - -void Z_Device::setPower(bool power_on, uint8_t ep) { - data.get(ep).setPower(power_on); -} - -bool Z_Device::validPower(uint8_t ep) const { - const Z_Data_OnOff & onoff = data.find(ep); - return (&onoff != nullptr); -} - -bool Z_Device::getPower(uint8_t ep) const { - const Z_Data_OnOff & onoff = data.find(ep); - if (&onoff != nullptr) return onoff.getPower(); - return false; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_3_hue.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_3_hue.ino" -#ifdef USE_ZIGBEE -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) - - - - -void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response) { - static const char HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE[] PROGMEM = - "%s\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":%s}"; - - bool power = false; - bool reachable = false; - uint8_t colormode = 0xFF; - uint8_t bri = 0xFF; - uint8_t sat = 0xFF; - uint16_t ct = 0xFFFF; - uint16_t hue = 0xFFFF; - uint16_t x = 0xFFFF, y = 0xFFFF; - String light_status = ""; - uint32_t echo_gen = findEchoGeneration(); - - const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); - const Z_Data_Light & light = device.data.find(); - if (&light != nullptr) { - bri = light.getDimmer(); - colormode = light.getColorMode(); - sat = light.getSat(); - ct = light.getCT(); - hue = light.getHue(); - x = light.getX(); - y = light.getY(); - } - power = device.getPower(); - reachable = device.getReachable(); - - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - if (sat > 254) sat = 254; - uint16_t hue16 = changeUIntScale(hue, 0, 360, 0, 65535); - - const size_t buf_size = 256; - char * buf = (char*) malloc(buf_size); - - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? "true" : "false"); - - if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { - snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); - } - if (LST_COLDWARM <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"colormode\":\"%s\","), buf, (0 == colormode) ? "hs" : (1 == colormode) ? "xy" : "ct"); - } - if (LST_RGB <= local_light_subtype) { - if (prev_x_str[0] && prev_y_str[0]) { - snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, prev_x_str, prev_y_str); - } else { - float x_f = x / 65536.0f; - float y_f = y / 65536.0f; - snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, String(x, 5).c_str(), String(y, 5).c_str()); - } - snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue16, sat); - } - if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { - snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); - } - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? "true" : "false"); - - *response += buf; - free(buf); -} - -void HueLightStatus2Zigbee(uint16_t shortaddr, String *response) -{ - const size_t buf_size = 300; - char * buf = (char*) malloc(buf_size); - - const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); - const char * friendlyName = device.friendlyName; - const char * modelId = device.modelId; - const char * manufacturerId = device.manufacturerId; - char shortaddrname[8]; - snprintf_P(shortaddrname, sizeof(shortaddrname), PSTR("0x%04X"), shortaddr); - - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON2, - (friendlyName) ? EscapeJSONString(friendlyName).c_str() : shortaddrname, - (modelId) ? EscapeJSONString(modelId).c_str() : PSTR("Unknown"), - (manufacturerId) ? EscapeJSONString(manufacturerId).c_str() : PSTR("Tasmota"), - GetHueDeviceId(shortaddr).c_str()); - - *response += buf; - free(buf); -} - -void ZigbeeHueStatus(String * response, uint16_t shortaddr) { - *response += F("{\"state\":"); - HueLightStatus1Zigbee(shortaddr, zigbee_devices.getHueBulbtype(shortaddr), response); - HueLightStatus2Zigbee(shortaddr, response); -} - -void ZigbeeCheckHue(String * response, bool &appending) { - uint32_t zigbee_num = zigbee_devices.devicesSize(); - for (uint32_t i = 0; i < zigbee_num; i++) { - uint16_t shortaddr = zigbee_devices.devicesAt(i).shortaddr; - int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); - - if (bulbtype >= 0) { - - if (appending) { *response += ","; } - *response += "\""; - *response += EncodeLightId(0, shortaddr); - *response += F("\":{\"state\":"); - HueLightStatus1Zigbee(shortaddr, bulbtype, response); - HueLightStatus2Zigbee(shortaddr, response); - appending = true; - } - } -} - -void ZigbeeHueGroups(String * lights) { - uint32_t zigbee_num = zigbee_devices.devicesSize(); - for (uint32_t i = 0; i < zigbee_num; i++) { - uint16_t shortaddr = zigbee_devices.devicesAt(i).shortaddr; - int8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); - - if (bulbtype >= 0) { - *lights += ",\""; - *lights += EncodeLightId(i); - *lights += "\""; - } - } -} - - - -void ZigbeeHuePower(uint16_t shortaddr, bool power) { - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0006, power ? 1 : 0, ""); - zigbee_devices.getShortAddr(shortaddr).setPower(power, 0); -} - - -void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { - if (dimmer > 0xFE) { dimmer = 0xFE; } - char param[8]; - snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer); - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0008, 0x04, param); - zigbee_devices.getLight(shortaddr).setDimmer(dimmer); -} - - -void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { - if (ct > 0xFEFF) { ct = 0xFEFF; } - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeHueCT 0x%04X - %d"), shortaddr, ct); - char param[12]; - snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8); - uint8_t colormode = 2; - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x0A, param); - Z_Data_Light & light = zigbee_devices.getLight(shortaddr); - light.setColorMode(colormode); - light.setCT(ct); -} - - -void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { - char param[16]; - if (x > 0xFEFF) { x = 0xFEFF; } - if (y > 0xFEFF) { y = 0xFEFF; } - snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8); - uint8_t colormode = 1; - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x07, param); - Z_Data_Light & light = zigbee_devices.getLight(shortaddr); - light.setColorMode(colormode); - light.setX(x); - light.setY(y); -} - - -void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { - char param[16]; - uint8_t hue8 = changeUIntScale(hue, 0, 360, 0, 254); - if (sat > 0xFE) { sat = 0xFE; } - snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat); - uint8_t colormode = 0; - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x06, param); - Z_Data_Light & light = zigbee_devices.getLight(shortaddr); - light.setColorMode(colormode); - light.setSat(sat); - light.setHue(hue); -} - -void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { - uint8_t power, colormode, bri, sat; - uint16_t ct, hue; - float x, y; - int code = 200; - - bool resp = false; - bool on = false; - - uint8_t bulbtype = zigbee_devices.getHueBulbtype(shortaddr); - - const size_t buf_size = 100; - char * buf = (char*) malloc(buf_size); - - if (Webserver->args()) { - response = "["; - - JsonParser parser((char*) Webserver->arg((Webserver->args())-1).c_str()); - JsonParserObject root = parser.getRootObject(); - - JsonParserToken hue_on = root[PSTR("on")]; - if (hue_on) { - on = hue_on.getBool(); - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"), - device_id, on ? "true" : "false"); - - if (on) { - ZigbeeHuePower(shortaddr, 0x01); - } else { - ZigbeeHuePower(shortaddr, 0x00); - } - response += buf; - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_bri = root[PSTR("bri")]; - if (hue_bri) { - bri = hue_bri.getUInt(); - prev_bri = bri; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "bri", bri); - response += buf; - if (LST_SINGLE <= bulbtype) { - - if (254 <= bri) { bri = 255; } - ZigbeeHueDimmer(shortaddr, bri); - } - resp = true; - } - - - parser.setCurrent(); - JsonParserToken hue_xy = root[PSTR("xy")]; - if (hue_xy) { - JsonParserArray arr_xy = JsonParserArray(hue_xy); - JsonParserToken tok_x = arr_xy[0]; - JsonParserToken tok_y = arr_xy[1]; - float x = tok_x.getFloat(); - float y = tok_y.getFloat(); - strlcpy(prev_x_str, tok_x.getStr(), sizeof(prev_x_str)); - strlcpy(prev_y_str, tok_y.getStr(), sizeof(prev_y_str)); - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/xy\":[%s,%s]}}"), - device_id, prev_x_str, prev_y_str); - response += buf; - resp = true; - uint16_t xi = x * 65536.0f; - uint16_t yi = y * 65536.0f; - ZigbeeHueXY(shortaddr, xi, yi); - } - bool huesat_changed = false; - - parser.setCurrent(); - JsonParserToken hue_hue = root[PSTR("hue")]; - if (hue_hue) { - hue = hue_hue.getUInt(); - prev_hue = hue; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "hue", hue); - response += buf; - if (LST_RGB <= bulbtype) { - - hue = changeUIntScale(hue, 0, 65535, 0, 360); - huesat_changed = true; - } - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_sat = root[PSTR("sat")]; - if (hue_sat) { - sat = hue_sat.getUInt(); - prev_sat = sat; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "sat", sat); - response += buf; - if (LST_RGB <= bulbtype) { - - if (254 <= sat) { sat = 255; } - huesat_changed = true; - } - if (huesat_changed) { - ZigbeeHueHS(shortaddr, hue, sat); - } - resp = true; - } - - parser.setCurrent(); - JsonParserToken hue_ct = root[PSTR("ct")]; - if (hue_ct) { - ct = hue_ct.getUInt(); - prev_ct = ct; - if (resp) { response += ","; } - snprintf_P(buf, buf_size, - PSTR("{\"success\":{\"/lights/%d/state/%s\":%d}}"), - device_id, "ct", ct); - response += buf; - if ((LST_COLDWARM == bulbtype) || (LST_RGBW <= bulbtype)) { - ZigbeeHueCT(shortaddr, ct); - } - resp = true; - } - - response += "]"; - if (2 == response.length()) { - response = FPSTR(HUE_ERROR_JSON); - } - } - else { - response = FPSTR(HUE_ERROR_JSON); - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); - - free(buf); -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -#ifdef USE_ZIGBEE -# 52 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -#ifdef ESP8266 -const static uint16_t z_spi_start_sector = 0xFF; -const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; -const static uint8_t* z_dev_start = z_spi_start + 0x0800; -const static size_t z_spi_len = 0x1000; -const static size_t z_block_offset = 0x0800; -const static size_t z_block_len = 0x0800; -#else -uint8_t* z_dev_start; -const static size_t z_spi_len = 0x1000; -const static size_t z_block_offset = 0x0000; -const static size_t z_block_len = 0x1000; -#endif - -class z_flashdata_t { -public: - uint32_t name; - uint16_t len; - uint16_t reserved; -}; - -const static uint32_t ZIGB_NAME = 0x3167697A; -const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); - - -class SBuffer hibernateDevice(const struct Z_Device &device) { - SBuffer buf(128); - - buf.add8(0x00); - buf.add16(device.shortaddr); - buf.add64(device.longaddr); - - uint32_t endpoints_count = 0; - for (endpoints_count = 0; endpoints_count < endpoints_max; endpoints_count++) { - if (0x00 == device.endpoints[endpoints_count]) { break; } - } - - buf.add8(endpoints_count); - - for (uint32_t i = 0; i < endpoints_max; i++) { - uint8_t endpoint = device.endpoints[i]; - if (0x00 == endpoint) { break; } - - buf.add8(endpoint); - buf.add16(0x0000); - - - buf.add8(0xFF); - - - buf.add8(0xFF); - } - - - if (device.modelId) { - size_t model_len = strlen(device.modelId); - if (model_len > 32) { model_len = 32; } - buf.addBuffer(device.modelId, model_len); - } - buf.add8(0x00); - - - if (device.manufacturerId) { - size_t manuf_len = strlen(device.manufacturerId); - if (manuf_len > 32) { manuf_len = 32; } - buf.addBuffer(device.manufacturerId, manuf_len); - } - buf.add8(0x00); - - - if (device.friendlyName) { - size_t frname_len = strlen(device.friendlyName); - if (frname_len > 32) {frname_len = 32; } - buf.addBuffer(device.friendlyName, frname_len); - } - buf.add8(0x00); - - - buf.add8(device.getLightChannels()); - - - buf.set8(0, buf.len()); - - return buf; -} - -class SBuffer hibernateDevices(void) { - SBuffer buf(2048); - - size_t devices_size = zigbee_devices.devicesSize(); - if (devices_size > 32) { devices_size = 32; } - buf.add8(devices_size); - - for (uint32_t i = 0; i < devices_size; i++) { - const Z_Device & device = zigbee_devices.devicesAt(i); - const SBuffer buf_device = hibernateDevice(device); - buf.addBuffer(buf_device); - } - - size_t buf_len = buf.len(); - if (buf_len > 2040) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); - } - - - char *hex_char = (char*) malloc((buf_len * 2) + 2); - if (hex_char) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), - ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); - free(hex_char); - } - - return buf; -} - -void hydrateDevices(const SBuffer &buf) { - uint32_t buf_len = buf.len(); - if (buf_len <= 10) { return; } - - uint32_t k = 0; - uint32_t num_devices = buf.get8(k++); - for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { - uint32_t dev_record_len = buf.get8(k); - - SBuffer buf_d = buf.subBuffer(k, dev_record_len); - - uint32_t d = 1; - uint16_t shortaddr = buf_d.get16(d); d += 2; - uint64_t longaddr = buf_d.get64(d); d += 8; - zigbee_devices.updateDevice(shortaddr, longaddr); - - uint32_t endpoints = buf_d.get8(d++); - for (uint32_t j = 0; j < endpoints; j++) { - uint8_t ep = buf_d.get8(d++); - uint16_t ep_profile = buf_d.get16(d); d += 2; - zigbee_devices.addEndpoint(shortaddr, ep); - - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - - } - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - - } - } - - - char empty[] = ""; - - - uint32_t s_len = buf_d.strlen_s(d); - char *ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setModelId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setManufId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setFriendlyName(shortaddr, ptr); - d += s_len + 1; - - - if (d < dev_record_len) { - zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d)); - d++; - } - - - k += dev_record_len; - } -} - -void loadZigbeeDevices(void) { -#ifdef ESP32 - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - ZigbeeRead(&spi_buffer, z_spi_len); - z_dev_start = spi_buffer; -#endif - z_flashdata_t flashdata; - memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); - - - if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { - uint16_t buf_len = flashdata.len; - - SBuffer buf(buf_len); - buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); - hydrateDevices(buf); - zigbee_devices.clean(); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); - } - -#ifdef ESP32 - free(spi_buffer); -#endif -} - -void saveZigbeeDevices(void) { - SBuffer buf = hibernateDevices(); - size_t buf_len = buf.len(); - if (buf_len > Z_MAX_FLASH) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); - return; - } - - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - -#ifdef ESP8266 - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); -#else - ZigbeeRead(&spi_buffer, z_spi_len); -#endif - - z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); - flashdata->name = ZIGB_NAME; - flashdata->len = buf_len; - flashdata->reserved = 0; - - memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); - - -#ifdef ESP8266 - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); -#else - ZigbeeWrite(&spi_buffer, z_spi_len); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data saved (%d bytes)"), buf_len); -#endif - free(spi_buffer); -} - - -void eraseZigbeeDevices(void) { - zigbee_devices.clean(); -#ifdef ESP8266 - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - - - memset(spi_buffer + z_block_offset, 0xFF, z_block_len); - - - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - - free(spi_buffer); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); -#else - ZigbeeErase(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (%d bytes)"), z_block_len); -#endif -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" -#ifdef USE_ZIGBEE -# 76 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5__constants.ino" -const char Z_strings[] PROGMEM = - "\x00" - "ZCLVersion" "\x00" - "AppVersion" "\x00" - "StackVersion" "\x00" - "HWVersion" "\x00" - "Manufacturer" "\x00" - "ModelId" "\x00" - "DateCode" "\x00" - "PowerSource" "\x00" - "GenericDeviceClass" "\x00" - "GenericDeviceType" "\x00" - "ProductCode" "\x00" - "ProductURL" "\x00" - "SWBuildID" "\x00" - "MainsVoltage" "\x00" - "MainsFrequency" "\x00" - "BatteryVoltage" "\x00" - "BatteryPercentage" "\x00" - "CurrentTemperature" "\x00" - "MinTempExperienced" "\x00" - "MaxTempExperienced" "\x00" - "OverTempTotalDwell" "\x00" - "IdentifyTime" "\x00" - "GroupNameSupport" "\x00" - "SceneCount" "\x00" - "CurrentScene" "\x00" - "CurrentGroup" "\x00" - "SceneValid" "\x00" - "Power" "\x00" - "StartUpOnOff" "\x00" - "SwitchType" "\x00" - "Dimmer" "\x00" - "DimmerOptions" "\x00" - "DimmerRemainingTime" "\x00" - "OnOffTransitionTime" "\x00" - "AlarmCount" "\x00" - "Time" "\x00" - "TimeStatus" "\x00" - "TimeZone" "\x00" - "DstStart" "\x00" - "DstEnd" "\x00" - "DstShift" "\x00" - "StandardTime" "\x00" - "LocalTime" "\x00" - "LastSetTime" "\x00" - "ValidUntilTime" "\x00" - "TimeEpoch" "\x00" - "LocationType" "\x00" - "LocationMethod" "\x00" - "LocationAge" "\x00" - "QualityMeasure" "\x00" - "NumberOfDevices" "\x00" - "AnalogInDescription" "\x00" - "AnalogInMaxValue" "\x00" - "AnalogInMinValue" "\x00" - "AnalogInOutOfService" "\x00" - "AqaraRotate" "\x00" - "AnalogInReliability" "\x00" - "AnalogInResolution" "\x00" - "AnalogInStatusFlags" "\x00" - "AnalogInEngineeringUnits" "\x00" - "AnalogInApplicationType" "\x00" - "Aqara_FF05" "\x00" - "AnalogOutDescription" "\x00" - "AnalogOutMaxValue" "\x00" - "AnalogOutMinValue" "\x00" - "AnalogOutOutOfService" "\x00" - "AnalogOutValue" "\x00" - "AnalogOutReliability" "\x00" - "AnalogOutRelinquishDefault" "\x00" - "AnalogOutResolution" "\x00" - "AnalogOutStatusFlags" "\x00" - "AnalogOutEngineeringUnits" "\x00" - "AnalogOutApplicationType" "\x00" - "AnalogDescription" "\x00" - "AnalogOutOfService" "\x00" - "AnalogValue" "\x00" - "AnalogPriorityArray" "\x00" - "AnalogReliability" "\x00" - "AnalogRelinquishDefault" "\x00" - "AnalogStatusFlags" "\x00" - "AnalogEngineeringUnits" "\x00" - "AnalogApplicationType" "\x00" - "BinaryInActiveText" "\x00" - "BinaryInDescription" "\x00" - "BinaryInInactiveText" "\x00" - "BinaryInOutOfService" "\x00" - "BinaryInPolarity" "\x00" - "BinaryInValue" "\x00" - "BinaryInReliability" "\x00" - "BinaryInStatusFlags" "\x00" - "BinaryInApplicationType" "\x00" - "BinaryOutActiveText" "\x00" - "BinaryOutDescription" "\x00" - "BinaryOutInactiveText" "\x00" - "BinaryOutMinimumOffTime" "\x00" - "BinaryOutMinimumOnTime" "\x00" - "BinaryOutOutOfService" "\x00" - "BinaryOutPolarity" "\x00" - "BinaryOutValue" "\x00" - "BinaryOutReliability" "\x00" - "BinaryOutRelinquishDefault" "\x00" - "BinaryOutStatusFlags" "\x00" - "BinaryOutApplicationType" "\x00" - "BinaryActiveText" "\x00" - "BinaryDescription" "\x00" - "BinaryInactiveText" "\x00" - "BinaryMinimumOffTime" "\x00" - "BinaryMinimumOnTime" "\x00" - "BinaryOutOfService" "\x00" - "BinaryValue" "\x00" - "BinaryReliability" "\x00" - "BinaryRelinquishDefault" "\x00" - "BinaryStatusFlags" "\x00" - "BinaryApplicationType" "\x00" - "MultiInDescription" "\x00" - "MultiInNumberOfStates" "\x00" - "MultiInOutOfService" "\x00" - "MultiInValue" "\x00" - "MultiInReliability" "\x00" - "MultiInStatusFlags" "\x00" - "MultiInApplicationType" "\x00" - "MultiOutDescription" "\x00" - "MultiOutNumberOfStates" "\x00" - "MultiOutOutOfService" "\x00" - "MultiOutValue" "\x00" - "MultiOutReliability" "\x00" - "MultiOutRelinquishDefault" "\x00" - "MultiOutStatusFlags" "\x00" - "MultiOutApplicationType" "\x00" - "MultiDescription" "\x00" - "MultiNumberOfStates" "\x00" - "MultiOutOfService" "\x00" - "MultiValue" "\x00" - "MultiReliability" "\x00" - "MultiRelinquishDefault" "\x00" - "MultiStatusFlags" "\x00" - "MultiApplicationType" "\x00" - "TotalProfileNum" "\x00" - "MultipleScheduling" "\x00" - "EnergyFormatting" "\x00" - "EnergyRemote" "\x00" - "ScheduleMode" "\x00" - "CheckinInterval" "\x00" - "LongPollInterval" "\x00" - "ShortPollInterval" "\x00" - "FastPollTimeout" "\x00" - "CheckinIntervalMin" "\x00" - "LongPollIntervalMin" "\x00" - "FastPollTimeoutMax" "\x00" - "PhysicalClosedLimit" "\x00" - "MotorStepSize" "\x00" - "Status" "\x00" - "ClosedLimit" "\x00" - "Mode" "\x00" - "LockState" "\x00" - "LockType" "\x00" - "ActuatorEnabled" "\x00" - "DoorState" "\x00" - "DoorOpenEvents" "\x00" - "DoorClosedEvents" "\x00" - "OpenPeriod" "\x00" - "AqaraVibrationMode" "\x00" - "AqaraVibrationsOrAngle" "\x00" - "AqaraVibration505" "\x00" - "AqaraAccelerometer" "\x00" - "WindowCoveringType" "\x00" - "PhysicalClosedLimitLift" "\x00" - "PhysicalClosedLimitTilt" "\x00" - "CurrentPositionLift" "\x00" - "CurrentPositionTilt" "\x00" - "NumberofActuationsLift" "\x00" - "NumberofActuationsTilt" "\x00" - "ConfigStatus" "\x00" - "CurrentPositionLiftPercentage" "\x00" - "CurrentPositionTiltPercentage" "\x00" - "InstalledOpenLimitLift" "\x00" - "InstalledClosedLimitLift" "\x00" - "InstalledOpenLimitTilt" "\x00" - "InstalledClosedLimitTilt" "\x00" - "VelocityLift" "\x00" - "AccelerationTimeLift" "\x00" - "DecelerationTimeLift" "\x00" - "IntermediateSetpointsLift" "\x00" - "IntermediateSetpointsTilt" "\x00" - "LocalTemperature" "\x00" - "OutdoorTemperature" "\x00" - "PICoolingDemand" "\x00" - "PIHeatingDemand" "\x00" - "LocalTemperatureCalibration" "\x00" - "OccupiedCoolingSetpoint" "\x00" - "OccupiedHeatingSetpoint" "\x00" - "UnoccupiedCoolingSetpoint" "\x00" - "UnoccupiedHeatingSetpoint" "\x00" - "RemoteSensing" "\x00" - "ControlSequenceOfOperation" "\x00" - "SystemMode" "\x00" - "TRVMode" "\x00" - "ValvePosition" "\x00" - "EurotronicErrors" "\x00" - "CurrentTemperatureSetPoint" "\x00" - "ThSetpoint" "\x00" - "TempTarget" "\x00" - "Hue" "\x00" - "Sat" "\x00" - "RemainingTime" "\x00" - "X" "\x00" - "Y" "\x00" - "DriftCompensation" "\x00" - "CompensationText" "\x00" - "CT" "\x00" - "ColorMode" "\x00" - "NumberOfPrimaries" "\x00" - "Primary1X" "\x00" - "Primary1Y" "\x00" - "Primary1Intensity" "\x00" - "Primary2X" "\x00" - "Primary2Y" "\x00" - "Primary2Intensity" "\x00" - "Primary3X" "\x00" - "Primary3Y" "\x00" - "Primary3Intensity" "\x00" - "WhitePointX" "\x00" - "WhitePointY" "\x00" - "ColorPointRX" "\x00" - "ColorPointRY" "\x00" - "ColorPointRIntensity" "\x00" - "ColorPointGX" "\x00" - "ColorPointGY" "\x00" - "ColorPointGIntensity" "\x00" - "ColorPointBX" "\x00" - "ColorPointBY" "\x00" - "ColorPointBIntensity" "\x00" - "Illuminance" "\x00" - "IlluminanceMinMeasuredValue" "\x00" - "IlluminanceMaxMeasuredValue" "\x00" - "IlluminanceTolerance" "\x00" - "IlluminanceLightSensorType" "\x00" - "IlluminanceLevelStatus" "\x00" - "IlluminanceTargetLevel" "\x00" - "Temperature" "\x00" - "TemperatureMinMeasuredValue" "\x00" - "TemperatureMaxMeasuredValue" "\x00" - "TemperatureTolerance" "\x00" - "Pressure" "\x00" - "PressureMinMeasuredValue" "\x00" - "PressureMaxMeasuredValue" "\x00" - "PressureTolerance" "\x00" - "PressureScaledValue" "\x00" - "PressureMinScaledValue" "\x00" - "PressureMaxScaledValue" "\x00" - "PressureScaledTolerance" "\x00" - "PressureScale" "\x00" - "SeaPressure" "\x00" - "FlowRate" "\x00" - "FlowMinMeasuredValue" "\x00" - "FlowMaxMeasuredValue" "\x00" - "FlowTolerance" "\x00" - "Humidity" "\x00" - "HumidityMinMeasuredValue" "\x00" - "HumidityMaxMeasuredValue" "\x00" - "HumidityTolerance" "\x00" - "Occupancy" "\x00" - "OccupancySensorType" "\x00" - "ZoneState" "\x00" - "ZoneType" "\x00" - "ZoneStatus" "\x00" - "CurrentSummDelivered" "\x00" - "CompanyName" "\x00" - "MeterTypeID" "\x00" - "DataQualityID" "\x00" - "CustomerName" "\x00" - "Model" "\x00" - "PartNumber" "\x00" - "ProductRevision" "\x00" - "SoftwareRevision" "\x00" - "UtilityName" "\x00" - "POD" "\x00" - "AvailablePower" "\x00" - "PowerThreshold" "\x00" - "RMSVoltage" "\x00" - "RMSCurrent" "\x00" - "ActivePower" "\x00" - "NumberOfResets" "\x00" - "PersistentMemoryWrites" "\x00" - "LastMessageLQI" "\x00" - "LastMessageRSSI" "\x00" - "TuyaScheduleWorkdays" "\x00" - "TuyaScheduleHolidays" "\x00" - "TuyaChildLock" "\x00" - "TuyaWindowDetection" "\x00" - "TuyaValveDetection" "\x00" - "TuyaAutoLock" "\x00" - "TuyaTempTarget" "\x00" - "TuyaBattery" "\x00" - "TuyaMinTemp" "\x00" - "TuyaMaxTemp" "\x00" - "TuyaBoostTime" "\x00" - "TuyaComfortTemp" "\x00" - "TuyaEcoTemp" "\x00" - "TuyaValvePosition" "\x00" - "TuyaAwayTemp" "\x00" - "TuyaAwayDays" "\x00" - "TuyaPreset" "\x00" - "TuyaFanMode" "\x00" - "TuyaForceMode" "\x00" - "TuyaWeekSelect" "\x00" - "TerncyRotate" "\x00" - "TerncyDuration" "\x00" - "Identify" "\x00" - "xxxx" "\x00" - "IdentifyQuery" "\x00" - "AddGroup" "\x00" - "xxxx00" "\x00" - "ViewGroup" "\x00" - "GetGroup" "\x00" - "01xxxx" "\x00" - "GetAllGroups" "\x00" - "00" "\x00" - "RemoveGroup" "\x00" - "RemoveAllGroups" "\x00" - "ViewScene" "\x00" - "xxxxyy" "\x00" - "RemoveScene" "\x00" - "RemoveAllScenes" "\x00" - "RecallScene" "\x00" - "GetSceneMembership" "\x00" - "PowerOffEffect" "\x00" - "xxyy" "\x00" - "PowerOnRecall" "\x00" - "PowerOnTimer" "\x00" - "xxyyyyzzzz" "\x00" - "xx0A00" "\x00" - "DimmerUp" "\x00" - "00190200" "\x00" - "DimmerDown" "\x00" - "01190200" "\x00" - "DimmerStop" "\x00" - "ResetAlarm" "\x00" - "xxyyyy" "\x00" - "ResetAllAlarms" "\x00" - "xx000A00" "\x00" - "HueSat" "\x00" - "xxyy0A00" "\x00" - "Color" "\x00" - "xxxxyyyy0A00" "\x00" - "xxxx0A00" "\x00" - "ShutterOpen" "\x00" - "ShutterClose" "\x00" - "ShutterStop" "\x00" - "ShutterLift" "\x00" - "xx" "\x00" - "ShutterTilt" "\x00" - "Shutter" "\x00" - "DimmerMove" "\x00" - "xx0A" "\x00" - "DimmerStepUp" "\x00" - "00xx0A00" "\x00" - "DimmerStepDown" "\x00" - "01xx0A00" "\x00" - "DimmerStep" "\x00" - "xx190A00" "\x00" - "01" "\x00" - "HueMove" "\x00" - "xx19" "\x00" - "HueStepUp" "\x00" - "HueStepDown" "\x00" - "03xx0A00" "\x00" - "HueStep" "\x00" - "SatMove" "\x00" - "SatStep" "\x00" - "xx190A" "\x00" - "ColorMove" "\x00" - "xxxxyyyy" "\x00" - "ColorStep" "\x00" - "ColorTempMoveUp" "\x00" - "01xxxx000000000000" "\x00" - "ColorTempMoveDown" "\x00" - "03xxxx000000000000" "\x00" - "ColorTempMoveStop" "\x00" - "00xxxx000000000000" "\x00" - "ColorTempMove" "\x00" - "xxyyyy000000000000" "\x00" - "ColorTempStepUp" "\x00" - "01xxxx0A0000000000" "\x00" - "ColorTempStepDown" "\x00" - "03xxxx0A0000000000" "\x00" - "ColorTempStep" "\x00" - "xxyyyy0A0000000000" "\x00" - "ArrowClick" "\x00" - "ArrowHold" "\x00" - "ArrowRelease" "\x00" - "ZoneStatusChange" "\x00" - "xxxxyyzz" "\x00" - "xxyyzzzz" "\x00" - "AddScene" "\x00" - "xxyyyyzz" "\x00" - "StoreScene" "\x00" - ; - -enum Z_offsets { - Zo_ = 0, - Zo_ZCLVersion = 1, - Zo_AppVersion = 12, - Zo_StackVersion = 23, - Zo_HWVersion = 36, - Zo_Manufacturer = 46, - Zo_ModelId = 59, - Zo_DateCode = 67, - Zo_PowerSource = 76, - Zo_GenericDeviceClass = 88, - Zo_GenericDeviceType = 107, - Zo_ProductCode = 125, - Zo_ProductURL = 137, - Zo_SWBuildID = 148, - Zo_MainsVoltage = 158, - Zo_MainsFrequency = 171, - Zo_BatteryVoltage = 186, - Zo_BatteryPercentage = 201, - Zo_CurrentTemperature = 219, - Zo_MinTempExperienced = 238, - Zo_MaxTempExperienced = 257, - Zo_OverTempTotalDwell = 276, - Zo_IdentifyTime = 295, - Zo_GroupNameSupport = 308, - Zo_SceneCount = 325, - Zo_CurrentScene = 336, - Zo_CurrentGroup = 349, - Zo_SceneValid = 362, - Zo_Power = 373, - Zo_StartUpOnOff = 379, - Zo_SwitchType = 392, - Zo_Dimmer = 403, - Zo_DimmerOptions = 410, - Zo_DimmerRemainingTime = 424, - Zo_OnOffTransitionTime = 444, - Zo_AlarmCount = 464, - Zo_Time = 475, - Zo_TimeStatus = 480, - Zo_TimeZone = 491, - Zo_DstStart = 500, - Zo_DstEnd = 509, - Zo_DstShift = 516, - Zo_StandardTime = 525, - Zo_LocalTime = 538, - Zo_LastSetTime = 548, - Zo_ValidUntilTime = 560, - Zo_TimeEpoch = 575, - Zo_LocationType = 585, - Zo_LocationMethod = 598, - Zo_LocationAge = 613, - Zo_QualityMeasure = 625, - Zo_NumberOfDevices = 640, - Zo_AnalogInDescription = 656, - Zo_AnalogInMaxValue = 676, - Zo_AnalogInMinValue = 693, - Zo_AnalogInOutOfService = 710, - Zo_AqaraRotate = 731, - Zo_AnalogInReliability = 743, - Zo_AnalogInResolution = 763, - Zo_AnalogInStatusFlags = 782, - Zo_AnalogInEngineeringUnits = 802, - Zo_AnalogInApplicationType = 827, - Zo_Aqara_FF05 = 851, - Zo_AnalogOutDescription = 862, - Zo_AnalogOutMaxValue = 883, - Zo_AnalogOutMinValue = 901, - Zo_AnalogOutOutOfService = 919, - Zo_AnalogOutValue = 941, - Zo_AnalogOutReliability = 956, - Zo_AnalogOutRelinquishDefault = 977, - Zo_AnalogOutResolution = 1004, - Zo_AnalogOutStatusFlags = 1024, - Zo_AnalogOutEngineeringUnits = 1045, - Zo_AnalogOutApplicationType = 1071, - Zo_AnalogDescription = 1096, - Zo_AnalogOutOfService = 1114, - Zo_AnalogValue = 1133, - Zo_AnalogPriorityArray = 1145, - Zo_AnalogReliability = 1165, - Zo_AnalogRelinquishDefault = 1183, - Zo_AnalogStatusFlags = 1207, - Zo_AnalogEngineeringUnits = 1225, - Zo_AnalogApplicationType = 1248, - Zo_BinaryInActiveText = 1270, - Zo_BinaryInDescription = 1289, - Zo_BinaryInInactiveText = 1309, - Zo_BinaryInOutOfService = 1330, - Zo_BinaryInPolarity = 1351, - Zo_BinaryInValue = 1368, - Zo_BinaryInReliability = 1382, - Zo_BinaryInStatusFlags = 1402, - Zo_BinaryInApplicationType = 1422, - Zo_BinaryOutActiveText = 1446, - Zo_BinaryOutDescription = 1466, - Zo_BinaryOutInactiveText = 1487, - Zo_BinaryOutMinimumOffTime = 1509, - Zo_BinaryOutMinimumOnTime = 1533, - Zo_BinaryOutOutOfService = 1556, - Zo_BinaryOutPolarity = 1578, - Zo_BinaryOutValue = 1596, - Zo_BinaryOutReliability = 1611, - Zo_BinaryOutRelinquishDefault = 1632, - Zo_BinaryOutStatusFlags = 1659, - Zo_BinaryOutApplicationType = 1680, - Zo_BinaryActiveText = 1705, - Zo_BinaryDescription = 1722, - Zo_BinaryInactiveText = 1740, - Zo_BinaryMinimumOffTime = 1759, - Zo_BinaryMinimumOnTime = 1780, - Zo_BinaryOutOfService = 1800, - Zo_BinaryValue = 1819, - Zo_BinaryReliability = 1831, - Zo_BinaryRelinquishDefault = 1849, - Zo_BinaryStatusFlags = 1873, - Zo_BinaryApplicationType = 1891, - Zo_MultiInDescription = 1913, - Zo_MultiInNumberOfStates = 1932, - Zo_MultiInOutOfService = 1954, - Zo_MultiInValue = 1974, - Zo_MultiInReliability = 1987, - Zo_MultiInStatusFlags = 2006, - Zo_MultiInApplicationType = 2025, - Zo_MultiOutDescription = 2048, - Zo_MultiOutNumberOfStates = 2068, - Zo_MultiOutOutOfService = 2091, - Zo_MultiOutValue = 2112, - Zo_MultiOutReliability = 2126, - Zo_MultiOutRelinquishDefault = 2146, - Zo_MultiOutStatusFlags = 2172, - Zo_MultiOutApplicationType = 2192, - Zo_MultiDescription = 2216, - Zo_MultiNumberOfStates = 2233, - Zo_MultiOutOfService = 2253, - Zo_MultiValue = 2271, - Zo_MultiReliability = 2282, - Zo_MultiRelinquishDefault = 2299, - Zo_MultiStatusFlags = 2322, - Zo_MultiApplicationType = 2339, - Zo_TotalProfileNum = 2360, - Zo_MultipleScheduling = 2376, - Zo_EnergyFormatting = 2395, - Zo_EnergyRemote = 2412, - Zo_ScheduleMode = 2425, - Zo_CheckinInterval = 2438, - Zo_LongPollInterval = 2454, - Zo_ShortPollInterval = 2471, - Zo_FastPollTimeout = 2489, - Zo_CheckinIntervalMin = 2505, - Zo_LongPollIntervalMin = 2524, - Zo_FastPollTimeoutMax = 2544, - Zo_PhysicalClosedLimit = 2563, - Zo_MotorStepSize = 2583, - Zo_Status = 2597, - Zo_ClosedLimit = 2604, - Zo_Mode = 2616, - Zo_LockState = 2621, - Zo_LockType = 2631, - Zo_ActuatorEnabled = 2640, - Zo_DoorState = 2656, - Zo_DoorOpenEvents = 2666, - Zo_DoorClosedEvents = 2681, - Zo_OpenPeriod = 2698, - Zo_AqaraVibrationMode = 2709, - Zo_AqaraVibrationsOrAngle = 2728, - Zo_AqaraVibration505 = 2751, - Zo_AqaraAccelerometer = 2769, - Zo_WindowCoveringType = 2788, - Zo_PhysicalClosedLimitLift = 2807, - Zo_PhysicalClosedLimitTilt = 2831, - Zo_CurrentPositionLift = 2855, - Zo_CurrentPositionTilt = 2875, - Zo_NumberofActuationsLift = 2895, - Zo_NumberofActuationsTilt = 2918, - Zo_ConfigStatus = 2941, - Zo_CurrentPositionLiftPercentage = 2954, - Zo_CurrentPositionTiltPercentage = 2984, - Zo_InstalledOpenLimitLift = 3014, - Zo_InstalledClosedLimitLift = 3037, - Zo_InstalledOpenLimitTilt = 3062, - Zo_InstalledClosedLimitTilt = 3085, - Zo_VelocityLift = 3110, - Zo_AccelerationTimeLift = 3123, - Zo_DecelerationTimeLift = 3144, - Zo_IntermediateSetpointsLift = 3165, - Zo_IntermediateSetpointsTilt = 3191, - Zo_LocalTemperature = 3217, - Zo_OutdoorTemperature = 3234, - Zo_PICoolingDemand = 3253, - Zo_PIHeatingDemand = 3269, - Zo_LocalTemperatureCalibration = 3285, - Zo_OccupiedCoolingSetpoint = 3313, - Zo_OccupiedHeatingSetpoint = 3337, - Zo_UnoccupiedCoolingSetpoint = 3361, - Zo_UnoccupiedHeatingSetpoint = 3387, - Zo_RemoteSensing = 3413, - Zo_ControlSequenceOfOperation = 3427, - Zo_SystemMode = 3454, - Zo_TRVMode = 3465, - Zo_ValvePosition = 3473, - Zo_EurotronicErrors = 3487, - Zo_CurrentTemperatureSetPoint = 3504, - Zo_ThSetpoint = 3531, - Zo_TempTarget = 3542, - Zo_Hue = 3553, - Zo_Sat = 3557, - Zo_RemainingTime = 3561, - Zo_X = 3575, - Zo_Y = 3577, - Zo_DriftCompensation = 3579, - Zo_CompensationText = 3597, - Zo_CT = 3614, - Zo_ColorMode = 3617, - Zo_NumberOfPrimaries = 3627, - Zo_Primary1X = 3645, - Zo_Primary1Y = 3655, - Zo_Primary1Intensity = 3665, - Zo_Primary2X = 3683, - Zo_Primary2Y = 3693, - Zo_Primary2Intensity = 3703, - Zo_Primary3X = 3721, - Zo_Primary3Y = 3731, - Zo_Primary3Intensity = 3741, - Zo_WhitePointX = 3759, - Zo_WhitePointY = 3771, - Zo_ColorPointRX = 3783, - Zo_ColorPointRY = 3796, - Zo_ColorPointRIntensity = 3809, - Zo_ColorPointGX = 3830, - Zo_ColorPointGY = 3843, - Zo_ColorPointGIntensity = 3856, - Zo_ColorPointBX = 3877, - Zo_ColorPointBY = 3890, - Zo_ColorPointBIntensity = 3903, - Zo_Illuminance = 3924, - Zo_IlluminanceMinMeasuredValue = 3936, - Zo_IlluminanceMaxMeasuredValue = 3964, - Zo_IlluminanceTolerance = 3992, - Zo_IlluminanceLightSensorType = 4013, - Zo_IlluminanceLevelStatus = 4040, - Zo_IlluminanceTargetLevel = 4063, - Zo_Temperature = 4086, - Zo_TemperatureMinMeasuredValue = 4098, - Zo_TemperatureMaxMeasuredValue = 4126, - Zo_TemperatureTolerance = 4154, - Zo_Pressure = 4175, - Zo_PressureMinMeasuredValue = 4184, - Zo_PressureMaxMeasuredValue = 4209, - Zo_PressureTolerance = 4234, - Zo_PressureScaledValue = 4252, - Zo_PressureMinScaledValue = 4272, - Zo_PressureMaxScaledValue = 4295, - Zo_PressureScaledTolerance = 4318, - Zo_PressureScale = 4342, - Zo_SeaPressure = 4356, - Zo_FlowRate = 4368, - Zo_FlowMinMeasuredValue = 4377, - Zo_FlowMaxMeasuredValue = 4398, - Zo_FlowTolerance = 4419, - Zo_Humidity = 4433, - Zo_HumidityMinMeasuredValue = 4442, - Zo_HumidityMaxMeasuredValue = 4467, - Zo_HumidityTolerance = 4492, - Zo_Occupancy = 4510, - Zo_OccupancySensorType = 4520, - Zo_ZoneState = 4540, - Zo_ZoneType = 4550, - Zo_ZoneStatus = 4559, - Zo_CurrentSummDelivered = 4570, - Zo_CompanyName = 4591, - Zo_MeterTypeID = 4603, - Zo_DataQualityID = 4615, - Zo_CustomerName = 4629, - Zo_Model = 4642, - Zo_PartNumber = 4648, - Zo_ProductRevision = 4659, - Zo_SoftwareRevision = 4675, - Zo_UtilityName = 4692, - Zo_POD = 4704, - Zo_AvailablePower = 4708, - Zo_PowerThreshold = 4723, - Zo_RMSVoltage = 4738, - Zo_RMSCurrent = 4749, - Zo_ActivePower = 4760, - Zo_NumberOfResets = 4772, - Zo_PersistentMemoryWrites = 4787, - Zo_LastMessageLQI = 4810, - Zo_LastMessageRSSI = 4825, - Zo_TuyaScheduleWorkdays = 4841, - Zo_TuyaScheduleHolidays = 4862, - Zo_TuyaChildLock = 4883, - Zo_TuyaWindowDetection = 4897, - Zo_TuyaValveDetection = 4917, - Zo_TuyaAutoLock = 4936, - Zo_TuyaTempTarget = 4949, - Zo_TuyaBattery = 4964, - Zo_TuyaMinTemp = 4976, - Zo_TuyaMaxTemp = 4988, - Zo_TuyaBoostTime = 5000, - Zo_TuyaComfortTemp = 5014, - Zo_TuyaEcoTemp = 5030, - Zo_TuyaValvePosition = 5042, - Zo_TuyaAwayTemp = 5060, - Zo_TuyaAwayDays = 5073, - Zo_TuyaPreset = 5086, - Zo_TuyaFanMode = 5097, - Zo_TuyaForceMode = 5109, - Zo_TuyaWeekSelect = 5123, - Zo_TerncyRotate = 5138, - Zo_TerncyDuration = 5151, - Zo_Identify = 5166, - Zo_xxxx = 5175, - Zo_IdentifyQuery = 5180, - Zo_AddGroup = 5194, - Zo_xxxx00 = 5203, - Zo_ViewGroup = 5210, - Zo_GetGroup = 5220, - Zo_01xxxx = 5229, - Zo_GetAllGroups = 5236, - Zo_00 = 5249, - Zo_RemoveGroup = 5252, - Zo_RemoveAllGroups = 5264, - Zo_ViewScene = 5280, - Zo_xxxxyy = 5290, - Zo_RemoveScene = 5297, - Zo_RemoveAllScenes = 5309, - Zo_RecallScene = 5325, - Zo_GetSceneMembership = 5337, - Zo_PowerOffEffect = 5356, - Zo_xxyy = 5371, - Zo_PowerOnRecall = 5376, - Zo_PowerOnTimer = 5390, - Zo_xxyyyyzzzz = 5403, - Zo_xx0A00 = 5414, - Zo_DimmerUp = 5421, - Zo_00190200 = 5430, - Zo_DimmerDown = 5439, - Zo_01190200 = 5450, - Zo_DimmerStop = 5459, - Zo_ResetAlarm = 5470, - Zo_xxyyyy = 5481, - Zo_ResetAllAlarms = 5488, - Zo_xx000A00 = 5503, - Zo_HueSat = 5512, - Zo_xxyy0A00 = 5519, - Zo_Color = 5528, - Zo_xxxxyyyy0A00 = 5534, - Zo_xxxx0A00 = 5547, - Zo_ShutterOpen = 5556, - Zo_ShutterClose = 5568, - Zo_ShutterStop = 5581, - Zo_ShutterLift = 5593, - Zo_xx = 5605, - Zo_ShutterTilt = 5608, - Zo_Shutter = 5620, - Zo_DimmerMove = 5628, - Zo_xx0A = 5639, - Zo_DimmerStepUp = 5644, - Zo_00xx0A00 = 5657, - Zo_DimmerStepDown = 5666, - Zo_01xx0A00 = 5681, - Zo_DimmerStep = 5690, - Zo_xx190A00 = 5701, - Zo_01 = 5710, - Zo_HueMove = 5713, - Zo_xx19 = 5721, - Zo_HueStepUp = 5726, - Zo_HueStepDown = 5736, - Zo_03xx0A00 = 5748, - Zo_HueStep = 5757, - Zo_SatMove = 5765, - Zo_SatStep = 5773, - Zo_xx190A = 5781, - Zo_ColorMove = 5788, - Zo_xxxxyyyy = 5798, - Zo_ColorStep = 5807, - Zo_ColorTempMoveUp = 5817, - Zo_01xxxx000000000000 = 5833, - Zo_ColorTempMoveDown = 5852, - Zo_03xxxx000000000000 = 5870, - Zo_ColorTempMoveStop = 5889, - Zo_00xxxx000000000000 = 5907, - Zo_ColorTempMove = 5926, - Zo_xxyyyy000000000000 = 5940, - Zo_ColorTempStepUp = 5959, - Zo_01xxxx0A0000000000 = 5975, - Zo_ColorTempStepDown = 5994, - Zo_03xxxx0A0000000000 = 6012, - Zo_ColorTempStep = 6031, - Zo_xxyyyy0A0000000000 = 6045, - Zo_ArrowClick = 6064, - Zo_ArrowHold = 6075, - Zo_ArrowRelease = 6085, - Zo_ZoneStatusChange = 6098, - Zo_xxxxyyzz = 6115, - Zo_xxyyzzzz = 6124, - Zo_AddScene = 6133, - Zo_xxyyyyzz = 6142, - Zo_StoreScene = 6151, -}; - - - - - - - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -#ifdef USE_ZIGBEE - - - - - - -enum Z_DataTypes { - Znodata = 0x00, - Zdata8 = 0x08, Zdata16, Zdata24, Zdata32, Zdata40, Zdata48, Zdata56, Zdata64, - Zbool = 0x10, - Zmap8 = 0x18, Zmap16, Zmap24, Zmap32, Zmap40, Zmap48, Zmap56, Zmap64, - Zuint8 = 0x20, Zuint16, Zuint24, Zuint32, Zuint40, Zuint48, Zuint56, Zuint64, - Zint8 = 0x28, Zint16, Zint24, Zint32, Zint40, Zint48, Zint56, Zint64, - Zenum8 = 0x30, Zenum16 = 0x31, - Zsemi = 0x38, Zsingle = 0x39, Zdouble = 0x3A, - Zoctstr = 0x41, Zstring = 0x42, Zoctstr16 = 0x43, Zstring16 = 0x44, - Arrray = 0x48, - Zstruct = 0x4C, - Zset = 0x50, Zbag = 0x51, - ZToD = 0xE0, Zdate = 0xE1, ZUTC = 0xE2, - ZclusterId = 0xE8, ZattribId = 0xE9, ZbacOID = 0xEA, - ZEUI64 = 0xF0, Zkey128 = 0xF1, - Zunk = 0xFF, - - Ztuya1 = 0x80, - Ztuya2 = 0x81, - Ztuya4 = 0x82, -}; - - - - - - -uint8_t Z_getDatatypeLen(uint8_t t) { - if ( ((t >= 0x08) && (t <= 0x0F)) || - ((t >= 0x18) && (t <= 0x2F)) ) { - return (t & 0x07) + 1; - } - switch (t) { - case Zbool: - case Zenum8: - return 1; - case Zenum16: - case Zsemi: - case ZclusterId: - case ZattribId: - case Ztuya1: - return 2; - case Ztuya2: - return 3; - case Zsingle: - case ZToD: - case Zdate: - case ZUTC: - case ZbacOID: - return 4; - case Ztuya4: - return 5; - case Zdouble: - case ZEUI64: - return 8; - case Zkey128: - return 16; - case Znodata: - default: - return 0; - } -} - - -bool Z_isDiscreteDataType(uint8_t t) { - if ( ((t >= 0x20) && (t <= 0x2F)) || - ((t >= 0x38) && (t <= 0x3A)) || - ((t >= 0xE0) && (t <= 0xE2)) ) { - return false; - } else { - return true; - } -} - -typedef struct Z_AttributeConverter { - uint8_t type; - uint8_t cluster_short; - uint16_t attribute; - uint16_t name_offset; - uint8_t multiplier_idx; - - - uint8_t mapping; - -} Z_AttributeConverter; - - -#define Z_OFFSET(c,a) (offsetof(class c, a) - sizeof(Z_Data)) -#define Z_CLASS(c) c -#define Z_MAPPING(c,a) (((((uint8_t)Z_CLASS(c)::type) & 0x0F) << 4) | Z_OFFSET(c,a)) - - - -const uint8_t Z_EXPORT_DATA = 0x80; - - - - -enum Cx_cluster_short { - Cx0000, Cx0001, Cx0002, Cx0003, Cx0004, Cx0005, Cx0006, Cx0007, - Cx0008, Cx0009, Cx000A, Cx000B, Cx000C, Cx000D, Cx000E, Cx000F, - Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100, - Cx0101, Cx0102, Cx0201, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403, - Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05, - CxEF00, CxFCCC, -}; - -const uint16_t Cx_cluster[] PROGMEM = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100, - 0x0101, 0x0102, 0x0201, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403, - 0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05, - 0xEF00, 0xFCCC, -}; - -uint16_t CxToCluster(uint8_t cx) { - if (cx < ARRAY_SIZE(Cx_cluster)) { - return pgm_read_word(&Cx_cluster[cx]); - } - return 0xFFFF; -} - -uint8_t ClusterToCx(uint16_t cluster) { - for (uint32_t i=0; iname_offset)) { continue; } - if (0 == strcasecmp_P(command, Z_strings + pgm_read_word(&converter->name_offset))) { - if (cluster) { *cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); } - if (attribute) { *attribute = pgm_read_word(&converter->attribute); } - if (multiplier) { *multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); } - if (zigbee_type) { *zigbee_type = pgm_read_byte(&converter->type); } - uint8_t conv_mapping = pgm_read_byte(&converter->mapping); - if (data_type) { *data_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4); } - if (map_offset) { *map_offset = (conv_mapping & 0x0F); } - return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&converter->name_offset)); - } - } - return nullptr; -} - - - - -const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t attr_id, - uint8_t *attr_type, int8_t *multiplier) { - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint16_t conv_attr_id = pgm_read_word(&converter->attribute); - - if ((conv_cluster == cluster) && (conv_attr_id == attr_id)) { - if (multiplier) { *multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); } - if (attr_type) { *attr_type = pgm_read_byte(&converter->type); } - return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&converter->name_offset)); - } - } - return nullptr; -} - -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, uint16_t groupaddr, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber): - _manuf_code(manuf_code), _transact_seq(transact_seq), _cmd_id(cmd_id), - _payload(buf_len ? buf_len : 250), - _cluster_id(clusterid), _groupaddr(groupaddr), - _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), - _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber) - { - _frame_control.d8 = frame_control; - _payload.addBuffer(buf, buf_len); - }; - - - void log(void) { - 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_ZIGBEEZCL_RECEIVED "\":{" - "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," - "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," - "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," - "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), - _groupaddr, _cluster_id, _srcaddr, - _srcendpoint, _dstendpoint, _wasbroadcast, - _linkquality, _securityuse, _seqnumber, - _frame_control, _manuf_code, _transact_seq, _cmd_id, - hex_char); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - } - - static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber) { - 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, - srcaddr, srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber); - return zcl_frame; - } - - bool isClusterSpecificCommand(void) { - return _frame_control.b.frame_type & 1; - } - - void parseReportAttributes(Z_attribute_list& attr_list); - void generateSyntheticAttributes(Z_attribute_list& attr_list); - void computeSyntheticAttributes(Z_attribute_list& attr_list); - void generateCallBacks(Z_attribute_list& attr_list); - void parseReadAttributes(Z_attribute_list& attr_list); - void parseReadAttributesResponse(Z_attribute_list& attr_list); - void parseReadConfigAttributes(Z_attribute_list& attr_list); - void parseConfigAttributes(Z_attribute_list& attr_list); - void parseResponse(void); - void parseResponseOld(void); - void parseClusterSpecificCommand(Z_attribute_list& attr_list); - void postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list); - - - void syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr); - void syntheticAqaraSensor2(Z_attribute_list &attr_list, class Z_attribute &attr); - void syntheticAqaraCubeOrButton(Z_attribute_list &attr_list, class Z_attribute &attr); - void syntheticAqaraVibration(Z_attribute_list &attr_list, class Z_attribute &attr); - - - void autoResponder(const uint16_t *attr_list_ids, size_t attr_len); - - inline void setGroupId(uint16_t groupid) { - _groupaddr = groupid; - } - - inline void setClusterId(uint16_t clusterid) { - _cluster_id = clusterid; - } - - inline uint16_t getSrcAddr(void) const { return _srcaddr; } - inline uint16_t getGroupAddr(void) const { return _groupaddr; } - inline uint16_t getClusterId(void) const { return _cluster_id; } - inline uint8_t getLinkQuality(void) const { return _linkquality; } - inline uint8_t getCmdId(void) const { return _cmd_id; } - inline uint16_t getSrcEndpoint(void) const { return _srcendpoint; } - - const SBuffer &getPayload(void) const { - return _payload; - } - - uint16_t getManufCode(void) const { - return _manuf_code; - } - - -private: - ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; - uint16_t _manuf_code = 0; - uint8_t _transact_seq = 0; - uint8_t _cmd_id = 0; - SBuffer _payload; - uint16_t _cluster_id = 0; - uint16_t _groupaddr = 0; - - uint16_t _srcaddr; - uint8_t _srcendpoint; - uint8_t _dstendpoint; - uint8_t _wasbroadcast; - uint8_t _linkquality; - uint8_t _securityuse; - uint8_t _seqnumber; -}; - - - - - - -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; -} - - - - - - -int32_t encodeSingleAttribute(class SBuffer &buf, double val_d, const char *val_str, uint8_t attrtype) { - uint32_t len = Z_getDatatypeLen(attrtype); - uint32_t u32 = val_d; - int32_t i32 = val_d; - float f32 = val_d; - - switch (attrtype) { - - case Zbool: - case Zuint8: - case Zenum8: - case Zdata8: - case Zmap8: - buf.add8(u32); - break; - case Ztuya1: - buf.add8(1); - buf.add8(u32); - break; - - case Zuint16: - case Zenum16: - case Zdata16: - case Zmap16: - buf.add16(u32); - break; - case Ztuya2: - buf.add8(2); - buf.add16BigEndian(u32); - - case Zuint32: - case Zdata32: - case Zmap32: - case ZUTC: - buf.add32(u32); - break; - - - case Zint8: - buf.add8(i32); - break; - case Zint16: - buf.add16(i32); - break; - case Zint32: - buf.add32(i32); - break; - case Ztuya4: - buf.add8(4); - buf.add32BigEndian(i32); - break; - - case Zsingle: - uint32_t *f_ptr; - buf.add32( *((uint32_t*)&f32) ); - break; - - case Zstring: - case Zstring16: - { - if (nullptr == val_str) { return -2; } - size_t val_len = strlen(val_str); - if (val_len > 32) { val_len = 32; } - len = val_len + 1; - buf.add8(val_len); - if (Zstring16 == attrtype) { - buf.add8(0); - len++; - } - for (uint32_t i = 0; i < val_len; i++) { - buf.add8(val_str[i]); - } - } - break; - - default: - return -1; - } - return len; -} -# 924 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf, - uint32_t offset, int32_t attrtype = -1) { - - uint32_t i = offset; - if (attrtype < 0) { - attrtype = buf.get8(i++); - } - - - attr.setNone(); - - uint32_t len = Z_getDatatypeLen(attrtype); - - - switch (attrtype) { - - - - case Zbool: - case Zuint8: - case Zenum8: - { - uint8_t uint8_val = buf.get8(i); - - if (0xFF != uint8_val) { - attr.setUInt(uint8_val); - } - } - break; - case Zuint16: - case Zenum16: - { - uint16_t uint16_val = buf.get16(i); - - if (0xFFFF != uint16_val) { - attr.setUInt(uint16_val); - } - } - break; - case Zuint32: - case ZUTC: - { - uint32_t uint32_val = buf.get32(i); - - if (0xFFFFFFFF != uint32_val) { - attr.setUInt(uint32_val); - } - } - break; - case Ztuya1: - attr.setUInt(buf.get8(i+1)); - break; - case Ztuya2: - attr.setUInt(buf.get16BigEndian(i+1)); - break; - case Ztuya4: - attr.setInt(buf.get32IBigEndian(i+1)); - break; - - - case Zuint40: - case Zuint48: - case Zuint56: - case Zuint64: - case Zint40: - case Zint48: - case Zint56: - case Zint64: - { - - - char hex[2*len+3]; - snprintf_P(hex, sizeof(hex), PSTR("0x")); - for (uint32_t j=0; j buf.len()) { - len = buf.len() - i; - } - - - if ((Zoctstr == attrtype) || (Zoctstr16 == attrtype)) { parse_as_string = false; } - - if (parse_as_string) { - char str[len+1]; - strncpy(str, buf.charptr(i), len); - str[len] = 0x00; - attr.setStr(str); - } else { - attr.setBuf(buf, i, len); - } - - - - } - - break; - - case Zstruct: - { - uint16_t struct_size = buf.get16(i); - len = 2; - if (0xFFFF != struct_size) { - if (struct_size > 16) { struct_size = 16; } - - for (uint32_t j = 0; j < struct_size; j++) { - uint8_t attr_type = buf.get8(i+len); - len += Z_getDatatypeLen(attr_type) + 1; - } - attr.setBuf(buf, i, len); - } - } - break; - - case Zdata8: - case Zmap8: - { - uint8_t uint8_val = buf.get8(i); - - attr.setUInt(uint8_val); - } - break; - case Zdata16: - case Zmap16: - { - uint16_t uint16_val = buf.get16(i); - - attr.setUInt(uint16_val); - } - break; - case Zdata32: - case Zmap32: - { - uint32_t uint32_val = buf.get32(i); - - attr.setUInt(uint32_val); - } - break; - - case Zsingle: - { - uint32_t uint32_val = buf.get32(i); - float * float_val = (float*) &uint32_val; - - attr.setFloat(*float_val); - } - break; - - - case ZToD: - case Zdate: - case ZclusterId: - case ZattribId: - case ZbacOID: - case ZEUI64: - case Zkey128: - case Zsemi: - break; - - - case Zdata24: - case Zdata40: - case Zdata48: - case Zdata56: - case Zdata64: - break; - - case Zmap24: - case Zmap40: - case Zmap48: - case Zmap56: - case Zmap64: - break; - case Zdouble: - { - uint64_t uint64_val = buf.get64(i); - double * double_val = (double*) &uint64_val; - - attr.setFloat((float) *double_val); - } - break; - } - i += len; - - return i - offset; -} - - -void ZCLFrame::parseReportAttributes(Z_attribute_list& attr_list) { - uint32_t i = 0; - uint32_t len = _payload.len(); - - while (len >= i + 3) { - uint16_t attrid = _payload.get16(i); - i += 2; - - - if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { - if (0x42 == _payload.get8(i)) { - _payload.set8(i, 0x41); - } - } - - - Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid); - - i += parseSingleAttribute(attr, _payload, i); - } - - - - if (0 == _frame_control.b.disable_def_resp) { - - SBuffer buf(2); - buf.add8(_cmd_id); - buf.add8(0x00); - - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - _srcaddr, - 0x0000, - _cluster_id, - _srcendpoint, - ZCL_DEFAULT_RESPONSE, - _manuf_code, - false , - false , - true , - _transact_seq, - buf.getBuffer(), buf.len() - })); - } -} - - - - -void ZCLFrame::generateSyntheticAttributes(Z_attribute_list& attr_list) { - - for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; - - switch (ccccaaaa) { - case 0x0000FF01: - syntheticAqaraSensor(attr_list, attr); - break; - case 0x0000FF02: - syntheticAqaraSensor2(attr_list, attr); - break; - case 0x00120055: - syntheticAqaraCubeOrButton(attr_list, attr); - break; - case 0x01010055: - case 0x01010508: - syntheticAqaraVibration(attr_list, attr); - break; - } - } -} - - - - - -void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { - - for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; - - switch (ccccaaaa) { - case 0x00010020: - if (attr_list.countAttribute(0x0001,0x0021) == 0) { - uint32_t mv = attr.getUInt()*100; - attr_list.addAttribute(0x0001, 0x0021).setUInt(toPercentageCR2032(mv) * 2); - } - break; - case 0x02010008: - { - const char * manufacturer_c = zigbee_devices.getManufacturerId(_srcaddr); - String manufacturerId((char*) manufacturer_c); - if (manufacturerId.equals(F("Eurotronic"))) { - - uint8_t valve = attr.getUInt(); - if (attr.isNone()) { valve = 255; } - uint8_t valve_100 = changeUIntScale(valve, 0, 255, 0, 100); - attr.setUInt(valve_100); - } - } - break; - case 0x04030000: - { - int16_t pressure = attr.getInt(); - int16_t pressure_sealevel = (pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0f), 5.255f)) - 21.6f; - attr_list.addAttribute(0x0403, 0xFFF0).setInt(pressure_sealevel); - - } - break; - } - } -} - - - -void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) { - static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; - - for (auto &attr : attr_list) { - if (attr.key_is_str) { continue; } - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; - - switch (ccccaaaa) { - case 0x04060000: - uint32_t occupancy = attr.getUInt(); - if (occupancy) { - zigbee_devices.setTimer(_srcaddr, 0 , OCCUPANCY_TIMEOUT, _cluster_id, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback); - } else { - zigbee_devices.resetTimersForDevice(_srcaddr, 0 , Z_CAT_VIRTUAL_OCCUPANCY); - } - break; - } - } -} - - - - - -void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint = 0) { - uint32_t wait_ms = 0xFFFF; - - switch (cluster) { - case 0x0006: - wait_ms = 200; - break; - case 0x0008: - wait_ms = 1050; - break; - case 0x0102: - wait_ms = 10000; - break; - case 0x0300: - wait_ms = 1050; - break; - default: - break; - } - if (0xFFFF != wait_ms) { - if ((BAD_SHORTADDR != shortaddr) && (0 == endpoint)) { - endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - } - if ((BAD_SHORTADDR == shortaddr) || (endpoint)) { - zigbee_devices.queueTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); - if (BAD_SHORTADDR != shortaddr) { - zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 , &Z_Unreachable); - } - - } - } -} - - -void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { - uint32_t i = 0; - uint32_t len = _payload.len(); - - uint16_t read_attr_ids[len/2]; - - attr_list.addAttribute(F(D_CMND_ZIGBEE_CLUSTER)).setUInt(_cluster_id); - - Z_json_array attr_numbers; - Z_attribute_list attr_names; - while (len >= 2 + i) { - uint16_t attrid = _payload.get16(i); - attr_numbers.add(attrid); - read_attr_ids[i/2] = attrid; - - - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint16_t conv_attribute = pgm_read_word(&converter->attribute); - - if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) { - attr_names.addAttribute(Z_strings + pgm_read_word(&converter->name_offset), true).setBool(true); - break; - } - } - i += 2; - } - attr_list.addAttribute(F("Read")).setStrRaw(attr_numbers.toString().c_str()); - attr_list.addAttribute(F("ReadNames")).setStrRaw(attr_names.toString(true).c_str()); - - - autoResponder(read_attr_ids, len/2); -} - - -void ZCLFrame::parseConfigAttributes(Z_attribute_list& attr_list) { - uint32_t len = _payload.len(); - - Z_attribute_list attr_config_list; - for (uint32_t i=0; len >= i+4; i+=4) { - uint8_t status = _payload.get8(i); - uint16_t attr_id = _payload.get8(i+2); - - Z_attribute_list attr_config_response; - attr_config_response.addAttribute(F("Status")).setUInt(status); - attr_config_response.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); - - const __FlashStringHelper* attr_name = zigbeeFindAttributeById(_cluster_id, attr_id, nullptr, nullptr); - if (attr_name) { - attr_config_list.addAttribute(attr_name).setStrRaw(attr_config_response.toString(true).c_str()); - } else { - attr_config_list.addAttribute(_cluster_id, attr_id).setStrRaw(attr_config_response.toString(true).c_str()); - } - } - - Z_attribute &attr_1 = attr_list.addAttribute(F("ConfigResponse")); - attr_1.setStrRaw(attr_config_list.toString(true).c_str()); -} - - -void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) { - uint32_t i = 0; - uint32_t len = _payload.len(); - - Z_attribute &attr_root = attr_list.addAttribute(F("ReadConfig")); - Z_attribute_list attr_1; - - while (len >= i + 4) { - uint8_t status = _payload.get8(i); - uint8_t direction = _payload.get8(i+1); - uint16_t attrid = _payload.get16(i+2); - - Z_attribute_list attr_2; - if (direction) { - attr_2.addAttribute(F("DirectionReceived")).setBool(true); - } - - - int8_t multiplier = 1; - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint16_t conv_attribute = pgm_read_word(&converter->attribute); - - if ((conv_cluster == _cluster_id) && (conv_attribute == attrid)) { - const char * attr_name = Z_strings + pgm_read_word(&converter->name_offset); - attr_2.addAttribute(attr_name, true).setBool(true); - multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); - break; - } - } - i += 4; - if (0 != status) { - attr_2.addAttribute(F("Status")).setUInt(status); - attr_2.addAttribute(F("StatusMsg")).setStr(getZigbeeStatusMessage(status).c_str()); - } else { - - if (direction) { - - uint16_t attr_timeout = _payload.get16(i); - i += 2; - attr_2.addAttribute(F("TimeoutPeriod")).setUInt((0xFFFF == attr_timeout) ? -1 : attr_timeout); - } else { - - uint8_t attr_type = _payload.get8(i); - bool attr_discrete = Z_isDiscreteDataType(attr_type); - uint16_t attr_min_interval = _payload.get16(i+1); - uint16_t attr_max_interval = _payload.get16(i+3); - i += 5; - attr_2.addAttribute(F("MinInterval")).setUInt((0xFFFF == attr_min_interval) ? -1 : attr_min_interval); - attr_2.addAttribute(F("MaxInterval")).setUInt((0xFFFF == attr_max_interval) ? -1 : attr_max_interval); - if (!attr_discrete) { - - Z_attribute &attr_change = attr_2.addAttribute(F("ReportableChange")); - i += parseSingleAttribute(attr_change, _payload, i, attr_type); - if ((1 != multiplier) && (0 != multiplier)) { - float fval = attr_change.getFloat(); - if (multiplier > 0) { fval = fval * multiplier; } - else { fval = fval / (-multiplier); } - attr_change.setFloat(fval); - } - } - } - } - attr_1.addAttribute(_cluster_id, attrid).setStrRaw(attr_2.toString(true).c_str()); - } - attr_root.setStrRaw(attr_1.toString(true).c_str()); -} - - -void ZCLFrame::parseReadAttributesResponse(Z_attribute_list& attr_list) { - uint32_t i = 0; - uint32_t len = _payload.len(); - - while (len >= i + 4) { - uint16_t attrid = _payload.get16(i); - i += 2; - uint8_t status = _payload.get8(i++); - - if (0 == status) { - Z_attribute & attr = attr_list.addAttribute(_cluster_id, attrid); - i += parseSingleAttribute(attr, _payload, i); - } - } -} - - -void ZCLFrame::parseResponse(void) { - if (_payload.len() < 2) { return; } - uint8_t cmd = _payload.get8(0); - uint8_t status = _payload.get8(1); - - Z_attribute_list attr_list; - - - char s[12]; - snprintf_P(s, sizeof(s), PSTR("0x%04X"), _srcaddr); - attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(s); - - const char * friendlyName = zigbee_devices.getFriendlyName(_srcaddr); - if (friendlyName) { - attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(friendlyName); - } - - snprintf_P(s, sizeof(s), PSTR("%04X!%02X"), _cluster_id, cmd); - attr_list.addAttribute(F(D_JSON_ZIGBEE_CMD)).setStr(s); - - attr_list.addAttribute(F(D_JSON_ZIGBEE_STATUS)).setUInt(status); - - attr_list.addAttribute(F(D_JSON_ZIGBEE_STATUS_MSG)).setStr(getZigbeeStatusMessage(status).c_str()); - - attr_list.addAttribute(F(D_CMND_ZIGBEE_ENDPOINT)).setUInt(_srcendpoint); - - if (_groupaddr) { - attr_list.group_id = _groupaddr; - } - - attr_list.lqi = _linkquality; - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RESPONSE "\":%s}"), attr_list.toString(true).c_str()); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); -} - - -void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) { - convertClusterSpecific(attr_list, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload); -#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES - if (!_frame_control.b.direction) { - if (_wasbroadcast) { - sendHueUpdate(BAD_SHORTADDR, _groupaddr, _cluster_id); - } - } -#endif -} - - - -void ZCLFrame::syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr) { - const SBuffer * buf = attr.getRaw(); - if (buf) { - const SBuffer & buf2 = *buf; - uint32_t i = 0; - uint32_t len = buf2.len(); - - const char * modelId_c = zigbee_devices.getModelId(_srcaddr); - String modelId((char*) modelId_c); - - while (len >= 2 + i) { - uint8_t attrid = buf2.get8(i++); - - Z_attribute attr; - i += parseSingleAttribute(attr, buf2, i); - int32_t ival32 = attr.getInt(); - uint32_t uval32 = attr.getUInt(); - bool translated = false; - if (0x01 == attrid) { - float batteryvoltage = attr.getFloat() / 100; - attr_list.addAttribute(0x0001, 0x0020).setFloat(batteryvoltage); - uint8_t batterypercentage = toPercentageCR2032(uval32); - attr_list.addAttribute(0x0001, 0x0021).setUInt(batterypercentage * 2); - } else if ((nullptr != modelId) && (0 == getManufCode())) { - translated = true; - if (modelId.startsWith(F("lumi.sensor_ht")) || - modelId.equals(F("lumi.sens")) || - modelId.startsWith(F("lumi.weather"))) { - - - if (0x64 == attrid) { - attr_list.addAttribute(0x0402, 0x0000).setInt(ival32); - } else if (0x65 == attrid) { - attr_list.addAttribute(0x0405, 0x0000).setUInt(uval32); - } else if (0x66 == attrid) { - attr_list.addAttribute(0x0403, 0x0000).setUInt((ival32 + 50) / 100); - } - } else if (modelId.startsWith(F("lumi.sensor_smoke"))) { - if (0x64 == attrid) { - attr_list.addAttribute(F("SmokeDensity")).copyVal(attr); - } - } else if (modelId.startsWith(F("lumi.sensor_natgas"))) { - if (0x64 == attrid) { - attr_list.addAttribute(F("GasDensity")).copyVal(attr); - } - } else { - translated = false; - } - - } - if (!translated) { - if (attrid >= 100) { - char attr_name[12]; - snprintf_P(attr_name, sizeof(attr_name), PSTR("Xiaomi_%02X"), attrid); - attr_list.addAttribute(attr_name).copyVal(attr); - } - } - } - } -} - -void ZCLFrame::syntheticAqaraSensor2(class Z_attribute_list &attr_list, class Z_attribute &attr) { - const SBuffer * buf = attr.getRaw(); - if (buf) { - const SBuffer & buf2 = *buf; - uint32_t len = buf2.len(); - - - uint16_t struct_size = buf2.get16(0); - size_t struct_len = 2; - if (0xFFFF != struct_size) { - if (struct_size > 16) { struct_size = 16; } - for (uint32_t j = 0; (j < struct_size) && (struct_len < len); j++) { - uint8_t attr_type = buf2.get8(struct_len); - if (0x21 == attr_type) { - uint16_t val = buf2.get16(struct_len+1); - float batteryvoltage = (float)val / 100; - attr_list.addAttribute(0x0001, 0x0020).setFloat(batteryvoltage); - uint8_t batterypercentage = toPercentageCR2032(val); - attr_list.addAttribute(0x0001, 0x0021).setUInt(batterypercentage * 2); - break; - } - struct_len += Z_getDatatypeLen(attr_type) + 1; - } - } - } - attr_list.removeAttribute(&attr); -} - - -void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, class Z_attribute &attr) { - const char * modelId_c = zigbee_devices.findShortAddr(_srcaddr).modelId; - String modelId((char*) modelId_c); - - if (modelId.startsWith(F("lumi.sensor_cube"))) { - int32_t val = attr.getInt(); - const __FlashStringHelper *aqara_cube = F("AqaraCube"); - const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); - const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); - - switch (val) { - case 0: - attr_list.addAttribute(aqara_cube).setStr(PSTR("shake")); - break; - case 2: - attr_list.addAttribute(aqara_cube).setStr(PSTR("wakeup")); - break; - case 3: - attr_list.addAttribute(aqara_cube).setStr(PSTR("fall")); - break; - case 64 ... 127: - attr_list.addAttribute(aqara_cube).setStr(PSTR("flip90")); - attr_list.addAttribute(aqara_cube_side).setInt(val % 8); - attr_list.addAttribute(aqara_cube_from_side).setInt((val - 64) / 8); - break; - case 128 ... 132: - attr_list.addAttribute(aqara_cube).setStr(PSTR("flip180")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 128); - break; - case 256 ... 261: - attr_list.addAttribute(aqara_cube).setStr(PSTR("slide")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 256); - break; - case 512 ... 517: - attr_list.addAttribute(aqara_cube).setStr(PSTR("tap")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 512); - break; - } - attr_list.removeAttribute(&attr); -# 1672 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - } else if (modelId.startsWith(F("lumi.remote")) || modelId.startsWith(F("lumi.sensor_switch"))) { - int32_t val = attr.getInt(); - const __FlashStringHelper *aqara_click = F("click"); - const __FlashStringHelper *aqara_action = F("action"); - - switch (val) { - case 0: - attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); - break; - case 1: - attr_list.addAttribute(aqara_click).setStr(PSTR("single")); - break; - case 2: - attr_list.addAttribute(aqara_click).setStr(PSTR("double")); - break; - case 16: - attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); - break; - case 17: - attr_list.addAttribute(aqara_action).setStr(PSTR("release")); - break; - case 18: - attr_list.addAttribute(aqara_action).setStr(PSTR("shake")); - break; - case 255: - attr_list.addAttribute(aqara_action).setStr(PSTR("release")); - break; - default: - attr_list.addAttribute(aqara_click).setUInt(val); - break; - } - } -} - - -void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class Z_attribute &attr) { - switch (attr.key.id.attr_id) { - case 0x0055: - { - int32_t ivalue = attr.getInt(); - const __FlashStringHelper * svalue; - switch (ivalue) { - case 1: svalue = F("vibrate"); break; - case 2: svalue = F("tilt"); break; - case 3: svalue = F("drop"); break; - default: svalue = F("unknown"); break; - } - attr.setStr((const char*)svalue); - } - break; - case 0x0503: - break; - case 0x0505: - break; - case 0x0508: - { - - - const SBuffer * buf = attr.getRaw(); - if (buf) { - const SBuffer & buf2 = *buf; - int16_t x, y, z; - z = buf2.get16(0); - y = buf2.get16(2); - x = buf2.get16(4); - char temp[32]; - snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", x, y, z); - attr.setStrRaw(temp); - - float X = x; - float Y = y; - float Z = z; - int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; - int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; - int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; - snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", Angle_X, Angle_Y, Angle_Z); - attr_list.addAttribute(F("AqaraAngles")).setStrRaw(temp); - } - } - break; - } -} - - -void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - Z_attribute_list attr_list; - attr_list.addAttribute(F(OCCUPANCY)).setUInt(0); - zigbee_devices.jsonPublishNow(shortaddr, attr_list); -} - - -void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list) { - - uint8_t src_ep = _srcendpoint; - - for (auto &attr : attr_list) { - - if (!attr.key_is_str) { - uint16_t cluster = attr.key.id.cluster; - uint16_t attribute = attr.key.id.attr_id; - uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; - Z_Device & device = zigbee_devices.getShortAddr(shortaddr); - - - bool found = false; - const char * conv_name; - Z_Data_Type map_type; - uint8_t map_offset; - uint8_t zigbee_type; - int8_t conv_multiplier; - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint16_t conv_attribute = pgm_read_word(&converter->attribute); - - if ((conv_cluster == cluster) && - ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { - conv_multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); - zigbee_type = pgm_read_byte(&converter->type); - uint8_t mapping = pgm_read_byte(&converter->mapping); - map_type = (Z_Data_Type) ((mapping & 0xF0)>>4); - map_offset = (mapping & 0x0F); - conv_name = Z_strings + pgm_read_word(&converter->name_offset); - found = true; - break; - } - } - - float fval = attr.getFloat(); - if (found && (map_type != Z_Data_Type::Z_Unknown)) { - - - - - - Z_Data & data = device.data.getByType(map_type, src_ep); - uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + map_offset; - uint32_t uval32 = attr.getUInt(); - int32_t ival32 = attr.getInt(); - - switch (zigbee_type) { - case Zenum8: - case Zuint8: *(uint8_t*)attr_address = uval32; break; - case Zenum16: - case Zuint16: *(uint16_t*)attr_address = uval32; break; - case Zuint32: *(uint32_t*)attr_address = uval32; break; - case Zint8: *(int8_t*)attr_address = ival32; break; - case Zint16: *(int16_t*)attr_address = ival32; break; - case Zint32: *(int32_t*)attr_address = ival32; break; - } - } - - uint16_t uval16 = attr.getUInt(); - int16_t ival16 = attr.getInt(); - Z_Data_Set & data = device.data; - - switch (ccccaaaa) { - case 0x00000004: zigbee_devices.setManufId(shortaddr, attr.getStr()); break; - case 0x00000005: zigbee_devices.setModelId(shortaddr, attr.getStr()); break; - case 0x00010021: zigbee_devices.setBatteryPercent(shortaddr, uval16 / 2); break; - case 0x00060000: - case 0x00068000: device.setPower(attr.getBool(), src_ep); break; - } - - - if (found) { - if (0 == conv_multiplier) { attr_list.removeAttribute(&attr); continue; } - if (1 != conv_multiplier) { - if (conv_multiplier > 0) { fval = fval * conv_multiplier; } - else { fval = fval / (-conv_multiplier); } - attr.setFloat(fval); - } - } - - - if (found) { - if (0x00 != pgm_read_byte(conv_name)) { - attr.setKeyName(conv_name, true); - } - } - } - } -} -# 1872 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -bool Z_parseAttributeKey(class Z_attribute & attr) { - - - if (attr.key_is_str) { - const char * key = attr.key.key; - char * delimiter = strchr(key, '/'); - char * delimiter2 = strchr(key, '%'); - if (delimiter) { - uint16_t attr_id = 0xFFFF; - uint16_t cluster_id = 0xFFFF; - uint8_t type_id = Zunk; - - cluster_id = strtoul(key, &delimiter, 16); - if (!delimiter2) { - attr_id = strtoul(delimiter+1, nullptr, 16); - } else { - attr_id = strtoul(delimiter+1, &delimiter2, 16); - type_id = strtoul(delimiter2+1, nullptr, 16); - } - attr.setKeyId(cluster_id, attr_id); - attr.attr_type = type_id; - } - } - - - - if (Zunk == attr.attr_type) { - - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - bool match = false; - uint16_t local_attr_id = pgm_read_word(&converter->attribute); - uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); - uint8_t local_type_id = pgm_read_byte(&converter->type); - int8_t local_multiplier = CmToMultiplier(pgm_read_byte(&converter->multiplier_idx)); - - - if (!attr.key_is_str) { - if ((attr.key.id.cluster == local_cluster_id) && (attr.key.id.attr_id == local_attr_id)) { - attr.attr_type = local_type_id; - break; - } - } else if (pgm_read_word(&converter->name_offset)) { - const char * key = attr.key.key; - - if (0 == strcasecmp_P(key, Z_strings + pgm_read_word(&converter->name_offset))) { - - attr.setKeyId(local_cluster_id, local_attr_id); - attr.attr_type = local_type_id; - attr.attr_multiplier = local_multiplier; - break; - } - } - } - } - return (Zunk != attr.attr_type) ? true : false; -} - - - - - - -void Z_Data::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { - - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint8_t conv_export = pgm_read_byte(&converter->multiplier_idx) & Z_EXPORT_DATA; - uint8_t conv_mapping = pgm_read_byte(&converter->mapping); - Z_Data_Type map_type = (Z_Data_Type) ((conv_mapping & 0xF0)>>4); - uint8_t map_offset = (conv_mapping & 0x0F); - - if ((conv_export != 0) && (map_type == type)) { - - const char * conv_name = Z_strings + pgm_read_word(&converter->name_offset); - uint8_t zigbee_type = pgm_read_byte(&converter->type); - uint8_t *attr_address = ((uint8_t*)this) + sizeof(Z_Data) + map_offset; - - int32_t data_size = 0; - int32_t ival32; - uint32_t uval32; - switch (zigbee_type) { - case Zenum8: - case Zuint8: uval32 = *(uint8_t*)attr_address; if (uval32 != 0xFF) data_size = 8; break; - case Zenum16: - case Zuint16: uval32 = *(uint16_t*)attr_address; if (uval32 != 0xFFFF) data_size = 16; break; - case Zuint32: uval32 = *(uint32_t*)attr_address; if (uval32 != 0xFFFFFFFF) data_size = 32; break; - case Zint8: ival32 = *(int8_t*)attr_address; if (ival32 != -0x80) data_size = -8; break; - case Zint16: ival32 = *(int16_t*)attr_address; if (ival32 != -0x8000) data_size = -16; break; - case Zint32: ival32 = *(int32_t*)attr_address; if (ival32 != -0x80000000) data_size = -32; break; - } - if (data_size != 0) { - Z_attribute & attr = attr_list.addAttribute(conv_name); - - if (data_size > 0) { attr.setUInt(uval32); } - else { attr.setInt(ival32); } - } - } - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -#ifdef USE_ZIGBEE - - - - - -typedef struct Z_CommandConverter { - uint16_t tasmota_cmd_offset; - uint16_t cluster; - uint8_t cmd; - uint8_t direction; - uint16_t param_offset; -} Z_CommandConverter; - -typedef struct Z_XYZ_Var { - uint32_t x = 0; - uint32_t y = 0; - uint32_t z = 0; - uint8_t x_type = 0; - uint8_t y_type = 0; - uint8_t z_type = 0; -} Z_XYZ_Var; -# 50 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -const Z_CommandConverter Z_Commands[] PROGMEM = { - - { Z_(Identify), 0x0003, 0x00, 0x01, Z_(xxxx) }, - { Z_(IdentifyQuery), 0x0003, 0x01, 0x01, Z_() }, - - { Z_(AddGroup), 0x0004, 0x00, 0x01, Z_(xxxx00) }, - { Z_(ViewGroup), 0x0004, 0x01, 0x01, Z_(xxxx) }, - { Z_(GetGroup), 0x0004, 0x02, 0x01, Z_(01xxxx) }, - { Z_(GetAllGroups), 0x0004, 0x02, 0x01, Z_(00) }, - { Z_(RemoveGroup), 0x0004, 0x03, 0x01, Z_(xxxx) }, - { Z_(RemoveAllGroups),0x0004, 0x04, 0x01, Z_() }, - - - { Z_(ViewScene), 0x0005, 0x01, 0x01, Z_(xxxxyy) }, - { Z_(RemoveScene), 0x0005, 0x02, 0x01, Z_(xxxxyy) }, - { Z_(RemoveAllScenes),0x0005, 0x03, 0x01, Z_(xxxx) }, - { Z_(RecallScene), 0x0005, 0x05, 0x01, Z_(xxxxyy) }, - { Z_(GetSceneMembership),0x0005, 0x06, 0x01, Z_(xxxx) }, - - { Z_(PowerOffEffect), 0x0006, 0x40, 0x81, Z_(xxyy) }, - { Z_(PowerOnRecall), 0x0006, 0x41, 0x81, Z_() }, - { Z_(PowerOnTimer), 0x0006, 0x42, 0x81, Z_(xxyyyyzzzz) }, - { Z_(Power), 0x0006, 0xFF, 0x01, Z_() }, - { Z_(Dimmer), 0x0008, 0x04, 0x01, Z_(xx0A00) }, - { Z_(DimmerUp), 0x0008, 0x06, 0x01, Z_(00190200) }, - { Z_(DimmerDown), 0x0008, 0x06, 0x01, Z_(01190200) }, - { Z_(DimmerStop), 0x0008, 0x03, 0x01, Z_() }, - { Z_(ResetAlarm), 0x0009, 0x00, 0x01, Z_(xxyyyy) }, - { Z_(ResetAllAlarms), 0x0009, 0x01, 0x01, Z_() }, - { Z_(Hue), 0x0300, 0x00, 0x01, Z_(xx000A00) }, - { Z_(Sat), 0x0300, 0x03, 0x01, Z_(xx0A00) }, - { Z_(HueSat), 0x0300, 0x06, 0x01, Z_(xxyy0A00) }, - { Z_(Color), 0x0300, 0x07, 0x01, Z_(xxxxyyyy0A00) }, - { Z_(CT), 0x0300, 0x0A, 0x01, Z_(xxxx0A00) }, - { Z_(ShutterOpen), 0x0102, 0x00, 0x01, Z_() }, - { Z_(ShutterClose), 0x0102, 0x01, 0x01, Z_() }, - { Z_(ShutterStop), 0x0102, 0x02, 0x01, Z_() }, - { Z_(ShutterLift), 0x0102, 0x05, 0x01, Z_(xx) }, - { Z_(ShutterTilt), 0x0102, 0x08, 0x01, Z_(xx) }, - { Z_(Shutter), 0x0102, 0xFF, 0x01, Z_() }, - - { Z_(Occupancy), 0xEF00, 0x01, 0x82, Z_()}, - - { Z_(Dimmer), 0x0008, 0x00, 0x01, Z_(xx) }, - { Z_(DimmerMove), 0x0008, 0x01, 0x01, Z_(xx0A) }, - { Z_(DimmerStepUp), 0x0008, 0x02, 0x01, Z_(00xx0A00) }, - { Z_(DimmerStepDown), 0x0008, 0x02, 0x01, Z_(01xx0A00) }, - { Z_(DimmerStep), 0x0008, 0x02, 0x01, Z_(xx190A00) }, - { Z_(DimmerMove), 0x0008, 0x05, 0x01, Z_(xx0A) }, - { Z_(DimmerUp), 0x0008, 0x06, 0x01, Z_(00) }, - { Z_(DimmerDown), 0x0008, 0x06, 0x01, Z_(01) }, - { Z_(DimmerStop), 0x0008, 0x07, 0x01, Z_() }, - { Z_(HueMove), 0x0300, 0x01, 0x01, Z_(xx19) }, - { Z_(HueStepUp), 0x0300, 0x02, 0x01, Z_(01xx0A00) }, - { Z_(HueStepDown), 0x0300, 0x02, 0x01, Z_(03xx0A00) }, - { Z_(HueStep), 0x0300, 0x02, 0x01, Z_(xx190A00) }, - { Z_(SatMove), 0x0300, 0x04, 0x01, Z_(xx19) }, - { Z_(SatStep), 0x0300, 0x05, 0x01, Z_(xx190A) }, - { Z_(ColorMove), 0x0300, 0x08, 0x01, Z_(xxxxyyyy) }, - { Z_(ColorStep), 0x0300, 0x09, 0x01, Z_(xxxxyyyy0A00) }, - { Z_(ColorTempMoveUp), 0x0300, 0x4B, 0x01, Z_(01xxxx000000000000) }, - { Z_(ColorTempMoveDown),0x0300, 0x4B, 0x01, Z_(03xxxx000000000000) }, - { Z_(ColorTempMoveStop),0x0300, 0x4B, 0x01, Z_(00xxxx000000000000) }, - { Z_(ColorTempMove), 0x0300, 0x4B, 0x01, Z_(xxyyyy000000000000) }, - { Z_(ColorTempStepUp), 0x0300, 0x4C, 0x01, Z_(01xxxx0A0000000000) }, - { Z_(ColorTempStepDown),0x0300, 0x4C, 0x01, Z_(03xxxx0A0000000000) }, - { Z_(ColorTempStep), 0x0300, 0x4C, 0x01, Z_(xxyyyy0A0000000000) }, - - { Z_(ArrowClick), 0x0005, 0x07, 0x01, Z_(xx) }, - { Z_(ArrowHold), 0x0005, 0x08, 0x01, Z_(xx) }, - { Z_(ArrowRelease), 0x0005, 0x09, 0x01, Z_() }, - - { Z_(IdentifyQuery), 0x0003, 0x00, 0x02, Z_(xxxx) }, - - { Z_(ZoneStatusChange),0x0500, 0x00, 0x82, Z_(xxxxyyzz) }, - - { Z_(AddGroup), 0x0004, 0x00, 0x82, Z_(xxyyyy) }, - { Z_(ViewGroup), 0x0004, 0x01, 0x82, Z_(xxyyyy) }, - { Z_(GetGroup), 0x0004, 0x02, 0x82, Z_(xxyyzzzz) }, - { Z_(RemoveGroup), 0x0004, 0x03, 0x82, Z_(xxyyyy) }, - - { Z_(AddScene), 0x0005, 0x00, 0x82, Z_(xxyyyyzz) }, - { Z_(ViewScene), 0x0005, 0x01, 0x82, Z_(xxyyyyzz) }, - { Z_(RemoveScene), 0x0005, 0x02, 0x82, Z_(xxyyyyzz) }, - { Z_(RemoveAllScenes),0x0005, 0x03, 0x82, Z_(xxyyyy) }, - { Z_(StoreScene), 0x0005, 0x04, 0x82, Z_(xxyyyyzz) }, - { Z_(GetSceneMembership),0x0005, 0x06, 0x82,Z_(xxyyzzzz) }, - - { Z_(), 0xEF00, 0xFF, 0x83, Z_() }, - - { Z_(), 0xFCCC, 0x00, 0x82, Z_(xxyy) }, -}; - - - - -#define ZLE(x) ((x) & 0xFF), ((x) >> 8) - - -const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007), ZLE(0x0008) }; - - -void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - size_t attrs_len = 0; - const uint8_t* attrs = nullptr; - - switch (cluster) { - case 0x0006: - attrs = CLUSTER_0006; - attrs_len = sizeof(CLUSTER_0006); - break; - case 0x0008: - attrs = CLUSTER_0008; - attrs_len = sizeof(CLUSTER_0008); - break; - case 0x0009: - attrs = CLUSTER_0009; - attrs_len = sizeof(CLUSTER_0009); - break; - case 0x0300: - attrs = CLUSTER_0300; - attrs_len = sizeof(CLUSTER_0300); - break; - } - if (attrs) { - if (groupaddr) { - shortaddr = BAD_SHORTADDR; - } - uint8_t seq = zigbee_devices.getNextSeqNumber(shortaddr); - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - shortaddr, - groupaddr, - cluster , - endpoint, - ZCL_READ_ATTRIBUTES, - 0, - false , - true , - false , - seq, - attrs, attrs_len - })); - } -} - - - -void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - if (BAD_SHORTADDR != shortaddr) { - zigbee_devices.setReachable(shortaddr, false); - } -} - - -inline bool isXYZ(char c) { - return (c >= 'x') && (c <= 'z'); -} - - - - -inline int8_t hexValue(char c) { - if ((c >= '0') && (c <= '9')) { - return c - '0'; - } - if ((c >= 'A') && (c <= 'F')) { - return 10 + c - 'A'; - } - if ((c >= 'a') && (c <= 'f')) { - return 10 + c - 'a'; - } - return -1; -} - - -uint32_t parseHex_P(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(pgm_read_byte(*data)); - if (v < 0) { break; } - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - - - - - -void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { - const char *p = model; - uint32_t v = 0; - char c = pgm_read_byte(p); - while (c) { - char c1 = pgm_read_byte(p+1); - if (!c1) { break; } - if (isXYZ(c) && (c == c1) && (v < payload.len())) { - uint8_t val = payload.get8(v); - switch (c) { - case 'x': - xyz->x = xyz->x | (val << (xyz->x_type * 8)); - xyz->x_type++; - break; - case 'y': - xyz->y = xyz->y | (val << (xyz->y_type * 8)); - xyz->y_type++; - break; - case 'z': - xyz->z = xyz->z | (val << (xyz->z_type * 8)); - xyz->z_type++; - break; - } - } - p += 2; - v++; - c = pgm_read_byte(p); - } -} - - - -void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &payload) { - const char * command_name = nullptr; - uint8_t conv_direction; - Z_XYZ_Var xyz; - - - for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { - const Z_CommandConverter *conv = &Z_Commands[i]; - uint16_t conv_cluster = pgm_read_word(&conv->cluster); - if (conv_cluster == cluster) { - - uint8_t conv_cmd = pgm_read_byte(&conv->cmd); - conv_direction = pgm_read_byte(&conv->direction); - if ((0xFF == conv_cmd) || (cmd == conv_cmd)) { - - if ((direction && (conv_direction & 0x02)) || (!direction && (conv_direction & 0x01))) { - - - - - const char * p = Z_strings + pgm_read_word(&conv->param_offset); - - bool match = true; - for (uint8_t i = 0; i < payload.len(); i++) { - const char c1 = pgm_read_byte(p); - const char c2 = pgm_read_byte(p+1); - - if ((0x00 == c1) || isXYZ(c1)) { - break; - } - const char * p2 = p; - uint32_t nextbyte = parseHex_P(&p2, 2); - - if (nextbyte != payload.get8(i)) { - match = false; - break; - } - p += 2; - } - if (match) { - command_name = Z_strings + pgm_read_word(&conv->tasmota_cmd_offset); - parseXYZ(Z_strings + pgm_read_word(&conv->param_offset), payload, &xyz); - if (0xFF == conv_cmd) { - - xyz.z = xyz.y; - xyz.z_type = xyz.y_type; - xyz.y = xyz.x; - xyz.y_type = xyz.x_type; - xyz.x = cmd; - xyz.x_type = 1; - } - break; - } - } - } - } - } - - - - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); - Z_attribute & attr_raw = attr_list.addAttribute(attrid_str); - attr_raw.setBuf(payload, 0, payload.len()); - - if (command_name) { - - - if (conv_direction & 0x80) { - uint32_t cccc00mm = (cluster << 16) | cmd; - - switch (cccc00mm) { - case 0x05000000: - attr_list.addAttribute(command_name, true).setUInt(xyz.x); - if (0 != xyz.y) { - attr_list.addAttribute(command_name, PSTR("Ext")).setUInt(xyz.y); - } - if ((0 != xyz.z) && (0xFF != xyz.z)) { - attr_list.addAttribute(command_name, PSTR("Zone")).setUInt(xyz.z); - } - - - - attr_list.addAttribute(0x0406, 0x0000).setUInt((xyz.x) & 0x01 ? 1 : 0); - break; - case 0x00040000: - case 0x00040001: - case 0x00040003: - attr_list.addAttribute(command_name, true).setUInt(xyz.y); - attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); - attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); - break; - case 0x00040002: - attr_list.addAttribute(command_name, PSTR("Capacity")).setUInt(xyz.x); - attr_list.addAttribute(command_name, PSTR("Count")).setUInt(xyz.y); - { - - Z_json_array group_list; - for (uint32_t i = 0; i < xyz.y; i++) { - group_list.add(payload.get16(2 + 2*i)); - } - attr_list.addAttribute(command_name, true).setStrRaw(group_list.toString().c_str()); - } - break; - case 0x00050000: - case 0x00050001: - case 0x00050002: - case 0x00050004: - attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); - attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); - attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.y); - attr_list.addAttribute(PSTR("SceneId"), true).setUInt(xyz.z); - if (0x00050001 == cccc00mm) { - attr_list.addAttribute(PSTR("ScenePayload"), true).setBuf(payload, 4, payload.len()-4); - } - break; - case 0x00050003: - attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); - attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); - attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.y); - break; - case 0x00050006: - attr_list.addAttribute(command_name, PSTR("Status")).setUInt(xyz.x); - attr_list.addAttribute(command_name, PSTR("StatusMsg")).setStr(getZigbeeStatusMessage(xyz.x).c_str()); - attr_list.addAttribute(PSTR("Capacity"), true).setUInt(xyz.y); - attr_list.addAttribute(PSTR("GroupId"), true).setUInt(xyz.z); - attr_list.addAttribute(PSTR("ScenePayload"), true).setBuf(payload, 4, payload.len()-4); - break; - case 0x00060040: - attr_list.addAttribute(PSTR("Power"), true).setUInt(0); - attr_list.addAttribute(PSTR("PowerEffect"), true).setUInt(xyz.x); - attr_list.addAttribute(PSTR("PowerEffectVariant"), true).setUInt(xyz.y); - break; - case 0x00060041: - attr_list.addAttribute(PSTR("Power"), true).setUInt(1); - attr_list.addAttribute(PSTR("PowerRecallGlobalScene"), true).setBool(true); - break; - case 0x00060042: - attr_list.addAttribute(PSTR("Power"), true).setUInt(1); - attr_list.addAttribute(PSTR("PowerOnlyWhenOn"), true).setUInt(xyz.x); - attr_list.addAttribute(PSTR("PowerOnTime"), true).setFloat(xyz.y / 10.0f); - attr_list.addAttribute(PSTR("PowerOffWait"), true).setFloat(xyz.z / 10.0f); - break; - case 0xEF000000 ... 0xEF0000FF: - if (convertTuyaSpecificCluster(attr_list, cluster, cmd, direction, shortaddr, srcendpoint, payload)) { - attr_list.removeAttribute(&attr_raw); - } - break; - case 0xFCCC0000: - attr_list.addAttribute(PSTR("TerncyPress"), true).setUInt(xyz.y); - attr_list.addAttribute(PSTR("TerncyCount"), true).setUInt(xyz.x); - break; - } - } else { - - char command_suffix[4] = { 0x00 }; - - if (Settings.flag4.zb_index_ep) { - if (zigbee_devices.countEndpoints(shortaddr) > 0) { - snprintf_P(command_suffix, sizeof(command_suffix), PSTR("%d"), srcendpoint); - } - } - if (0 == xyz.x_type) { - attr_list.addAttribute(command_name, command_suffix).setBool(true); - } else if (0 == xyz.y_type) { - attr_list.addAttribute(command_name, command_suffix).setUInt(xyz.x); - } else { - - Z_json_array arr; - arr.add(xyz.x); - arr.add(xyz.y); - if (xyz.z_type) { - arr.add(xyz.z); - } - attr_list.addAttribute(command_name, command_suffix).setStrRaw(arr.toString().c_str()); - } - } - } -} - - - - - - -bool convertTuyaSpecificCluster(class Z_attribute_list &attr_list, uint16_t cluster, uint8_t cmd, bool direction, uint16_t shortaddr, uint8_t srcendpoint, const SBuffer &buf) { - - - uint16_t dp = buf.get16(2); - - uint8_t len = buf.get8(5); - - if ((1 == cmd) || (2 == cmd)) { - - Z_attribute & attr = attr_list.addAttribute(cluster, dp); - uint8_t attr_type; - switch (len) { - case 1: attr_type = Ztuya1; break; - case 2: attr_type = Ztuya2; break; - case 4: attr_type = Ztuya4; break; - default: attr_type = Zoctstr; break; - } - parseSingleAttribute(attr, buf, 5, attr_type); - return true; - } - return false; -} - - - - - -const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { - if (nullptr == command) { return nullptr; } - for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { - const Z_CommandConverter *conv = &Z_Commands[i]; - uint8_t conv_direction = pgm_read_byte(&conv->direction); - uint8_t conv_cmd = pgm_read_byte(&conv->cmd); - uint16_t conv_cluster = pgm_read_word(&conv->cluster); - if ((conv_direction & 0x01) && (0 == strcasecmp_P(command, Z_strings + pgm_read_word(&conv->tasmota_cmd_offset)))) { - *cluster = conv_cluster; - *cmd = conv_cmd; - return (const __FlashStringHelper*) (Z_strings + pgm_read_word(&conv->param_offset)); - } - } - - return nullptr; -} - - -inline char hexDigit(uint32_t h) { - uint32_t nybble = h & 0x0F; - return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; -} - - -String zigbeeCmdAddParams(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); - - char *p = zcl_cmd; - while (*p) { - if (isXYZ(*p) && (*p == *(p+1))) { - 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); -} - -const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" - "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" - "TOGGLE|" D_TOGGLE "|" - "ALL" ; - -const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, - 1,1,1,1,1, - 2,2, - 255 }; - - -uint32_t ZigbeeAliasOrNumber(const char *state_text) { - char command[16]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); - if (state_number >= 0) { - - return pgm_read_byte(kZ_Numbers + state_number); - } else { - - return strtoul(state_text, nullptr, 0); - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -#ifdef USE_ZIGBEE - - - -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_PERMITJOIN_ERROR = 23; -const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; -const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; -const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; -const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; -const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; -const uint8_t ZIGBEE_STATUS_SCANNING = 40; -const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; -const uint8_t ZIGBEE_STATUS_CC_INFO = 51; -const uint8_t ZIGBEE_STATUS_EZ_VERSION = 55; -const uint8_t ZIGBEE_STATUS_EZ_INFO = 56; -const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; -const uint8_t ZIGBEE_STATUS_ABORT = 99; - -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_STATE, - ZGB_INSTR_SEND, - ZGB_INSTR_WAIT_UNTIL, - ZGB_INSTR_WAIT_RECV, - ZGB_ON_RECV_UNEXPECTED, - - - ZGB_INSTR_12_BYTES = 0xF0, - ZGB_INSTR_WAIT_UNTIL_CALL, - 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_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (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_UNTIL_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_UNTIL_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, -#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) }, - - - - - -#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 ZBR(n,x...) uint8_t n[] = { x }; -#define ZBW(n,x...) { const uint8_t n ##t[] = { x }; memcpy(n, n ##t, sizeof(n)); } - -#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) - -const char kCheckingDeviceConfiguration[] PROGMEM = D_LOG_ZIGBEE "checking device configuration"; -const char kConfiguredCoord[] PROGMEM = "Configured, starting coordinator"; -const char kConfiguredRouter[] PROGMEM = "Configured, starting router"; -const char kConfiguredDevice[] PROGMEM = "Configured, starting device"; -const char kStarted[] PROGMEM = "Started"; -const char kZigbeeStarted[] PROGMEM = D_LOG_ZIGBEE "Zigbee started"; -const char kResetting[] PROGMEM = "Resetting configuration"; -const char kResettingDevice[] PROGMEM = D_LOG_ZIGBEE "Resetting EZSP device"; -const char kReconfiguringDevice[] PROGMEM = D_LOG_ZIGBEE "Factory reset EZSP device"; -const char kZNP12[] PROGMEM = "Only ZNP 1.2 is currently supported"; -const char kEZ8[] PROGMEM = "Only EZSP protocol v8 is currently supported"; -const char kAbort[] PROGMEM = "Abort"; -const char kZigbeeAbort[] PROGMEM = D_LOG_ZIGBEE "Abort"; -const char kZigbeeGroup0[] PROGMEM = D_LOG_ZIGBEE "Subscribe to group 0 'ZbListen0 0'"; - -#ifdef USE_ZIGBEE_ZNP - - - -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 ) -ZBR(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PANID, 0x02 , - 0x00, 0x00 ) - -ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) -ZBR(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_EXTENDED_PAN_ID, - 0x08 , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ) - -ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) -ZBR(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 ) -ZBR(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, - 0x10 , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - ) - -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(ZBS_LOGTYPE, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_LOGICAL_TYPE ) -ZBM(ZBS_LOGTYPE_COORD, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, - 0x01 , 0x00 ) -ZBM(ZBS_LOGTYPE_ROUTER, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, - 0x01 , 0x01 ) -ZBM(ZBS_LOGTYPE_DEVICE, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_LOGICAL_TYPE, - 0x01 , 0x02 ) - - - - -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 , 0x03 ) - -ZBR(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , 0x00, 0x00 ) - -ZBR(ZBS_W_ALL_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(0xFFFF), Z_B1(0xFFFF) ) - -ZBR(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ) - -ZBR(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), - ) - -const uint32_t ZB_ALL_CHANNELS = 0x07FFF800; -ZBR(ZBS_W_ALL_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , - Z_B0(ZB_ALL_CHANNELS), Z_B1(ZB_ALL_CHANNELS), Z_B2(ZB_ALL_CHANNELS), Z_B3(ZB_ALL_CHANNELS), - ) - -ZBM(ZBS_W_LOGTYP_COORD, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) - -ZBM(ZBS_W_LOGTYP_ROUTER, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x01 ) - -ZBM(ZBS_W_LOGTYP_DEVICE, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x02 ) - -ZBR(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ) - -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 ) -ZBM(AREQ_STARTUPFROMAPP_COORD, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) -ZBM(AREQ_STARTUPFROMAPP_ROUTER, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ROUTER ) -ZBM(AREQ_STARTUPFROMAPP_DEVICE, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_END_DEVICE ) - -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 ) -# 270 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.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_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) -# 288 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.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_AF_REGISTER_ALL, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x0E , - 0x00,0x00, 0x04,0x00, 0x05,0x00, 0x06,0x00, - 0x07,0x00, 0x08,0x00, 0x0A,0x00, 0x02,0x01, - 0x00,0x03, 0x00,0x04, 0x02,0x04, 0x03,0x04, - 0x05,0x04, 0x06,0x04, - 0x00 ) - - -ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , - 0x00, 0x00 , 0x00 , 0x00 ) -ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_SUCCESS) -ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_SUCCESS ) - - -void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) { - uint32_t zb_channel_mask = (1 << zb_channel); - - ZBW(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PANID, 0x02 , - Z_B0(zb_pan_id), Z_B1(zb_pan_id) ) - - ZBW(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_EXTENDED_PAN_ID, - 0x08 , - Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), - Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), - ) - - ZBW(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_CHANLIST, - 0x04 , - Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask), - ) - - ZBW(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_SUCCESS, CONF_PRECFGKEY, - 0x10 , - Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), - Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), - Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), - Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), - - ) - - ZBW(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(zb_pan_id), Z_B1(zb_pan_id) ) - - ZBW(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , - Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), - Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid) - ) - - ZBW(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , - Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask), - ) - - ZBW(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 , - Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), - Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), - Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), - Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), - ) -} - -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(&ZNP_Recv_Default) - ZI_WAIT(10500) - - - ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting CC2530 device") - - ZI_CALL(&ZNP_Reset_Device, 0) - ZI_WAIT(100) - ZI_CALL(&ZNP_Reset_Device, 1) - ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &ZNP_Reboot) - ZI_WAIT(100) - ZI_LOG(LOG_LEVEL_DEBUG, kCheckingDeviceConfiguration) - ZI_SEND(ZBS_VERSION) - ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &ZNP_ReceiveCheckVersion) - - - ZI_CALL(&Z_SwitchDeviceType, 0) - - - - - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_COORD) - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - - ZI_SEND(ZBS_LOGTYPE) - ZI_WAIT_RECV(1000, ZBS_LOGTYPE_COORD) - 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_COORD) - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - - ZI_SEND(ZBS_STARTUPFROMAPP) - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) - ZI_WAIT_UNTIL_FUNC(10000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) - ZI_SEND(ZBS_GETDEVICEINFO) - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo) - - ZI_SEND(ZBS_ZDO_NODEDESCREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) - ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) - 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_STATE(ZIGBEE_STATUS_OK, kStarted) - ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted) - ZI_CALL(&Z_State_Ready, 1) - ZI_CALL(&Z_Load_Devices, 0) - ZI_CALL(&Z_Query_Bulbs, 0) - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_COORD) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) - - 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_COORD) - 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, &ZNP_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - - ZI_GOTO(ZIGBEE_LABEL_START_COORD) - - - - - ZI_LABEL(ZIGBEE_LABEL_INIT_ROUTER) - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_ROUTER) - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_LOGTYPE) - ZI_WAIT_RECV(1000, ZBS_LOGTYPE_ROUTER) - - - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredRouter) - ZI_LABEL(ZIGBEE_LABEL_START_ROUTER_DEVICE) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_SEND(ZBS_AF_REGISTER_ALL) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - ZI_SEND(ZBS_STARTUPFROMAPP) - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) - ZI_WAIT_UNTIL_FUNC(0xFFFF, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) - ZI_SEND(ZBS_GETDEVICEINFO) - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo) - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_ROUTER) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) - 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_LOGTYP_ROUTER) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST) - ZI_SEND(ZBS_W_ALL_PAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_ALL_CHANN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - - - ZI_SEND(ZBS_WNV_INITZNPHC) - ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &ZNP_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - ZI_GOTO(ZIGBEE_LABEL_START_ROUTER_DEVICE) - - - - - ZI_LABEL(ZIGBEE_LABEL_INIT_DEVICE) - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_FACT_RESET_DEVICE) - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_LOGTYPE) - ZI_WAIT_RECV(1000, ZBS_LOGTYPE_DEVICE) - - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredDevice) - ZI_GOTO(ZIGBEE_LABEL_START_ROUTER_DEVICE) - - ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_DEVICE) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) - 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_LOGTYP_DEVICE) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_GOTO(ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST) - - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kZNP12) - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - - ZI_LABEL(ZIGBEE_LABEL_ABORT) - ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, kAbort) - ZI_LOG(LOG_LEVEL_ERROR, kZigbeeAbort) - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -#endif - -#ifdef USE_ZIGBEE_EZSP - - - - -ZBM(ZBR_RSTACK, Z_B0(EZSP_rstAck), Z_B1(EZSP_rstAck)) - - -ZBM(ZBS_VERSION, EZSP_version, 0x00, 0x08) -ZBM(ZBR_VERSION, EZSP_version, 0x00, 0x08, 0x02) - - - -ZBM(ZBS_SET_ADDR_TABLE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_KEY_TABLE_SIZE, 0x02, 0x00) -ZBM(ZBS_SET_MCAST_TABLE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_MULTICAST_TABLE_SIZE, 0x10, 0x00) -ZBM(ZBS_SET_STK_PROF, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_STACK_PROFILE, 0x02, 0x00) -ZBM(ZBS_SET_SEC_LEVEL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SECURITY_LEVEL, 0x05, 0x00) -ZBM(ZBS_SET_MAX_DEVICES, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_MAX_END_DEVICE_CHILDREN, 0x20, 0x00) -ZBM(ZBS_SET_INDIRECT_TMO, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_INDIRECT_TRANSMISSION_TIMEOUT, 0x00, 0x1E) -ZBM(ZBS_SET_TC_CACHE, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE, 0x02, 0x00) -ZBM(ZBS_SET_ROUTE_TBL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE, 0x10, 0x00) -ZBM(ZBS_SET_KEY_TBL, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_KEY_TABLE_SIZE, 0x04, 0x00) -ZBM(ZBS_SET_PANID_CNFLCT, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_PAN_ID_CONFLICT_REPORT_THRESHOLD, 0x02, 0x00) -ZBM(ZBS_SET_ZDO_REQ, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_APPLICATION_ZDO_FLAGS, EMBER_APP_RECEIVES_SUPPORTED_ZDO_REQUESTS | EMBER_APP_HANDLES_UNSUPPORTED_ZDO_REQUESTS, 0x00) -ZBM(ZBS_SET_NETWORKS, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_SUPPORTED_NETWORKS, 0x01, 0x00) -ZBM(ZBS_SET_PACKET_BUF, EZSP_setConfigurationValue, 0x00 , EZSP_CONFIG_PACKET_BUFFER_COUNT, 0xFF, 0x00) - -ZBM(ZBR_SET_OK, EZSP_setConfigurationValue, 0x00 , 0x00 ) - - -ZBR(ZBR_SET_OK2, EZSP_setConfigurationValue, 0x00 , 0x00 ) - - - - - - -ZBM(ZBS_ADD_ENDPOINT1, EZSP_addEndpoint, 0x00 , 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , - 0x00 , - 0X00 , - - - - - ) -ZBM(ZBS_ADD_ENDPOINTB, EZSP_addEndpoint, 0x00 , 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , - 0x00 , - 0X00 , - - - - - ) -ZBM(ZBR_ADD_ENDPOINT, EZSP_addEndpoint, 0x00 , 0x00 ) - - -ZBM(ZBS_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 , 0x00 , 0xF9,0xFF , - 0x58,0x02 , 0x08,0x07 , 0x02 , 0x05 , 0x00 ) -ZBM(ZBR_SET_CONCENTRATOR, EZSP_setConcentrator, 0x00 , 0x00 ) - - -#define EZ_SECURITY_MODE EMBER_TRUST_CENTER_GLOBAL_LINK_KEY | EMBER_PRECONFIGURED_NETWORK_KEY_MODE | EMBER_HAVE_NETWORK_KEY | EMBER_HAVE_PRECONFIGURED_KEY -ZBR(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , - Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE), - - 0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - ) -ZBM(ZBR_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , 0x00 ) - - -ZBM(ZBS_SET_POLICY_00, EZSP_setPolicy, 0x00 , EZSP_TRUST_CENTER_POLICY, - EZSP_DECISION_ALLOW_JOINS | EZSP_DECISION_ALLOW_UNSECURED_REJOINS) -ZBM(ZBS_SET_POLICY_02, EZSP_setPolicy, 0x00 , EZSP_UNICAST_REPLIES_POLICY, - EZSP_HOST_WILL_NOT_SUPPLY_REPLY) -ZBM(ZBS_SET_POLICY_03, EZSP_setPolicy, 0x00 , EZSP_POLL_HANDLER_POLICY, - EZSP_POLL_HANDLER_IGNORE) -ZBM(ZBS_SET_POLICY_04, EZSP_setPolicy, 0x00 , EZSP_MESSAGE_CONTENTS_IN_CALLBACK_POLICY, - EZSP_MESSAGE_TAG_ONLY_IN_CALLBACK) -ZBM(ZBS_SET_POLICY_05, EZSP_setPolicy, 0x00 , EZSP_TC_KEY_REQUEST_POLICY, - EZSP_ALLOW_TC_KEY_REQUESTS_AND_SEND_CURRENT_KEY) -ZBM(ZBS_SET_POLICY_06, EZSP_setPolicy, 0x00 , EZSP_APP_KEY_REQUEST_POLICY, - EZSP_DENY_APP_KEY_REQUESTS) -ZBM(ZBR_SET_POLICY_XX, EZSP_setPolicy, 0x00 , 0x00 ) - - -ZBM(ZBS_NETWORK_INIT, EZSP_networkInit, 0x00 , 0x00, 0x00) -ZBM(ZBR_NETWORK_INIT, EZSP_networkInit, 0x00 , 0x00 ) - - -ZBR(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - USE_ZIGBEE_TXRADIO_DBM , - USE_ZIGBEE_CHANNEL , - EMBER_USE_MAC_ASSOCIATION, - 0xFF,0xFF, - 0x00, - 0x00,0x00,0x00,0x00, - ) -ZBM(ZBR_FORM_NETWORK, EZSP_formNetwork, 0x00 , 0x00 ) -ZBM(ZBR_NETWORK_UP, EZSP_stackStatusHandler, 0x00 , EMBER_NETWORK_UP) - - -ZBR(ZBS_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 ) -ZBM(ZBR_LEAVE_NETWORK, EZSP_leaveNetwork, 0x00 ) - - -ZBM(ZBS_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 ) -ZBM(ZBR_GET_NETW_PARM, EZSP_getNetworkParameters, 0x00 , 0x00 ) -ZBR(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 , - 0x00 , - EMBER_COORDINATOR , - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - USE_ZIGBEE_TXRADIO_DBM , - USE_ZIGBEE_CHANNEL , - ) - -ZBM(ZBS_GET_EUI64, EZSP_getEui64, 0x00 ) -ZBM(ZBR_GET_EUI64, EZSP_getEui64, 0x00 ) -ZBM(ZBS_GET_NODEID, EZSP_getNodeId, 0x00 ) -ZBM(ZBR_GET_NODEID, EZSP_getNodeId, 0x00 ) - - -ZBM(ZBS_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 , - 0x00 , 0x00,0x00 , 0x01 , 0x00 ) -ZBM(ZBR_SET_MCAST_ENTRY, EZSP_setMulticastTableEntry, 0x00 , 0x00 ) - - - - -ZBM(ZBS_GET_KEY_NWK, EZSP_getKey, 0x00 , EMBER_CURRENT_NETWORK_KEY) -ZBM(ZBR_GET_KEY_NWK, EZSP_getKey, 0x00 , 0x00 ) - - - - - -uint64_t ezsp_key_low, ezsp_key_high; - -void EZ_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h, int8_t zb_txradio_dbm) { - int8_t txradio = zb_txradio_dbm; - - if (txradio < 0) { txradio = USE_ZIGBEE_TXRADIO_DBM; } - if (txradio > 20) { txradio = USE_ZIGBEE_TXRADIO_DBM; } - ezsp_key_low = zb_precfgkey_l; - ezsp_key_high = zb_precfgkey_h; - - ZBW(ZBS_SET_SECURITY, EZSP_setInitialSecurityState, 0x00 , - Z_B0(EZ_SECURITY_MODE), Z_B1(EZ_SECURITY_MODE), - - 0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39, - - Z_B0(zb_precfgkey_l), Z_B1(zb_precfgkey_l), Z_B2(zb_precfgkey_l), Z_B3(zb_precfgkey_l), - Z_B4(zb_precfgkey_l), Z_B5(zb_precfgkey_l), Z_B6(zb_precfgkey_l), Z_B7(zb_precfgkey_l), - Z_B0(zb_precfgkey_h), Z_B1(zb_precfgkey_h), Z_B2(zb_precfgkey_h), Z_B3(zb_precfgkey_h), - Z_B4(zb_precfgkey_h), Z_B5(zb_precfgkey_h), Z_B6(zb_precfgkey_h), Z_B7(zb_precfgkey_h), - 0x00 , - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - ) - - ZBW(ZBS_FORM_NETWORK, EZSP_formNetwork, 0x00 , - Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), - Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), - Z_B0(zb_pan_id), Z_B1(zb_pan_id), - (uint8_t)txradio , - zb_channel , - EMBER_USE_MAC_ASSOCIATION, - 0xFF,0xFF, - 0x00, - 0x00,0x00,0x00,0x00, - ) - - ZBW(ZBR_CHECK_NETW_PARM, EZSP_getNetworkParameters, 0x00 , - 0x00 , - EMBER_COORDINATOR , - Z_B0(zb_ext_panid), Z_B1(zb_ext_panid), Z_B2(zb_ext_panid), Z_B3(zb_ext_panid), - Z_B4(zb_ext_panid), Z_B5(zb_ext_panid), Z_B6(zb_ext_panid), Z_B7(zb_ext_panid), - Z_B0(zb_pan_id), Z_B1(zb_pan_id), - (uint8_t)txradio , - zb_channel , - ) -} - -static const Zigbee_Instruction zb_prog[] PROGMEM = { - ZI_LABEL(0) - ZI_CALL(&EZ_Reset_Device, 0) - ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) - - ZI_LABEL(ZIGBEE_LABEL_RESTART) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_RECV_UNEXPECTED(&EZ_Recv_Default) - ZI_WAIT(10500) - - - ZI_LOG(LOG_LEVEL_INFO, kResettingDevice) - ZI_CALL(&EZ_Reset_Device, 0) - ZI_WAIT(100) - ZI_CALL(&EZ_Reset_Device, 1) - - - ZI_WAIT_UNTIL(5000, ZBR_RSTACK) - - - ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &EZ_ReceiveCheckVersion) - - - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) - ZI_SEND(ZBS_SET_ADDR_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_MCAST_TABLE) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_STK_PROF) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_SEC_LEVEL) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_MAX_DEVICES) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_INDIRECT_TMO) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_TC_CACHE) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_ROUTE_TBL) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_KEY_TBL) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_PANID_CNFLCT) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_ZDO_REQ) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_NETWORKS) ZI_WAIT_RECV(500, ZBR_SET_OK) - ZI_SEND(ZBS_SET_PACKET_BUF) ZI_WAIT_RECV(500, ZBR_SET_OK2) - - - - - - - ZI_SEND(ZBS_ADD_ENDPOINT1) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT) - ZI_SEND(ZBS_ADD_ENDPOINTB) ZI_WAIT_RECV(500, ZBR_ADD_ENDPOINT) - - - ZI_SEND(ZBS_SET_CONCENTRATOR) ZI_WAIT_RECV(500, ZBR_SET_CONCENTRATOR) - - - ZI_SEND(ZBS_SET_POLICY_00) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) - ZI_SEND(ZBS_SET_POLICY_02) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) - ZI_SEND(ZBS_SET_POLICY_03) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) - - ZI_SEND(ZBS_SET_POLICY_05) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) - ZI_SEND(ZBS_SET_POLICY_06) ZI_WAIT_RECV(500, ZBR_SET_POLICY_XX) - - - ZI_CALL(&EZ_GotoIfResetConfig, ZIGBEE_LABEL_CONFIGURE_EZSP) - - - - - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_BAD_CONFIG) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_BAD_CONFIG) - ZI_SEND(ZBS_NETWORK_INIT) ZI_WAIT_RECV(500, ZBR_NETWORK_INIT) - ZI_WAIT_RECV(1500, ZBR_NETWORK_UP) - - ZI_SEND(ZBS_GET_KEY_NWK) ZI_WAIT_RECV_FUNC(500, ZBR_GET_KEY_NWK, &EZ_CheckKeyNWK) - ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64) - ZI_SEND(ZBS_GET_NETW_PARM) ZI_WAIT_RECV_FUNC(500, ZBR_CHECK_NETW_PARM, &EZ_NetworkParameters) - - - ZI_GOTO(ZIGBEE_LABEL_NETWORK_CONFIGURED) - - ZI_LABEL(ZIGBEE_LABEL_BAD_CONFIG) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting) - ZI_CALL(EZ_Set_ResetConfig, 1) - ZI_GOTO(ZIGBEE_LABEL_RESTART) - - ZI_LABEL(ZIGBEE_LABEL_CONFIGURE_EZSP) - - ZI_LOG(LOG_LEVEL_INFO, kReconfiguringDevice) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_SEND(ZBS_SET_SECURITY) ZI_WAIT_RECV(500, ZBR_SET_SECURITY) - - ZI_SEND(ZBS_FORM_NETWORK) ZI_WAIT_RECV(500, ZBR_FORM_NETWORK) - ZI_WAIT_RECV(5000, ZBR_NETWORK_UP) - - ZI_LABEL(ZIGBEE_LABEL_NETWORK_CONFIGURED) - - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_SEND(ZBS_GET_EUI64) ZI_WAIT_RECV_FUNC(500, ZBR_GET_EUI64, &EZ_GetEUI64) - ZI_SEND(ZBS_GET_NODEID) ZI_WAIT_RECV_FUNC(500, ZBR_GET_NODEID, &EZ_GetNodeId) - - ZI_LOG(LOG_LEVEL_INFO, kZigbeeGroup0) - ZI_SEND(ZBS_SET_MCAST_ENTRY) ZI_WAIT_RECV(500, ZBR_SET_MCAST_ENTRY) - - - ZI_MQTT_STATE(ZIGBEE_STATUS_OK, kStarted) - ZI_LOG(LOG_LEVEL_INFO, kZigbeeStarted) - ZI_CALL(&Z_State_Ready, 1) - ZI_CALL(&Z_Load_Devices, 0) -#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES - ZI_CALL(&Z_Query_Bulbs, 0) -#endif - - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, kEZ8) - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - - ZI_LABEL(ZIGBEE_LABEL_ABORT) - ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, kAbort) - ZI_LOG(LOG_LEVEL_ERROR, kZigbeeAbort) - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -#endif - -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 < ARRAY_SIZE(zb_prog); 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(D_LOG_ZIGBEE "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(D_LOG_ZIGBEE "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(D_LOG_ZIGBEE "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 > ARRAY_SIZE(zb_prog)) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); - zigbee.pc = -1; - } - if (zigbee.pc < 0) { - zigbee.state_machine = false; - return; - } - - - 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(D_LOG_ZIGBEE "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_STATE: - { - const char *f_msg = (const char*) cur_ptr1; - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), - cur_d8, f_msg); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - } - break; - case ZGB_INSTR_SEND: -#ifdef USE_ZIGBEE_ZNP - ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); -#endif -#ifdef USE_ZIGBEE_EZSP - ZigbeeEZSPSendCmd((uint8_t*) cur_ptr1, cur_d8 ); -#endif - 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; - if (0xFFFF == cur_d16) { - zigbee.next_timeout = 0; - } else { - 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_UNTIL_CALL: - zigbee.recv_until = true; - 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; - if (0xFFFF == cur_d16) { - zigbee.next_timeout = 0; - } else { - 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; - } - } - } - - - 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); - } - } - - - if (0 == res) { - - zigbee.state_waiting = false; - } else if (res > 0) { - ZigbeeGotoLabel(res); - } else if (-1 == res) { - - - } else { - - ZigbeeGotoLabel(zigbee.on_error_goto); - } - return 0; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -#ifdef USE_ZIGBEE - -#ifdef USE_ZIGBEE_EZSP - - - - -uint8_t ZNP_RSSI2Lqi(int8_t rssi) { - if (rssi < -87) { rssi = -87; } - if (rssi > 10) { rssi = 10; } - return changeUIntScale(rssi + 87, 0, 87+10, 0, 254); -} - - - - - - -int32_t EZ_RSTACK(uint8_t reset_code) { - const char *reason_str; - - switch (reset_code) { - case 0x01: reason_str = PSTR("External"); break; - case 0x02: reason_str = PSTR("Power-on"); break; - case 0x03: reason_str = PSTR("Watchdog"); break; - case 0x06: reason_str = PSTR("Assert"); break; - case 0x09: reason_str = PSTR("Bootloader"); break; - case 0x0B: reason_str = PSTR("Software"); break; - case 0x00: - default: reason_str = PSTR("Unknown"); break; - } - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"EFR32 booted\",\"RestartReason\":\"%s\"" - ",\"Code\":%d}}"), - ZIGBEE_STATUS_BOOT, reason_str, reset_code); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); -} - - -int32_t EZ_ERROR(uint8_t error_code) { - const char *reason_str; - - switch (error_code) { - case 0x51: reason_str = PSTR("ACK timeout"); break; - default: reason_str = PSTR("Unknown"); break; - } - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"Failed state\",\"Error\":\"%s\"" - ",\"Code\":%d}}"), - ZIGBEE_STATUS_ABORT, reason_str, error_code); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); -} - -int32_t EZ_ReadAPSUnicastMessage(int32_t res, class SBuffer &buf) { - - - uint16_t value = buf.get16(2); - return res; -} -# 89 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -int32_t EZ_GetEUI64(int32_t res, class SBuffer &buf) { - localIEEEAddr = buf.get64(2); - return res; -} - - - - -int32_t EZ_GetNodeId(int32_t res, class SBuffer &buf) { - localShortAddr = buf.get8(2); - return res; -} - - - - -int32_t EZ_NetworkParameters(int32_t res, class SBuffer &buf) { - uint8_t node_type = buf.get8(3); -# 116 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" - char hex[20]; - Uint64toHex(localIEEEAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d}}"), - ZIGBEE_STATUS_EZ_INFO, hex, localShortAddr, node_type); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - return res; -} - - - - -int32_t EZ_CheckKeyNWK(int32_t res, class SBuffer &buf) { - uint8_t status = buf.get8(2); - uint16_t bitmask = buf.get16(3); - uint8_t key_type = buf.get8(5); - uint64_t key_low = buf.get64(6); - uint64_t key_high = buf.get64(14); - - if ( (key_type == EMBER_CURRENT_NETWORK_KEY) && - (key_low == ezsp_key_low) && - (key_high == ezsp_key_high) ) { - return 0; - } else { - return -2; - } -} - - - - -int32_t EZ_RouteError(int32_t res, const class SBuffer &buf) { - uint8_t status = buf.get8(2); - uint16_t shortaddr = buf.get16(3); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_ROUTE_ERROR "\":{" - "\"ShortAddr\":\"0x%04X\",\"" D_JSON_ZIGBEE_STATUS "\":%d,\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"}}"), - shortaddr, status, getEmberStatus(status).c_str()); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - return -1; -} - - - - -int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf) { - uint8_t status = buf.get8(2); - - if (status) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":23,\"Message\":\"Pairing mode error 0x%02X\"}}"), status); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - } - return -1; -} - - - - -void Z_PermitJoinDisable(void) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":20,\"Message\":\"Pairing mode disabled\"}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); -} - - - - - - - -int32_t EZ_MessageSent(int32_t res, const class SBuffer &buf) { - uint8_t message_type = buf.get8(2); - uint16_t dst_addr = buf.get16(3); - uint16_t group_addr = buf.get16(13); - - if ((EMBER_OUTGOING_MULTICAST == message_type) && (0xFFFD == dst_addr)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Sniffing group 0x%04X"), group_addr); - } - return -1; -} - -#endif -# 210 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -int32_t Z_EZSPGetEUI64(int32_t res, class SBuffer &buf) { - localIEEEAddr = buf.get64(2); - return res; -} - - - - -int32_t Z_EZSPGetNodeId(int32_t res, class SBuffer &buf) { - localShortAddr = buf.get8(2); - return res; -} - - - - -int32_t Z_EZSPNetworkParameters(int32_t res, class SBuffer &buf) { - uint8_t node_type = buf.get8(3); -# 237 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" - char hex[20]; - Uint64toHex(localIEEEAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d}}"), - ZIGBEE_STATUS_EZ_INFO, hex, localShortAddr, node_type); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - return res; -} -# 256 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -int32_t ZNP_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); - - - localIEEEAddr = long_adr; - localShortAddr = short_adr; - - char hex[20]; - Uint64toHex(long_adr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%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("]")); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - return res; -} - -int32_t ZNP_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 ZNP_Reboot(int32_t res, class SBuffer &buf) { - - - - uint8_t reason = buf.get8(2); - uint8_t transport_rev = buf.get8(3); - uint8_t product_id = buf.get8(4); - uint8_t major_rel = buf.get8(5); - uint8_t minor_rel = buf.get8(6); - uint8_t hw_rev = buf.get8(7); - const char *reason_str; - - switch (reason) { - case 0: reason_str = PSTR("Power-up"); break; - case 1: reason_str = PSTR("External"); break; - case 2: reason_str = PSTR("Watchdog"); break; - default: reason_str = PSTR("Unknown"); break; - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"CC2530 booted\",\"RestartReason\":\"%s\"" - ",\"MajorRel\":%d,\"MinorRel\":%d}}"), - ZIGBEE_STATUS_BOOT, reason_str, - major_rel, minor_rel); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -#ifdef USE_ZIGBEE_ZNP -int32_t ZNP_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { -# 357 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.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_STATE "\":{" - "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" - ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} -#endif - -#ifdef USE_ZIGBEE_EZSP -int32_t EZ_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { - uint8_t protocol_version = buf.get8(2); - uint8_t stack_type = buf.get8(3); - uint16_t stack_version = buf.get16(4); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Version\":\"%d.%d.%d.%d\",\"Protocol\":%d" - ",\"Stack\":%d}}"), - ZIGBEE_STATUS_EZ_VERSION, - (stack_version & 0xF000) >> 12, - (stack_version & 0x0F00) >> 8, - (stack_version & 0x00F0) >> 4, - stack_version & 0x000F, - protocol_version, - stack_type - ); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - - if (0x08 == protocol_version) { - if ((stack_version & 0xFF00) == 0x6700) { - - ZBW(ZBR_SET_OK2, 0x00, 0x00 , 0x00 ) - } - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -bool EZ_reset_config = false; - - -int32_t EZ_Set_ResetConfig(uint8_t value) { - EZ_reset_config = value ? true : false; - return 0; -} - - - -int32_t EZ_GotoIfResetConfig(uint8_t value) { - if (EZ_reset_config) { return ZIGBEE_LABEL_CONFIGURE_EZSP; } - else { return 0; } -} - -#endif - - - - - -int32_t Z_SwitchDeviceType(int32_t res, class SBuffer &buf) { - switch (Settings.zb_pan_id) { - case 0xFFFF: return ZIGBEE_LABEL_INIT_ROUTER; - case 0xFFFE: return ZIGBEE_LABEL_INIT_DEVICE; - default: return 0; - } -} - - - - -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 ZNP_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { - - 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_STATE "\":{" - "\"Status\":%d,\"Message\":\""), - status_code); - ResponseAppend_P(message, duration); - ResponseAppend_P(PSTR("\"}}")); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - return -1; -} - - - - -int32_t ZNP_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { - - 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; - const char * deviceTypeStr; - switch (deviceType) { - case 0: deviceTypeStr = PSTR("Coordinator"); break; - case 1: deviceTypeStr = PSTR("Router"); break; - case 2: deviceTypeStr = PSTR("Device"); break; - default: deviceTypeStr = PSTR("Unknown"); break; - } - bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), - ZIGBEE_STATUS_NODE_DESC, deviceTypeStr, - complexDescriptorAvailable ? PSTR("true") : PSTR("false") - ); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - } - - return -1; -} - - - - -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { - -#ifdef USE_ZIGBEE_ZNP - - 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); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t status = buf.get8(0); - Z_ShortAddress nwkAddr = buf.get16(1); - uint8_t activeEpCount = buf.get8(3); - uint8_t* activeEpList = (uint8_t*) buf.charptr(4); -#endif - - for (uint32_t i = 0; i < activeEpCount; i++) { - uint8_t ep = activeEpList[i]; - zigbee_devices.addEndpoint(nwkAddr, ep); - if ((i < 4) && (ep < 0x10)) { - zigbee_devices.queueTimer(nwkAddr, 0 , 1500, ep , ep, Z_CAT_EP_DESC, 0 , &Z_SendSimpleDescReq); - } - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"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("]}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - - Z_SendDeviceInfoRequest(nwkAddr); - - return -1; -} - - -const uint8_t Z_bindings[] PROGMEM = { - Cx0001, Cx0006, Cx0008, Cx0201, Cx0300, - Cx0400, Cx0402, Cx0403, Cx0405, Cx0406, - Cx0500, -}; - -int32_t Z_ClusterToCxBinding(uint16_t cluster) { - uint8_t cx = ClusterToCx(cluster); - for (uint32_t i=0; i= 0) { - bitSet(cluster_map, found_cx); - bitSet(cluster_in_map, found_cx); - } - } - - for (uint32_t i=0; i= 0) { - bitSet(cluster_map, found_cx); - } - } - - - if (bitRead(cluster_map, Z_ClusterToCxBinding(0x0500))) { - - zigbee_devices.queueTimer(shortaddr, 0 , 2000, 0x0500, endpoint, Z_CAT_READ_ATTRIBUTE, 0x0001, &Z_SendSingleAttributeRead); - } - - - for (uint32_t i=0; i 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(numInIndex + 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(numOutIndex + i*2)); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - } - - return -1; -} - - - - - -int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { -#ifdef USE_ZIGBEE_ZNP - uint8_t status = buf.get8(2); - Z_IEEEAddress ieeeAddr = buf.get64(3); - Z_ShortAddress nwkAddr = buf.get16(11); - - -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t status = buf.get8(0); - Z_IEEEAddress ieeeAddr = buf.get64(1); - Z_ShortAddress nwkAddr = buf.get16(9); - - -#endif - - if (0 == status) { - zigbee_devices.updateDevice(nwkAddr, ieeeAddr); - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - - const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" - ",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\""), nwkAddr, hex); - if (friendlyName) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); - } - ResponseAppend_P(PSTR("\"}}")); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - } - return -1; -} - - - - -int32_t ZNP_DataConfirm(int32_t res, const class SBuffer &buf) { - uint8_t status = buf.get8(2); - uint8_t endpoint = buf.get8(3); - - - if (status) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), endpoint, status, getZigbeeStatusMessage(status).c_str()); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - } - - return -1; -} -# 761 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -int32_t ZNP_ReceiveStateChange(int32_t res, const class SBuffer &buf) { - uint8_t state = buf.get8(2); - const char * msg = nullptr; - - switch (state) { - case ZDO_DEV_NWK_DISC: - msg = PSTR("Scanning Zigbee network"); - break; - case ZDO_DEV_NWK_JOINING: - case ZDO_DEV_NWK_REJOIN: - msg = PSTR("Joining a PAN"); - break; - case ZDO_DEV_END_DEVICE_UNAUTH: - msg = PSTR("Joined, not yet authenticated"); - break; - case ZDO_DEV_END_DEVICE: - msg = PSTR("Started as device"); - break; - case ZDO_DEV_ROUTER: - msg = PSTR("Started as router"); - break; - case ZDO_DEV_ZB_COORD: - msg = PSTR("Started as coordinator"); - break; - case ZDO_DEV_NWK_ORPHAN: - msg = PSTR("Device has lost its parent"); - break; - }; - - if (msg) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"NewState\":%d,\"Message\":\"%s\"}}"), - ZIGBEE_STATUS_SCANNING, state, msg - ); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - } - - if ((ZDO_DEV_END_DEVICE == state) || (ZDO_DEV_ROUTER == state) || (ZDO_DEV_ZB_COORD == state)) { - return 0; - } else { - return -1; - } -} - - - - - - -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { -#ifdef USE_ZIGBEE_ZNP - - Z_ShortAddress nwkAddr = buf.get16(4); - Z_IEEEAddress ieeeAddr = buf.get64(6); - uint8_t capabilities = buf.get8(14); -#endif -#ifdef USE_ZIGBEE_EZSP - - Z_ShortAddress nwkAddr = buf.get16(0); - Z_IEEEAddress ieeeAddr = buf.get64(2); - uint8_t capabilities = buf.get8(10); -#endif - - zigbee_devices.updateDevice(nwkAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" - ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), - ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, - (capabilities & 0x04) ? PSTR("true") : PSTR("false"), - (capabilities & 0x08) ? PSTR("true") : PSTR("false"), - (capabilities & 0x40) ? PSTR("true") : PSTR("false") - ); - - uint32_t wait_ms = 2000; - Z_Query_Bulb(nwkAddr, wait_ms); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - Z_SendActiveEpReq(nwkAddr); - return -1; -} - - - - - -int32_t ZNP_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_IEEEAddress ieeeAddr = buf.get64(4); - Z_ShortAddress parentNw = buf.get16(12); - - zigbee_devices.updateDevice(srcAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" - ",\"ParentNetwork\":\"0x%04X\"}}"), - ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw - ); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - return -1; -} - - - - -int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { -#ifdef USE_ZIGBEE_ZNP - Z_ShortAddress nwkAddr = buf.get16(2); - uint8_t status = buf.get8(4); - String msg = getZigbeeStatusMessage(status); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t status = buf.get8(0); - Z_ShortAddress nwkAddr = buf.get16(buf.len()-2); - String msg = getZDPStatusMessage(status); -#endif - - const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); - if (friendlyName) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); - } - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), status, msg.c_str()); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - - return -1; -} - - - - -int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { -#ifdef USE_ZIGBEE_ZNP - Z_ShortAddress nwkAddr = buf.get16(2); - uint8_t status = buf.get8(4); - String msg = getZigbeeStatusMessage(status); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t status = buf.get8(0); - Z_ShortAddress nwkAddr = buf.get16(buf.len()-2); - String msg = getZDPStatusMessage(status); -#endif - - const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), nwkAddr); - if (friendlyName) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); - } - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), status, msg.c_str()); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - - return -1; -} - - - -int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { -#ifdef USE_ZIGBEE_ZNP - uint16_t shortaddr = buf.get16(2); - uint8_t status = buf.get8(4); - uint8_t bind_total = buf.get8(5); - uint8_t bind_start = buf.get8(6); - uint8_t bind_len = buf.get8(7); - const size_t prefix_len = 8; -#endif -#ifdef USE_ZIGBEE_EZSP - uint16_t shortaddr = buf.get16(buf.len()-2); - uint8_t status = buf.get8(0); - uint8_t bind_total = buf.get8(1); - uint8_t bind_start = buf.get8(2); - uint8_t bind_len = buf.get8(3); - const size_t prefix_len = 4; -#endif - - const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); - if (friendlyName) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); - } - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - ",\"BindingsTotal\":%d" - ",\"BindingsStart\":%d" - ",\"Bindings\":[" - ), status, getZigbeeStatusMessage(status).c_str(), bind_total, bind_start + 1); - - uint32_t idx = prefix_len; - for (uint32_t i = 0; i < bind_len; i++) { - if (idx + 14 > buf.len()) { break; } - - - uint8_t srcep = buf.get8(idx + 8); - uint16_t cluster = buf.get16(idx + 9); - uint8_t addrmode = buf.get8(idx + 11); - uint16_t group = 0x0000; - uint64_t dstaddr = 0; - uint8_t dstep = 0x00; - if (Z_Addr_Group == addrmode) { - group = buf.get16(idx + 12); - idx += 14; - } else if (Z_Addr_IEEEAddress == addrmode) { - dstaddr = buf.get64(idx + 12); - dstep = buf.get8(idx + 20); - idx += 21; - } else { - - break; - } - - if (i > 0) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep); - if (Z_Addr_Group == addrmode) { - ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group); - } else if (Z_Addr_IEEEAddress == addrmode) { - char hex[20]; - Uint64toHex(dstaddr, hex, 64); - ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep); - } - } - - ResponseAppend_P(PSTR("]}}")); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE)); - - return -1; -} - -#ifdef USE_ZIGBEE_EZSP - - - - -int32_t EZ_ParentAnnceRsp(int32_t res, const class SBuffer &buf, bool rsp) { - size_t prefix_len; - uint8_t status; - uint8_t num_children; - uint16_t shortaddr = buf.get16(buf.len()-2); - if (rsp) { - status = buf.get8(0); - num_children = buf.get8(1); - prefix_len = 2; - } else { - status = 0; - num_children = buf.get8(0); - prefix_len = 1; - } - - const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_PARENT "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); - if (friendlyName) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); - } - if (rsp) { - ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - ), status, getZigbeeStatusMessage(status).c_str()); - } - ResponseAppend_P(PSTR(",\"Children\":%d" - ",\"ChildInfo\":[" - ), num_children); - - uint32_t idx = prefix_len; - for (uint32_t i = 0; i < num_children; i++) { - if (idx + 8 > buf.len()) { break; } - - uint64_t child_ieee = buf.get64(idx); - idx += 8; - - if (i > 0) { - ResponseAppend_P(PSTR(",")); - } - char hex[20]; - Uint64toHex(child_ieee, hex, 64); - ResponseAppend_P(PSTR("\"0x%s\""), hex); - } - - ResponseAppend_P(PSTR("]}}")); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE)); - - return -1; -} -#endif -# 1070 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -void Z_SendIEEEAddrReq(uint16_t shortaddr) { -#ifdef USE_ZIGBEE_ZNP - uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; - - ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t IEEEAddrReq[] = { Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; - EZ_SendZDO(shortaddr, ZDO_IEEE_addr_req, IEEEAddrReq, sizeof(IEEEAddrReq)); -#endif -} - - - - -void Z_SendActiveEpReq(uint16_t shortaddr) { -#ifdef USE_ZIGBEE_ZNP - uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t ActiveEpReq[] = { Z_B0(shortaddr), Z_B1(shortaddr) }; - EZ_SendZDO(shortaddr, ZDO_Active_EP_req, ActiveEpReq, sizeof(ActiveEpReq)); -#endif -} - - - - - -void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { -#ifdef USE_ZIGBEE_ZNP - uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), - endpoint }; - ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); -#endif -#ifdef USE_ZIGBEE_EZSP - uint8_t SimpleDescReq[] = { Z_B0(shortaddr), Z_B1(shortaddr), endpoint }; - EZ_SendZDO(shortaddr, ZDO_SIMPLE_DESC_REQ, SimpleDescReq, sizeof(SimpleDescReq)); -#endif -} -# 1121 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -void Z_SendDeviceInfoRequest(uint16_t shortaddr) { - uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - if (0x00 == endpoint) { endpoint = 0x01; } - uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); - - uint8_t InfoReq[] = { 0x04, 0x00, 0x05, 0x00 }; - - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - shortaddr, - 0x0000, - 0x0000 , - endpoint, - ZCL_READ_ATTRIBUTES, - 0x0000, - false , - true , - false , - transacid, - InfoReq, sizeof(InfoReq) - })); -} - - - - -void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); - uint8_t InfoReq[2] = { Z_B0(value), Z_B1(value) }; - - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - shortaddr, - 0x0000, - cluster , - endpoint, - ZCL_READ_ATTRIBUTES, - 0x0000, - false , - true , - false , - transacid, - InfoReq, sizeof(InfoReq) - })); -} - - - - -void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(shortaddr); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `ZbBind {\"Device\":\"0x%04X\",\"Endpoint\":%d,\"Cluster\":\"0x%04X\"}`"), - shortaddr, endpoint, cluster); -#ifdef USE_ZIGBEE_ZNP - SBuffer buf(34); - buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_BIND_REQ); - buf.add16(shortaddr); - buf.add64(srcLongAddr); - buf.add8(endpoint); - buf.add16(cluster); - buf.add8(Z_Addr_IEEEAddress); - buf.add64(localIEEEAddr); - buf.add8(0x01); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -#endif - -#ifdef USE_ZIGBEE_EZSP - SBuffer buf(24); - - - buf.add64(srcLongAddr); - buf.add8(endpoint); - buf.add16(cluster); - buf.add8(Z_Addr_IEEEAddress); - buf.add64(localIEEEAddr); - buf.add8(0x01); - - EZ_SendZDO(shortaddr, ZDO_BIND_REQ, buf.buf(), buf.len()); -#endif -} - - - - - - -typedef struct Z_autoAttributeReporting_t { - uint16_t cluster; - uint16_t attr_id; - uint16_t min_interval; - uint16_t max_interval; - float report_change; -} Z_autoAttributeReporting_t; - - -const Z_autoAttributeReporting_t Z_autoAttributeReporting[] PROGMEM = { - { 0x0001, 0x0020, 15*60, 15*60, 0.1 }, - { 0x0001, 0x0021, 15*60, 15*60, 1 }, - { 0x0006, 0x0000, 1, 60*60, 0 }, - { 0x0201, 0x0000, 60, 60*10, 0.5 }, - { 0x0201, 0x0008, 60, 60*10, 10 }, - { 0x0201, 0x0012, 60, 60*10, 0.5 }, - { 0x0008, 0x0000, 1, 60*60, 5 }, - { 0x0300, 0x0000, 1, 60*60, 5 }, - { 0x0300, 0x0001, 1, 60*60, 5 }, - { 0x0300, 0x0003, 1, 60*60, 100 }, - { 0x0300, 0x0004, 1, 60*60, 100 }, - { 0x0300, 0x0007, 1, 60*60, 5 }, - { 0x0300, 0x0008, 1, 60*60, 0 }, - { 0x0400, 0x0000, 10, 60*60, 5 }, - { 0x0402, 0x0000, 30, 60*60, 0.2 }, - { 0x0403, 0x0000, 30, 60*60, 1 }, - { 0x0405, 0x0000, 30, 60*60, 1.0 }, - { 0x0406, 0x0000, 10, 60*60, 0 }, - { 0x0500, 0x0002, 1, 60*60, 0 }, -}; - - - - - - -void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - - SBuffer buf(12*6); - - - Response_P(PSTR("ZbSend {\"Device\":\"0x%04X\",\"Config\":{"), shortaddr); - - boolean comma = false; - for (uint32_t i=0; i 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), mqtt_data); - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - shortaddr, - 0x0000, - cluster , - endpoint, - ZCL_CONFIGURE_REPORTING, - 0x0000, - false , - false , - false , - zigbee_devices.getNextSeqNumber(shortaddr), - buf.buf(), buf.len() - })); - } -} - - - - - -#ifdef USE_ZIGBEE_EZSP -int32_t EZ_ReceiveTCJoinHandler(int32_t res, const class SBuffer &buf) { - uint16_t srcAddr = buf.get16(2); - uint64_t ieeeAddr = buf.get64(4); - uint8_t status = buf.get8(12); - uint8_t decision = buf.get8(13); - uint16_t parentNw = buf.get16(14); - - if (EMBER_DEVICE_LEFT != status) { - zigbee_devices.updateDevice(srcAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" - ",\"ParentNetwork\":\"0x%04X\"" - ",\"Status\":%d,\"Decision\":%d" - "}}"), - ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw, - status, decision - ); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - } - return -1; -} -#endif - - - - - -void Z_IncomingMessage(class ZCLFrame &zcl_received) { - uint16_t srcaddr = zcl_received.getSrcAddr(); - uint16_t groupid = zcl_received.getGroupAddr(); - uint16_t clusterid = zcl_received.getClusterId(); - uint8_t linkquality = zcl_received.getLinkQuality(); - uint8_t srcendpoint = zcl_received.getSrcEndpoint(); - linkquality = linkquality != 0xFF ? linkquality : 0xFE; - - bool defer_attributes = false; - - - zcl_received.log(); - - zigbee_devices.setLQI(srcaddr, linkquality != 0xFF ? linkquality : 0xFE); - zigbee_devices.setLastSeenNow(srcaddr); - - char shortaddr[8]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); - - Z_attribute_list attr_list; - attr_list.lqi = linkquality; - attr_list.src_ep = srcendpoint; - if (groupid) { - attr_list.group_id = groupid; - } - - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_DEFAULT_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseResponse(); - } else { - - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseReportAttributes(attr_list); - if (clusterid) { defer_attributes = true; } - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseReadAttributesResponse(attr_list); - if (clusterid) { defer_attributes = true; } - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseReadAttributes(attr_list); - - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_REPORTING_CONFIGURATION_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseReadConfigAttributes(attr_list); - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_CONFIGURE_REPORTING_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseConfigAttributes(attr_list); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(attr_list); - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":{%s}}"), srcaddr, attr_list.toString().c_str()); - - - if (srcaddr == localShortAddr) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "loopback message, ignoring")); - return; - } - - zcl_received.generateSyntheticAttributes(attr_list); - zcl_received.computeSyntheticAttributes(attr_list); - zcl_received.generateCallBacks(attr_list); - zcl_received.postProcessAttributes(srcaddr, attr_list); - - - zigbee_devices.resetTimersForDevice(srcaddr, 0 , Z_CAT_REACHABILITY); - zigbee_devices.setReachable(srcaddr, true); - - if (defer_attributes) { - - if (zigbee_devices.jsonIsConflict(srcaddr, attr_list)) { - - zigbee_devices.jsonPublishFlush(srcaddr); - } - zigbee_devices.jsonAppend(srcaddr, attr_list); - zigbee_devices.setTimer(srcaddr, 0 , USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, Z_CAT_READ_ATTR, 0, &Z_PublishAttributes); - } else { - - zigbee_devices.jsonPublishNow(srcaddr, attr_list); - } - } -} - - -#ifdef USE_ZIGBEE_EZSP - - - - - -void EZ_SendZDO(uint16_t shortaddr, uint16_t cmd, const unsigned char *payload, size_t payload_len) { - SBuffer buf(payload_len + 22); - uint8_t seq = zigbee_devices.getNextSeqNumber(0x0000); - - if (shortaddr < 0xFFFC) { - - buf.add16(EZSP_sendUnicast); - - buf.add8(EMBER_OUTGOING_DIRECT); - buf.add16(shortaddr); - - buf.add16(0x0000); - buf.add16(cmd); - buf.add8(0); - buf.add8(0); - buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); - buf.add16(0x0000); - buf.add8(seq); - - buf.add8(0x01); - buf.add8(payload_len + 1); - buf.add8(seq); - buf.addBuffer(payload, payload_len); - } else { - - buf.add16(EZSP_sendBroadcast); - buf.add16(shortaddr); - - buf.add16(0x0000); - buf.add16(cmd); - buf.add8(0); - buf.add8(0); - buf.add16(0x00); - buf.add16(0x0000); - buf.add8(seq); - - buf.add8(0x1E); - buf.add8(0x01); - buf.add8(payload_len + 1); - buf.add8(seq); - buf.addBuffer(payload, payload_len); - } - - ZigbeeEZSPSendCmd(buf.buf(), buf.len()); -} - - - - - -int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { - uint8_t msgtype = buf.get8(2); - bool wasbroadcast = (msgtype >= EMBER_INCOMING_MULTICAST) && (msgtype <= EMBER_INCOMING_BROADCAST_LOOPBACK); - uint16_t profileid = buf.get16(3); - uint16_t clusterid = buf.get16(5); - uint8_t srcendpoint = buf.get8(7); - uint8_t dstendpoint = buf.get8(8); - uint16_t apsoptions = buf.get16(9); - bool securityuse = (apsoptions & EMBER_APS_OPTION_ENCRYPTION) ? true : false; - uint16_t groupid = buf.get16(11); - uint8_t seqnumber = buf.get8(13); - int8_t linkrssi = buf.get8(15); - uint8_t linkquality = ZNP_RSSI2Lqi(linkrssi); - uint16_t srcaddr = buf.get16(16); - - - - - - if ((0x0000 == profileid) && (0x00 == srcendpoint)) { - - - zigbee_devices.setLQI(srcaddr, linkquality); - zigbee_devices.setLastSeenNow(srcaddr); - - - SBuffer zdo_buf(buf.get8(20) - 1 + 2); - zdo_buf.addBuffer(buf.buf(22), buf.get8(20) - 1); - zdo_buf.add16(srcaddr); - switch (clusterid) { - case ZDO_Device_annce: - return Z_ReceiveEndDeviceAnnonce(res, zdo_buf); - case ZDO_Active_EP_rsp: - return Z_ReceiveActiveEp(res, zdo_buf); - case ZDO_IEEE_addr_rsp: - return Z_ReceiveIEEEAddr(res, zdo_buf); - case ZDO_Simple_Desc_rsp: - return Z_ReceiveSimpleDesc(res, zdo_buf); - case ZDO_Bind_rsp: - return Z_BindRsp(res, zdo_buf); - case ZDO_Unbind_rsp: - return Z_UnbindRsp(res, zdo_buf); - case ZDO_Mgmt_Bind_rsp: - return Z_MgmtBindRsp(res, zdo_buf); - case ZDO_Parent_annce: - return EZ_ParentAnnceRsp(res, zdo_buf, false); - case ZDO_Parent_annce_rsp: - return EZ_ParentAnnceRsp(res, zdo_buf, true); - default: - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Internal ZDO message 0x%04X sent from 0x%04X %s"), clusterid, srcaddr, wasbroadcast ? PSTR("(broadcast)") : ""); - break; - } - } else { - bool defer_attributes = false; - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 21, buf.get8(20), clusterid, groupid, - srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber); - - Z_IncomingMessage(zcl_received); - } - return -1; -} - - - - - - -int32_t EZ_Reset_Device(uint8_t value) { - - - - - - if (PinUsed(GPIO_ZIGBEE_RST)) { - digitalWrite(Pin(GPIO_ZIGBEE_RST), value); - } else { - - if (value) { - uint8_t ezsp_reset[1] = { 0xC0 }; - ZigbeeEZSPSendRaw(ezsp_reset, sizeof(ezsp_reset), true); - } - } - return 0; -} - - - - - -int32_t EZ_Recv_Default(int32_t res, const class SBuffer &buf) { - - if (zigbee.init_phase) { - - return -1; - } else { - uint16_t ezsp_command_index = buf.get16(0); - - switch (ezsp_command_index) { - case EZSP_incomingMessageHandler: - return EZ_IncomingMessage(res, buf); - break; - case EZSP_trustCenterJoinHandler: - return EZ_ReceiveTCJoinHandler(res, buf); - break; - case EZSP_incomingRouteErrorHandler: - return EZ_RouteError(res, buf); - break; - case EZSP_permitJoining: - return EZ_PermitJoinRsp(res, buf); - break; - case EZSP_messageSentHandler: - return EZ_MessageSent(res, buf); - break; - } - return -1; - } -} - -#endif - - - - - - -void Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { - zigbee_devices.jsonPublishFlush(shortaddr); -} - - - - - -#ifdef USE_ZIGBEE_ZNP - - - - - - -int32_t ZNP_Reset_Device(uint8_t value) { - - - - - - if (PinUsed(GPIO_ZIGBEE_RST)) { - digitalWrite(Pin(GPIO_ZIGBEE_RST), value); - } else { - - if (value) { - - ZigbeeZNPFlush(); - ZigbeeZNPSend(ZBS_RESET, sizeof(ZBS_RESET)); - } - } - return 0; -} - -int32_t ZNP_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { - uint16_t groupid = buf.get16(2); - uint16_t clusterid = buf.get16(4); - uint16_t 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); - - uint8_t seqnumber = buf.get8(17); - - bool defer_attributes = false; - - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, - srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber); - - Z_IncomingMessage(zcl_received); - - return -1; -} - -#endif - - - - - - -#ifdef USE_ZIGBEE_ZNP - - -typedef struct Z_Dispatcher { - uint8_t match[2]; - ZB_RecvMsgFunc func; -} Z_Dispatcher; - - -const Z_Dispatcher Z_DispatchTable[] PROGMEM = { - { { Z_AREQ | Z_AF, AF_DATA_CONFIRM }, &ZNP_DataConfirm }, - { { Z_AREQ | Z_AF, AF_INCOMING_MSG }, &ZNP_ReceiveAfIncomingMessage }, - - { { Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND }, &Z_ReceiveEndDeviceAnnonce }, - { { Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND }, &ZNP_ReceiveTCDevInd }, - { { Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND }, &ZNP_ReceivePermitJoinStatus }, - { { Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP }, &ZNP_ReceiveNodeDesc }, - { { Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP }, &Z_ReceiveActiveEp }, - { { Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP}, &Z_ReceiveSimpleDesc}, - { { Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP }, &Z_ReceiveIEEEAddr }, - { { Z_AREQ | Z_ZDO, ZDO_BIND_RSP }, &Z_BindRsp }, - { { Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP }, &Z_UnbindRsp }, - { { Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP }, &Z_MgmtBindRsp }, -}; - - - - - -int32_t ZNP_Recv_Default(int32_t res, const class SBuffer &buf) { - - if (zigbee.init_phase) { - - return -1; - } else { - for (uint32_t i = 0; i < ARRAY_SIZE(Z_DispatchTable); i++) { - if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { - (*Z_DispatchTable[i].func)(res, buf); - } - } - return -1; - } -} - -#endif -# 1731 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -int32_t Z_Load_Devices(uint8_t value) { - - loadZigbeeDevices(); - return 0; -} - - - - -void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) { - const uint32_t inter_message_ms = 100; - - if (0 <= zigbee_devices.getHueBulbtype(shortaddr)) { - uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - - if (endpoint) { - zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0006, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0008, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - zigbee_devices.setTimer(shortaddr, 0 , wait_ms, 0x0300, endpoint, Z_CAT_READ_CLUSTER, 0 , &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 , &Z_Unreachable); - wait_ms += 1000; - } - } -} - - - - -int32_t Z_Query_Bulbs(uint8_t value) { - - uint32_t wait_ms = 1000; - for (uint32_t i = 0; i < zigbee_devices.devicesSize(); i++) { - const Z_Device &device = zigbee_devices.devicesAt(i); - Z_Query_Bulb(device.shortaddr, wait_ms); - } - return 0; -} - - - - -int32_t Z_State_Ready(uint8_t value) { - zigbee.init_phase = false; - return 0; -} - - - - - - -void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) { - Z_attribute_list attr_list; - - for (uint32_t i=0; i 0xFEFF) ? uxy[i] : 0xFEFF; - } - if (0x0000 == attr_id) { attr.setUInt(changeUIntScale(hue, 0, 360, 0, 254)); } - if (0x0001 == attr_id) { attr.setUInt(changeUIntScale(sat, 0, 255, 0, 254)); } - if (0x0003 == attr_id) { attr.setUInt(uxy[0]); } - if (0x0004 == attr_id) { attr.setUInt(uxy[1]); } - if (0x0007 == attr_id) { attr.setUInt(LightGetColorTemp()); } - } - break; -#endif - case 0x000A0000: - attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time); - break; - case 0x000AFF00: - attr.setUInt(Rtc.utc_time); - break; - case 0x000A0001: - attr.setUInt((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? 0x02 : 0x00); - break; - case 0x000A0002: - attr.setUInt(Settings.toffset[0] * 60); - break; - case 0x000A0007: - attr.setUInt(Settings.toffset[0] * 60 + ((Rtc.utc_time > (60 * 60 * 24 * 365 * 10)) ? Rtc.utc_time - 946684800 : Rtc.utc_time)); - break; - } - if (!attr.isNone()) { - Z_parseAttributeKey(attr); - attr_list.addAttribute(_cluster_id, attr_id) = attr; - } - } - - SBuffer buf(200); - for (const auto & attr : attr_list) { - if (!ZbAppendWriteBuf(buf, attr, true)) { - return; - } - } - - if (buf.len() > 0) { - - - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Auto-responder: ZbSend {\"Device\":\"0x%04X\"" - ",\"Cluster\":\"0x%04X\"" - ",\"Endpoint\":%d" - ",\"Response\":%s}" - ), - _srcaddr, _cluster_id, _srcendpoint, - attr_list.toString().c_str()); - - - - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - _srcaddr, - 0x0000, - _cluster_id , - _srcendpoint, - ZCL_READ_ATTRIBUTES_RESPONSE, - 0x0000, - false , - false , - true , - _transact_seq, - buf.getBuffer(), buf.len() - })); - } -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" -#ifdef USE_ZIGBEE - -#ifdef USE_ZIGBEE_ZNP -const uint32_t ZIGBEE_BUFFER_SIZE = 256; -const uint8_t ZIGBEE_SOF = 0xFE; -const uint8_t ZIGBEE_SOF_ALT = 0xFF; -#endif - -#ifdef USE_ZIGBEE_EZSP -const uint32_t ZIGBEE_BUFFER_SIZE = 256; -const uint8_t ZIGBEE_EZSP_CANCEL = 0x1A; -const uint8_t ZIGBEE_EZSP_EOF = 0x7E; -const uint8_t ZIGBEE_EZSP_ESCAPE = 0x7D; - -const uint32_t ZIGBEE_LED_RECEIVE = 0; -const uint32_t ZIGBEE_LED_SEND = 0; - -class EZSP_Serial_t { -public: - uint8_t to_send = 0; - uint8_t to_end = 0; - uint8_t to_ack = 0; - uint8_t from_ack = 0; - uint8_t ezsp_seq = 0; - SBuffer *to_packets[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; -}; - - -EZSP_Serial_t EZSP_Serial; - - - - -const uint32_t Z_LED_STATUS_ON_MILLIS = 50; -bool Z_LedStatusSet(bool onoff) { - static bool led_status_on = false; - static uint32_t led_on_time = 0; - - if (onoff) { - SetLedPowerIdx(ZIGBEE_LED_RECEIVE, 1); - led_status_on = true; - led_on_time = millis(); - } else if ((led_status_on) && (TimePassedSince(led_on_time) >= Z_LED_STATUS_ON_MILLIS)) { - SetLedPowerIdx(ZIGBEE_LED_RECEIVE, 0); - led_status_on = false; - } - return led_status_on; -} - -#endif - -#include -TasmotaSerial *ZigbeeSerial = nullptr; - - - - - -void ZigbeeInputLoop(void) { - -#ifdef USE_ZIGBEE_ZNP - static uint32_t zigbee_polling_window = 0; - static uint8_t fcs = ZIGBEE_SOF; - static uint32_t zigbee_frame_len = 5; -# 92 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" - while (ZigbeeSerial->available()) { - yield(); - uint8_t zigbee_in_byte = ZigbeeSerial->read(); - - - if (0 == zigbee_buffer->len()) { - zigbee_frame_len = 5; - fcs = ZIGBEE_SOF; - - - - if (ZIGBEE_SOF_ALT == zigbee_in_byte) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); - zigbee_in_byte = ZIGBEE_SOF; - } - } - - if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput 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)); - - - - 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 { - - - - 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); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - - ZigbeeProcessInput(znp_buffer); - } - zigbee_buffer->setLen(0); - } -#endif - -#ifdef USE_ZIGBEE_EZSP - static uint32_t zigbee_polling_window = 0; - static bool escape = false; - bool frame_complete = false; - - - - - - Z_LedStatusSet(false); - - while (ZigbeeSerial->available()) { - Z_LedStatusSet(true); - - yield(); - uint8_t zigbee_in_byte = ZigbeeSerial->read(); - - - - - - - - if ((0x11 == zigbee_in_byte) || (0x13 == zigbee_in_byte)) { - continue; - } - - if (ZIGBEE_EZSP_ESCAPE == zigbee_in_byte) { - - escape = true; - continue; - } - - if (ZIGBEE_EZSP_CANCEL == zigbee_in_byte) { - - zigbee_buffer->setLen(0); - escape = false; - frame_complete = false; - continue; - } - - if (ZIGBEE_EZSP_EOF == zigbee_in_byte) { - - frame_complete = true; - break; - } - - if (zigbee_buffer->len() < ZIGBEE_BUFFER_SIZE) { - if (escape) { - - zigbee_in_byte ^= 0x20; - escape = false; - } - - zigbee_buffer->add8(zigbee_in_byte); - zigbee_polling_window = millis(); - } - } - - uint32_t frame_len = zigbee_buffer->len(); - if (frame_complete || (frame_len && (millis() > (zigbee_polling_window + ZIGBEE_POLLING)))) { - char hex_char[frame_len * 2 + 2]; - ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); - - - if ((frame_complete) && (frame_len >= 3)) { - - - uint16_t crc = 0xFFFF; - - for (uint32_t i=0; iget8(i) << 8); - for (uint32_t i=0; i<8; i++) { - if (crc & 0x8000) { - crc = (crc << 1) ^ 0x1021; - } else { - crc <<= 1; - } - } - } - - uint16_t crc_received = zigbee_buffer->get8(frame_len - 2) << 8 | zigbee_buffer->get8(frame_len - 1); - - - if (crc_received != crc) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": bad crc (received 0x%04X, computed 0x%04X) %s"), crc_received, crc, hex_char); - } else { - - SBuffer ezsp_buffer = zigbee_buffer->subBuffer(0, frame_len - 2); - - - if (0 == (ezsp_buffer.get8(0) & 0x80)) { - - uint8_t rand = 0x42; - for (uint32_t i=1; i> 1) ^ 0xB8; } - else { rand = (rand >> 1); } - } - } - - ToHex_P((unsigned char*)ezsp_buffer.getBuffer(), ezsp_buffer.len(), hex_char, sizeof(hex_char)); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "{\"" D_JSON_ZIGBEE_EZSP_RECEIVED "2\":\"%s\"}"), hex_char); - - ZigbeeProcessInputRaw(ezsp_buffer); - } - } else { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": time-out, discarding %s, %d"), hex_char); - } - zigbee_buffer->setLen(0); - escape = false; - frame_complete = false; - } - -#endif - -} - - - - -void ZigbeeInitSerial(void) -{ - - zigbee.active = false; - if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX)); - - ZigbeeSerial = new TasmotaSerial(Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX), seriallog_level ? 1 : 2, 0, 256); - ZigbeeSerial->begin(115200); - if (ZigbeeSerial->hardwareSerial()) { - ClaimSerial(); - uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); - } else { - - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); - - } - - if (PinUsed(GPIO_ZIGBEE_RST)) { - pinMode(Pin(GPIO_ZIGBEE_RST), OUTPUT); - digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); - } - - zigbee.active = true; - zigbee.init_phase = true; - zigbee.state_machine = true; - ZigbeeSerial->flush(); - } - -} - -#ifdef USE_ZIGBEE_ZNP - - -void ZigbeeZNPFlush(void) { - if (ZigbeeSerial) { - for (uint32_t i = 0; i < 256; i++) { - ZigbeeSerial->write(0xFF); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " 0xFF x 255")); - } -} - -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); - - ZigbeeSerial->write(data_len); - - for (uint32_t i = 0; i < len; i++) { - uint8_t b = pgm_read_byte(msg + i); - ZigbeeSerial->write(b); - fcs ^= b; - - } - ZigbeeSerial->write(fcs); - - } - - char hex_char[(len * 2) + 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), - ToHex_P(msg, len, hex_char, sizeof(hex_char))); -} - - - - - -void CmndZbZNPSendOrReceive(bool send) -{ - 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 > 1) { - char stemp[3]; - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, nullptr, 16); - buf.add8(code); - size -= 2; - codes += 2; - } - if (send) { - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - } else { - - ZigbeeProcessInput(buf); - } - } - ResponseCmndDone(); -} - - -void CmndZbZNPReceive(void) -{ - CmndZbZNPSendOrReceive(false); -} - -void CmndZbZNPSend(void) -{ - CmndZbZNPSendOrReceive(true); -} - -#endif - -#ifdef USE_ZIGBEE_EZSP - - -void ZigbeeEZSPSend_Out(uint8_t out_byte) { - switch (out_byte) { - case 0x7E: - case 0x11: - case 0x13: - case 0x18: - case 0x1A: - case 0x7D: - - ZigbeeSerial->write(ZIGBEE_EZSP_ESCAPE); - ZigbeeSerial->write(out_byte ^ 0x20); - break; - default: - ZigbeeSerial->write(out_byte); - break; - } -} -# 443 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" -void ZigbeeEZSPSendRaw(const uint8_t *msg, size_t len, bool send_cancel) { - if ((len < 1) || (len > 252)) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEE_EZSP_SENT ": bad message len %d"), len); - return; - } - uint8_t data_len = len - 2; - - - Z_LedStatusSet(true); - - if (ZigbeeSerial) { - if (send_cancel) { - ZigbeeSerial->write(ZIGBEE_EZSP_CANCEL); - } - - bool data_frame = (0 == (msg[0] & 0x80)); - uint8_t rand = 0x42; - uint16_t crc = 0xFFFF; - - for (uint32_t i=0; i 0)) { - out_byte ^= rand; - if (rand & 1) { rand = (rand >> 1) ^ 0xB8; } - else { rand = (rand >> 1); } - } - - - crc = crc ^ ((uint16_t)out_byte << 8); - for (uint32_t i=0; i<8; i++) { - if (crc & 0x8000) { - crc = (crc << 1) ^ 0x1021; - } else { - crc <<= 1; - } - } - - - ZigbeeEZSPSend_Out(out_byte); - } - - ZigbeeEZSPSend_Out(crc >> 8); - ZigbeeEZSPSend_Out(crc & 0xFF); - - - ZigbeeSerial->write(ZIGBEE_EZSP_EOF); - } - - - char hex_char[(len * 2) + 2]; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEE_EZSP_SENT_RAW " %s"), - ToHex_P(msg, len, hex_char, sizeof(hex_char))); -} - - - -void ZigbeeEZSPSendCmd(const uint8_t *msg, size_t len) { - char hex_char[len*2 + 2]; - ToHex_P(msg, len, hex_char, sizeof(hex_char)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbEZSPSend %s"), hex_char); - - SBuffer cmd(len+3); - - cmd.add8(EZSP_Serial.ezsp_seq++); - cmd.add8(0x00); - cmd.add8(0x01); - cmd.addBuffer(msg, len); - - - ZigbeeEZSPSendDATA(cmd.getBuffer(), cmd.len()); -} - - -void ZigbeeEZSPSendDATA_frm(bool send_cancel, uint8_t to_frm, uint8_t from_ack) { - SBuffer *buf = EZSP_Serial.to_packets[to_frm]; - if (!buf) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Buffer for packet %d is not allocated"), EZSP_Serial.to_send); - return; - } - - uint8_t control_byte = ((to_frm & 0x07) << 4) + (from_ack & 0x07); - buf->set8(0, control_byte); - - ZigbeeEZSPSendRaw(buf->getBuffer(), buf->len(), send_cancel); -} - - -void ZigbeeEZSPSendDATA(const uint8_t *msg, size_t len) { - - SBuffer *buf = new SBuffer(len+1); - buf->add8(0x00); - buf->addBuffer(msg, len); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: adding packet to_send, to_ack:%d, to_send:%d, to_end:%d"), - EZSP_Serial.to_ack, EZSP_Serial.to_send, EZSP_Serial.to_end); - uint8_t to_frm = EZSP_Serial.to_end; - if (EZSP_Serial.to_packets[to_frm]) { - delete EZSP_Serial.to_packets[to_frm]; - EZSP_Serial.to_packets[to_frm] = nullptr; - } - EZSP_Serial.to_packets[to_frm] = buf; - EZSP_Serial.to_end = (to_frm + 1) & 0x07; - - - - - - -} - - -int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) { - - - - uint16_t frame_control = buf.get16(1); - bool truncated = frame_control & 0x02; - bool overflow = frame_control & 0x01; - bool callbackPending = frame_control & 0x04; - bool security_enabled = frame_control & 0x8000; - if (truncated || overflow || security_enabled) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: specific frame_control 0x%04X"), frame_control); - } - - - for (uint32_t i=0; i> 4) + 1) & 0x07; - uint8_t ack_byte = 0x80 | EZSP_Serial.from_ack; - ZigbeeEZSPSendRaw(&ack_byte, 1, false); - - - - for (uint8_t i=0; i 0)) { - uint8_t code; - - char *codes = RemoveSpace(XdrvMailbox.data); - int32_t size = strlen(XdrvMailbox.data); - - SBuffer buf((size+1)/2); - - while (size > 1) { - char stemp[3]; - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, nullptr, 16); - buf.add8(code); - size -= 2; - codes += 2; - } - if (send) { - - if (2 == XdrvMailbox.index) { ZigbeeEZSPSendDATA(buf.getBuffer(), buf.len()); } - else if (3 == XdrvMailbox.index) { ZigbeeEZSPSendRaw(buf.getBuffer(), buf.len(), true); } - else { ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); } - - } else { - - if (2 == XdrvMailbox.index) { ZigbeeProcessInput(buf); } - else if (3 == XdrvMailbox.index) { ZigbeeProcessInputRaw(buf); } - else { ZigbeeProcessInputEZSP(buf); } - } - } - ResponseCmndDone(); -} - - -void CmndZbEZSPReceive(void) -{ - CmndZbEZSPSendOrReceive(false); -} - -void CmndZbEZSPSend(void) -{ - CmndZbEZSPSendOrReceive(true); -} -#endif -# 773 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9_serial.ino" -void ZigbeeZCLSend_Raw(const ZigbeeZCLSendMessage &zcl) { - -#ifdef USE_ZIGBEE_ZNP - SBuffer buf(32+zcl.len); - buf.add8(Z_SREQ | Z_AF); - buf.add8(AF_DATA_REQUEST_EXT); - if (BAD_SHORTADDR == zcl.shortaddr) { - buf.add8(Z_Addr_Group); - buf.add64(zcl.groupaddr); - buf.add8(0xFF); - } else { - buf.add8(Z_Addr_ShortAddress); - buf.add64(zcl.shortaddr); - buf.add8(zcl.endpoint); - } - buf.add16(0x0000); - buf.add8(0x01); - buf.add16(zcl.cluster); - buf.add8(zcl.transacId); - buf.add8(0x30); - buf.add8(0x1E); - - buf.add16(3 + zcl.len + (zcl.manuf ? 2 : 0)); - buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); - if (zcl.manuf) { - buf.add16(zcl.manuf); - } - buf.add8(zcl.transacId); - buf.add8(zcl.cmd); - if (zcl.len > 0) { - buf.addBuffer(zcl.msg, zcl.len); - } - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -#endif - -#ifdef USE_ZIGBEE_EZSP - SBuffer buf(32+zcl.len); - - if (BAD_SHORTADDR != zcl.shortaddr) { - - buf.add16(EZSP_sendUnicast); - buf.add8(EMBER_OUTGOING_DIRECT); - buf.add16(zcl.shortaddr); - - buf.add16(Z_PROF_HA); - buf.add16(zcl.cluster); - buf.add8(0x01); - buf.add8(zcl.endpoint); - if (zcl.direct) { - buf.add16(0x0000); - } else { - buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); - } - buf.add16(zcl.groupaddr); - buf.add8(zcl.transacId); - - buf.add8(0x01); - - buf.add8(3 + zcl.len + (zcl.manuf ? 2 : 0)); - buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); - if (zcl.manuf) { - buf.add16(zcl.manuf); - } - buf.add8(zcl.transacId); - buf.add8(zcl.cmd); - if (zcl.len > 0) { - buf.addBuffer(zcl.msg, zcl.len); - } - } else { - - buf.add16(EZSP_sendMulticast); - - buf.add16(Z_PROF_HA); - buf.add16(zcl.cluster); - buf.add8(0x01); - buf.add8(zcl.endpoint); - if (zcl.direct) { - buf.add16(0x0000); - } else { - buf.add16(EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY | EMBER_APS_OPTION_RETRY); - } - buf.add16(zcl.groupaddr); - buf.add8(zcl.transacId); - - buf.add8(0); - buf.add8(7); - buf.add8(0x01); - - buf.add8(3 + zcl.len + (zcl.manuf ? 2 : 0)); - buf.add8((zcl.needResponse ? 0x00 : 0x10) | (zcl.clusterSpecific ? 0x01 : 0x00) | (zcl.manuf ? 0x04 : 0x00)); - if (zcl.manuf) { - buf.add16(zcl.manuf); - } - buf.add8(zcl.transacId); - buf.add8(zcl.cmd); - if (zcl.len > 0) { - buf.addBuffer(zcl.msg, zcl.len); - } - } - - ZigbeeEZSPSendCmd(buf.buf(), buf.len()); -#endif -} - - - - - -void ZigbeeOutputLoop(void) { -#ifdef USE_ZIGBEE_EZSP - - if (EZSP_Serial.to_send != EZSP_Serial.to_end) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Something to_send, to_ack:%d, to_send:%d, to_end:%d"), - EZSP_Serial.to_ack, EZSP_Serial.to_send, EZSP_Serial.to_end); - - ZigbeeEZSPSendDATA_frm(true, EZSP_Serial.to_send, EZSP_Serial.from_ack); - - EZSP_Serial.to_send = (EZSP_Serial.to_send + 1) & 0x07; - } -#endif -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" -#ifdef USE_ZIGBEE - -#ifdef USE_ZIGBEE_EZSP -# 33 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" -#define XM_SOH 0x01 -#define XM_EOT 0x04 -#define XM_ACK 0x06 -#define XM_CR 0x0d -#define XM_NAK 0x15 -#define XM_CAN 0x18 -#define XM_SUB 0x1a - -enum ZbUploadSteps { ZBU_IDLE, ZBU_INIT, - ZBU_SOFTWARE_RESET, ZBU_SOFTWARE_SEND, ZBU_HARDWARE_RESET, ZBU_PROMPT, - ZBU_SYNC, ZBU_UPLOAD, ZBU_EOT, ZBU_COMPLETE, ZBU_DONE, ZBU_ERROR, ZBU_FINISH }; - -const uint8_t PIN_ZIGBEE_BOOTLOADER = 5; - -struct ZBUPLOAD { - uint32_t ota_size = 0; - uint32_t sector_cursor = 0; - uint32_t sector_counter = 0; - uint32_t byte_counter = 0; - char *buffer; - uint8_t ota_step = ZBU_IDLE; - uint8_t bootloader = 0; - uint8_t state = ZBU_IDLE; -} ZbUpload; - - - - - -uint32_t ZigbeeUploadFlashStart(void) { - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; -} - -uint32_t ZigbeeUploadAvailable(void) { - int available = ZbUpload.ota_size - ZbUpload.byte_counter; - if (available < 0) { available = 0; } - return available; -} - -char ZigbeeUploadFlashRead(void) { - if (0 == ZbUpload.byte_counter) { - if (!(ZbUpload.buffer = (char *)malloc(SPI_FLASH_SEC_SIZE))) { - return (-1); - } - ZbUpload.sector_counter = ZigbeeUploadFlashStart(); - } - - uint32_t index = ZbUpload.byte_counter % SPI_FLASH_SEC_SIZE; - if (0 == index) { - ESP.flashRead(ZbUpload.sector_counter * SPI_FLASH_SEC_SIZE, (uint32_t*)ZbUpload.buffer, SPI_FLASH_SEC_SIZE); - ZbUpload.sector_counter++; - } - - char data = ZbUpload.buffer[index]; - ZbUpload.byte_counter++; - - if (ZbUpload.byte_counter > ZbUpload.ota_size) { - - - data = XM_SUB; - - } - return data; -} - - - - - - -const uint32_t XMODEM_FLUSH_DELAY = 1000; - -const uint8_t XMODEM_SYNC_TIMEOUT = 30; - -const uint8_t XMODEM_MAX_RETRY = 30; - -const uint8_t XMODEM_PACKET_SIZE = 128; - -struct XMODEM { - uint32_t timeout = 0; - uint32_t delay = 0; - uint32_t flush_delay = 0xFFFFFFFF; - uint32_t filepos = 0; - int crcBuf = 0; - uint8_t packetNo = 1; - uint8_t checksumBuf = 0; - bool oldChecksum; -} XModem; - - -void XModemOutputByte(uint8_t out_char) { - XModem.checksumBuf += out_char; - - XModem.crcBuf = XModem.crcBuf ^ (int) out_char << 8; - for (uint32_t i = 0; i < 8; i++) { - if (XModem.crcBuf & 0x8000) { - XModem.crcBuf = XModem.crcBuf << 1 ^ 0x1021; - } else { - XModem.crcBuf = XModem.crcBuf << 1; - } - } - - ZigbeeSerial->write(out_char); -} - - - -char XModemWaitACK(void) -{ - char in_char; - do { - uint8_t i = 0; - while (!ZigbeeSerial->available()) { - delayMicroseconds(100); - i++; - if (i > 200) { return -1; } - } - in_char = ZigbeeSerial->read(); - if (XM_CAN == in_char) { return XM_CAN; } - } while ((in_char != XM_NAK) && (in_char != XM_ACK) && (in_char != 'C')); - return in_char; -} - -bool XModemSendPacket(uint32_t packet_no) { - XModem.filepos = ZbUpload.byte_counter; - - - uint32_t retries = 0; - char in_char; - do { - - - ZbUpload.byte_counter = XModem.filepos; - - - XModem.checksumBuf = 0x00; - XModem.crcBuf = 0x00; - - - ZigbeeSerial->write(XM_SOH); - ZigbeeSerial->write(packet_no); - ZigbeeSerial->write(~packet_no); - for (uint32_t i = 0; i < XMODEM_PACKET_SIZE; i++) { - in_char = ZigbeeUploadFlashRead(); - XModemOutputByte(in_char); - } - - - if (XModem.oldChecksum) { - ZigbeeSerial->write((char)XModem.checksumBuf); - } else { - ZigbeeSerial->write((char)(XModem.crcBuf >> 8)); - ZigbeeSerial->write((char)(XModem.crcBuf & 0xFF)); - } - in_char = XModemWaitACK(); - if (XM_CAN == in_char) { return false; } - retries++; - if (retries > XMODEM_MAX_RETRY) { return false; } - } while (in_char != XM_ACK); - return true; -} - - - - - - - -void ZigbeeUploadSetSoftwareBootloader() { - - SBuffer buf(4); - buf.add16(EZSP_launchStandaloneBootloader); - buf.add8(0x01); - ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); -} - -void ZigbeeUploadSetBootloader(uint8_t state) { - pinMode(PIN_ZIGBEE_BOOTLOADER, OUTPUT); - digitalWrite(PIN_ZIGBEE_BOOTLOADER, state); - digitalWrite(Pin(GPIO_ZIGBEE_RST), 0); - delay(100); - digitalWrite(Pin(GPIO_ZIGBEE_RST), 1); -} - -bool ZigbeeUploadBootloaderPrompt(void) { - - - - - uint8_t serial_buffer[255]; - uint32_t buf_len = 0; - - while (ZigbeeSerial->available()) { - yield(); - char bootloader_byte = ZigbeeSerial->read(); - - if (((uint8_t)bootloader_byte >=0) && (buf_len < sizeof(serial_buffer) -2)) { - serial_buffer[buf_len++] = bootloader_byte; - } - - if (ZbUpload.byte_counter != 4) { - switch (ZbUpload.byte_counter) { - case 0: - if ('B' == bootloader_byte) { ZbUpload.byte_counter++; } break; - case 1: - if ('L' == bootloader_byte) { ZbUpload.byte_counter++; } break; - case 2: - if (' ' == bootloader_byte) { ZbUpload.byte_counter++; } break; - case 3: - if ('>' == bootloader_byte) { - ZbUpload.byte_counter++; - XModem.flush_delay = millis() + XMODEM_FLUSH_DELAY; - XModem.delay = XModem.flush_delay + XMODEM_FLUSH_DELAY; - } - } - } - } - - if (buf_len) { - char hex_char[256]; - ToHex_P(serial_buffer, buf_len, hex_char, 256); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("XMD: Rcvd %s"), hex_char); - } - - return ((4 == ZbUpload.byte_counter) && (millis() > XModem.flush_delay)); -} - -bool ZigbeeUploadXmodem(void) { - switch (ZbUpload.ota_step) { - case ZBU_IDLE: { - return false; - } -#ifdef ZIGBEE_BOOTLOADER_SOFTWARE_RESET_FIRST - case ZBU_INIT: { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init bootloader")); - ZbUpload.ota_step = ZBU_SOFTWARE_RESET; - return false; - } - case ZBU_SOFTWARE_RESET: { - SBuffer buf(4); - buf.add16(EZSP_launchStandaloneBootloader); - buf.add8(0x01); - ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); - XModem.timeout = millis() + (10 * 1000); - ZbUpload.ota_step = ZBU_SOFTWARE_SEND; - return false; - } - case ZBU_SOFTWARE_SEND: { - if (millis() > XModem.timeout) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader software reset send timeout")); - ZbUpload.ota_step = ZBU_HARDWARE_RESET; - return true; - } - if (EZSP_Serial.to_send == EZSP_Serial.to_end) { - ZbUpload.bootloader = ZBU_SOFTWARE_RESET; - XModem.timeout = millis() + (10 * 1000); - XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); - ZbUpload.byte_counter = 0; - ZbUpload.ota_step = ZBU_PROMPT; - } - break; - } - case ZBU_HARDWARE_RESET: { - ZbUpload.bootloader = ZBU_HARDWARE_RESET; - ZigbeeUploadSetBootloader(0); - XModem.timeout = millis() + (30 * 1000); - XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); - ZbUpload.byte_counter = 0; - ZbUpload.ota_step = ZBU_PROMPT; - break; - } - case ZBU_PROMPT: { - if (millis() > XModem.timeout) { - if (ZBU_SOFTWARE_RESET == ZbUpload.bootloader) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader software reset timeout")); - ZbUpload.ota_step = ZBU_HARDWARE_RESET; - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader hardware reset timeout")); - ZbUpload.ota_step = ZBU_ERROR; - } - return true; - } -#else - case ZBU_INIT: { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init bootloader")); - ZigbeeUploadSetBootloader(0); - XModem.timeout = millis() + (30 * 1000); - XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); - ZbUpload.byte_counter = 0; - ZbUpload.ota_step = ZBU_PROMPT; - break; - } - case ZBU_PROMPT: { - if (millis() > XModem.timeout) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader timeout")); - ZbUpload.ota_step = ZBU_ERROR; - return true; - } -#endif - else if (!ZigbeeSerial->available() && (millis() < XModem.flush_delay)) { - - - if (millis() > XModem.delay) { - ZigbeeSerial->write(XM_CR); - XModem.delay = millis() + (2 * XMODEM_FLUSH_DELAY); - } - } else { - - - - - - - if (ZigbeeUploadBootloaderPrompt()) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init sync")); - ZigbeeSerial->flush(); - ZigbeeSerial->write('1'); - if (ssleep > 0) { - ssleep = 1; - } - XModem.timeout = millis() + (XMODEM_SYNC_TIMEOUT * 1000); - ZbUpload.ota_step = ZBU_SYNC; - } - } - break; - } - case ZBU_SYNC: { - if (millis() > XModem.timeout) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: SYNC timeout")); - ZbUpload.ota_step = ZBU_ERROR; - return true; - } - - if (ZigbeeSerial->available()) { - char xmodem_sync = ZigbeeSerial->read(); - if (('C' == xmodem_sync) || (XM_NAK == xmodem_sync)) { - - XModem.oldChecksum = (xmodem_sync == XM_NAK); - XModem.packetNo = 1; - ZbUpload.byte_counter = 0; - ZbUpload.ota_step = ZBU_UPLOAD; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init packet send")); - } - } - break; - } - case ZBU_UPLOAD: { - if (ZigbeeUploadAvailable()) { - if (!XModemSendPacket(XModem.packetNo)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Packet send failed")); - ZbUpload.ota_step = ZBU_ERROR; - return true; - } - XModem.packetNo++; - } else { - - - - ZigbeeSerial->write(XM_EOT); - XModem.timeout = millis() + (30 * 1000); - ZbUpload.ota_step = ZBU_EOT; - } - break; - } - case ZBU_EOT: { - - - - - - if (millis() > XModem.timeout) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: EOT ACK timeout")); - ZbUpload.ota_step = ZBU_ERROR; - return true; - } - if (ZigbeeSerial->available()) { - char xmodem_ack = XModemWaitACK(); - if (XM_ACK == xmodem_ack) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: " D_SUCCESSFUL)); - XModem.timeout = millis() + (30 * 1000); - ZbUpload.byte_counter = 0; - ZbUpload.ota_step = ZBU_COMPLETE; - } - } - break; - } - case ZBU_COMPLETE: { - if (millis() > XModem.timeout) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Bootloader timeout")); - ZbUpload.ota_step = ZBU_ERROR; - return true; - } else { -# 433 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_9a_upload.ino" - if (ZigbeeUploadBootloaderPrompt()) { - ZbUpload.state = ZBU_COMPLETE; - ZbUpload.ota_step = ZBU_DONE; - } - } - break; - } - case ZBU_ERROR: - ZbUpload.state = ZBU_ERROR; - case ZBU_DONE: { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: " D_RESTARTING)); - ZigbeeUploadSetBootloader(1); - if (1 == ssleep) { - ssleep = Settings.sleep; - } - - ZbUpload.ota_step = ZBU_FINISH; - break; - } - case ZBU_FINISH: { - - break; - } - } - return true; -} - - - - - -bool ZigbeeUploadOtaReady(void) { - return (ZBU_INIT == ZbUpload.ota_step); -} - -bool ZigbeeUploadFinish(void) { - return (ZBU_FINISH == ZbUpload.ota_step); -} - -uint8_t ZigbeeUploadInit(void) { - if (!PinUsed(GPIO_ZIGBEE_RST) && (ZigbeeSerial == nullptr)) { return 1; } - - ZbUpload.sector_counter = ZigbeeUploadFlashStart(); - ZbUpload.sector_cursor = 0; - ZbUpload.ota_size = 0; - ZbUpload.ota_step = ZBU_IDLE; - ZbUpload.state = ZBU_IDLE; - return 0; -} - -bool ZigbeeUploadWriteBuffer(uint8_t *buf, size_t size) { - - - if (0 == ZbUpload.sector_cursor) { - ESP.flashEraseSector(ZbUpload.sector_counter); - } - ZbUpload.sector_cursor++; - ESP.flashWrite((ZbUpload.sector_counter * SPI_FLASH_SEC_SIZE) + ((ZbUpload.sector_cursor-1) * 2048), (uint32_t*)buf, size); - ZbUpload.ota_size += size; - if (2 == ZbUpload.sector_cursor) { - ZbUpload.sector_cursor = 0; - ZbUpload.sector_counter++; - if (ZbUpload.sector_counter > (SPIFFS_END -2)) { - return false; - } - } - return true; -} - -void ZigbeeUploadDone(void) { - ZbUpload.ota_step = ZBU_INIT; - ZbUpload.state = ZBU_UPLOAD; -} - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_ZIGBEE_XFER "zx" - -const char HTTP_SCRIPT_XFER_STATE[] PROGMEM = - "function z9(){" - "if(x!=null){x.abort();}" - "x=new XMLHttpRequest();" - "x.onreadystatechange=function(){" - "if(x.readyState==4&&x.status==200){" - "var s=x.responseText;" - "if(s!=7){" - "location.href='/u3';" - "}" - "}" - "};" - "x.open('GET','" WEB_HANDLE_ZIGBEE_XFER "?z=1',true);" - "x.send();" - "lt=setTimeout(z9,950);" - "}" - "wl(z9);"; - -void HandleZigbeeXfer(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg("z")) { - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%d"), ZbUpload.state); - WSContentEnd(); - if (ZBU_ERROR == ZbUpload.state) { - Web.upload_error = 7; - } - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_UPLOAD_TRANSFER)); - - WSContentStart_P(S_INFORMATION); - WSContentSend_P(HTTP_SCRIPT_XFER_STATE); - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_UPLOAD_TRANSFER " ...
")); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - -#endif - -#endif - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" -#ifdef USE_ZIGBEE - -#define XDRV_23 23 - -const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" -#ifdef USE_ZIGBEE_ZNP - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEEZNPRECEIVE "|" -#endif -#ifdef USE_ZIGBEE_EZSP - D_CMND_ZIGBEE_EZSP_SEND "|" D_CMND_ZIGBEE_EZSP_RECEIVE "|" D_CMND_ZIGBEE_EZSP_LISTEN "|" -#endif - D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" - D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" - D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" - D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA - ; - -void (* const ZigbeeCommand[])(void) PROGMEM = { -#ifdef USE_ZIGBEE_ZNP - &CmndZbZNPSend, &CmndZbZNPReceive, -#endif -#ifdef USE_ZIGBEE_EZSP - &CmndZbEZSPSend, &CmndZbEZSPReceive, &CmndZbEZSPListen, -#endif - &CmndZbPermitJoin, - &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, - &CmndZbForget, &CmndZbSave, &CmndZbName, - &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, - &CmndZbLight, &CmndZbRestore, &CmndZbBindState, - &CmndZbConfig, CmndZbData, - }; - - - - -void ZigbeeInit(void) -{ - - - - - - if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { - if (0 == Settings.zb_channel) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Randomizing Zigbee parameters, please check with 'ZbConfig'")); - uint64_t mac64 = 0; - WiFi.macAddress((uint8_t*) &mac64); - uint32_t esp_id = ESP_getChipId(); -#ifdef ESP8266 - uint32_t flash_id = ESP.getFlashChipId(); -#else - uint32_t flash_id = 0; -#endif - - uint16_t pan_id = (mac64 & 0x3FFF); - if (0x0000 == pan_id) { pan_id = 0x0001; } - if (0x3FFF == pan_id) { pan_id = 0x3FFE; } - Settings.zb_pan_id = pan_id; - - Settings.zb_ext_panid = 0xCCCCCCCC00000000L | (mac64 & 0x00000000FFFFFFFFL); - Settings.zb_precfgkey_l = (mac64 << 32) | (esp_id << 16) | flash_id; - Settings.zb_precfgkey_h = (mac64 << 32) | (esp_id << 16) | flash_id; - Settings.zb_channel = USE_ZIGBEE_CHANNEL; - Settings.zb_txradio_dbm = USE_ZIGBEE_TXRADIO_DBM; - } - - if (Settings.zb_txradio_dbm < 0) { - Settings.zb_txradio_dbm = -Settings.zb_txradio_dbm; -#ifdef USE_ZIGBEE_EZSP - EZ_reset_config = true; -#endif - SettingsSave(2); - } - } - - -#ifdef USE_ZIGBEE_ZNP - ZNP_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h); -#endif -#ifdef USE_ZIGBEE_EZSP - EZ_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h, Settings.zb_txradio_dbm); -#endif - - ZigbeeInitSerial(); -} - - - - - -#ifdef USE_ZIGBEE_ZNP - -const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = - { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; - -#endif - -void CmndZbReset(void) { - if (ZigbeeSerial) { - switch (XdrvMailbox.payload) { - case 1: -#ifdef USE_ZIGBEE_ZNP - ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); -#endif - eraseZigbeeDevices(); - case 2: - Settings.zb_txradio_dbm = - abs(Settings.zb_txradio_dbm); - restart_flag = 2; -#ifdef USE_ZIGBEE_ZNP - ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING)); -#endif -#ifdef USE_ZIGBEE_EZSP - ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_EZSP " " D_JSON_RESET_AND_RESTARTING)); -#endif - break; - default: - ResponseCmndChar_P(PSTR("1 or 2 to reset")); - } - } -} -# 158 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" -void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf, - uint16_t cluster, uint8_t cmd, const char *param) { - size_t size = param ? strlen(param) : 0; - SBuffer buf((size+2)/2); - - if (param) { - while (*param) { - uint8_t code = parseHex_P(¶m, 2); - buf.add8(code); - } - } - - if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) { - - endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), - shortaddr, groupaddr, cluster, endpoint, cmd, param); - - if ((0 == endpoint) && (BAD_SHORTADDR != shortaddr)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); - return; - } - - - - uint8_t seq = zigbee_devices.getNextSeqNumber(shortaddr); - ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ - shortaddr, - groupaddr, - cluster , - endpoint, - cmd, - manuf, - clusterSpecific , - true , - false , - seq, - buf.getBuffer(), buf.len() - })); - - if (clusterSpecific) { -#ifndef USE_ZIGBEE_NO_READ_ATTRIBUTES - sendHueUpdate(shortaddr, groupaddr, cluster, endpoint); -#endif - } -} - - - - - - -void ZbApplyMultiplier(double &val_d, int8_t multiplier) { - if ((0 != multiplier) && (1 != multiplier)) { - if (multiplier > 0) { - val_d = val_d / multiplier; - } else { - val_d = val_d * (-multiplier); - } - } -} - - - - -bool ZbTuyaWrite(SBuffer & buf, const Z_attribute & attr, uint8_t transid) { - double val_d = attr.getFloat(); - const char * val_str = attr.getStr(); - - if (attr.key_is_str) { return false; } - if (attr.isNum() && (1 != attr.attr_multiplier)) { - ZbApplyMultiplier(val_d, attr.attr_multiplier); - } - buf.add8(0); - buf.add8(transid); - buf.add16(attr.key.id.attr_id); - buf.add8(0); - int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); - if (res < 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Error for Tuya attribute type %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); - return false; - } - return true; -} - - - - -bool ZbAppendWriteBuf(SBuffer & buf, const Z_attribute & attr, bool prepend_status_ok) { - double val_d = attr.getFloat(); - const char * val_str = attr.getStr(); - - if (attr.key_is_str) { return false; } - if (attr.isNum() && (1 != attr.attr_multiplier)) { - ZbApplyMultiplier(val_d, attr.attr_multiplier); - } - - - buf.add16(attr.key.id.attr_id); - if (prepend_status_ok) { - buf.add8(Z_SUCCESS); - } - buf.add8(attr.attr_type); - int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); - if (res < 0) { - - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Unsupported attribute type %04X/%04X '0x%02X'"), attr.key.id.cluster, attr.key.id.attr_id, attr.attr_type); - return false; - } - return true; -} - - - - - -void ZbSendReportWrite(class JsonParserToken val_pubwrite, class ZigbeeZCLSendMessage & packet) { - SBuffer buf(200); - - if (nullptr == XdrvMailbox.command) { - XdrvMailbox.command = (char*) ""; - } - - - for (auto key : val_pubwrite.getObject()) { - JsonParserToken value = key.getValue(); - - Z_attribute attr; - attr.setKeyName(key.getStr()); - if (Z_parseAttributeKey(attr)) { - - - - if (0xFFFF == packet.cluster) { - packet.cluster = attr.key.id.cluster; - } else if (packet.cluster != attr.key.id.cluster) { - ResponseCmndChar_P(PSTR("No more than one cluster id per command")); - return; - } - - } else { - if (attr.key_is_str) { - Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute "), key); - return; - } - if (Zunk == attr.attr_type) { - Response_P(PSTR("{\"%s\":\"%s'%s'\"}"), XdrvMailbox.command, PSTR("Unknown attribute type for attribute "), key); - return; - } - } - - - if (value.isStr()) { - attr.setStr(value.getStr()); - } else if (value.isNum()) { - attr.setFloat(value.getFloat()); - } - - double val_d = 0; - const char* val_str = ""; - - - if (packet.cmd != ZCL_CONFIGURE_REPORTING) { - if ((packet.cluster == 0XEF00) && (packet.cmd == ZCL_WRITE_ATTRIBUTES)) { - - if (buf.len() > 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Only 1 attribute allowed for Tuya")); - return; - } - packet.clusterSpecific = true; - packet.cmd = 0x00; - if (!ZbTuyaWrite(buf, attr, zigbee_devices.getNextSeqNumber(packet.shortaddr))) { - return; - } - } else if (!ZbAppendWriteBuf(buf, attr, packet.cmd == ZCL_READ_ATTRIBUTES_RESPONSE)) { - return; - } - } else { - - - if (!value.isObject()) { - ResponseCmndChar_P(PSTR("Config requires JSON objects")); - return; - } - JsonParserObject attr_config = value.getObject(); - bool attr_direction = false; - - uint32_t dir = attr_config.getUInt(PSTR("DirectionReceived"), 0); - if (dir) { attr_direction = true; } - - - uint16_t attr_min_interval = attr_config.getUInt(PSTR("MinInterval"), 0xFFFF); - uint16_t attr_max_interval = attr_config.getUInt(PSTR("MaxInterval"), 0xFFFF); - - - JsonParserToken val_attr_rc = attr_config[PSTR("ReportableChange")]; - if (val_attr_rc) { - val_d = val_attr_rc.getFloat(); - val_str = val_attr_rc.getStr(); - ZbApplyMultiplier(val_d, attr.attr_multiplier); - } - - - uint16_t attr_timeout = attr_config.getUInt(PSTR("TimeoutPeriod"), 0x0000); - - bool attr_discrete = Z_isDiscreteDataType(attr.attr_type); - - - - buf.add8(attr_direction ? 0x01 : 0x00); - buf.add16(attr.key.id.attr_id); - if (attr_direction) { - buf.add16(attr_timeout); - } else { - buf.add8(attr.attr_type); - buf.add16(attr_min_interval); - buf.add16(attr_max_interval); - if (!attr_discrete) { - int32_t res = encodeSingleAttribute(buf, val_d, val_str, attr.attr_type); - if (res < 0) { - Response_P(PSTR("{\"%s\":\"%s'%s' 0x%02X\"}"), XdrvMailbox.command, PSTR("Unsupported attribute type "), key, attr.attr_type); - return; - } - } - } - } - } - - - if (0 == buf.len()) { - ResponseCmndChar_P(PSTR("No attribute in list")); - return; - } - - - packet.transacId = zigbee_devices.getNextSeqNumber(packet.shortaddr); - packet.msg = buf.getBuffer(); - packet.len = buf.len(); - ZigbeeZCLSend_Raw(packet); - ResponseCmndDone(); -} - - -void ZbSendSend(class JsonParserToken val_cmd, uint16_t device, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint16_t manuf) { - uint8_t cmd = 0; - String cmd_str = ""; - const char *cmd_s = ""; - bool clusterSpecific = true; - - static char delim[] = ", "; - - - - if (val_cmd.isObject()) { - - JsonParserObject cmd_obj = val_cmd.getObject(); - int32_t cmd_size = cmd_obj.size(); - if (cmd_size > 1) { - Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); - return; - } else if (1 == cmd_size) { - - JsonParserKey key = cmd_obj.getFirstElement(); - JsonParserToken value = key.getValue(); - uint32_t x = 0, y = 0, z = 0; - uint16_t cmd_var; - uint16_t local_cluster_id; - - const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.getStr(), &local_cluster_id, &cmd_var); - if (tasmota_cmd) { - cmd_str = tasmota_cmd; - } else { - Response_P(PSTR("Unrecognized zigbee command: %s"), key.getStr()); - return; - } - - if (0xFFFF == cluster) { - cluster = local_cluster_id; - } else if (cluster != local_cluster_id) { - ResponseCmndChar_P(PSTR("No more than one cluster id per command")); - return; - } - - - if (value.isNum()) { - x = value.getUInt(); - - - - - - } else { - - const char *s_const = value.getStr(nullptr); - - if (s_const != nullptr) { - char s[strlen(s_const)+1]; - strcpy(s, s_const); - if ((nullptr != s) && (0x00 != *s)) { - char *sval = strtok(s, delim); - if (sval) { - x = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - y = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - z = ZigbeeAliasOrNumber(sval); - } - } - } - } - } - } - - - if (0xFF == cmd_var) { - cmd = x; - x = y; - y = z; - } else { - cmd = cmd_var; - } - cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); - - cmd_s = cmd_str.c_str(); - } else { - - } - } else if (val_cmd.isStr()) { - - - - - - const char * data = val_cmd.getStr(); - uint16_t local_cluster_id = parseHex(&data, 4); - - - if (0xFFFF == cluster) { - cluster = local_cluster_id; - } else if (cluster != local_cluster_id) { - ResponseCmndChar_P(PSTR("No more than one cluster id per command")); - return; - } - - - if (('_' == *data) || ('!' == *data)) { - if ('_' == *data) { clusterSpecific = false; } - data++; - } else { - ResponseCmndChar_P(PSTR("Wrong delimiter for payload")); - return; - } - - cmd = parseHex(&data, 2); - - - - if ('/' == *data) { data++; } - - cmd_s = data; - } else { - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLSend device: 0x%04X, group: 0x%04X, endpoint:%d, cluster:0x%04X, cmd:0x%02X, send:\"%s\""), - device, groupaddr, endpoint, cluster, cmd, cmd_s); - zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, manuf, cluster, cmd, cmd_s); - ResponseCmndDone(); -} - - - -void ZbSendRead(JsonParserToken val_attr, ZigbeeZCLSendMessage & packet) { -# 546 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - size_t attrs_len = 0; - uint8_t* attrs = nullptr; - size_t attr_item_len = 2; - size_t attr_item_offset = 0; - if (ZCL_READ_REPORTING_CONFIGURATION == packet.cmd) { - attr_item_len = 3; - attr_item_offset = 1; - } - - if (val_attr.isArray()) { - - JsonParserArray attr_arr = val_attr.getArray(); - attrs_len = attr_arr.size() * attr_item_len; - attrs = (uint8_t*) calloc(attrs_len, 1); - - uint32_t i = 0; - for (auto value : attr_arr) { - uint16_t val = value.getUInt(); - i += attr_item_offset; - attrs[i++] = val & 0xFF; - attrs[i++] = val >> 8; - i += attr_item_len - 2 - attr_item_offset; - } - } else if (val_attr.isObject()) { - - JsonParserObject attr_obj = val_attr.getObject(); - attrs_len = attr_obj.size() * attr_item_len; - attrs = (uint8_t*) calloc(attrs_len, 1); - uint32_t actual_attr_len = 0; - - - for (auto key : attr_obj) { - JsonParserToken value = key.getValue(); - - bool found = false; - - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - bool match = false; - uint16_t local_attr_id = pgm_read_word(&converter->attribute); - uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); - - - if ((pgm_read_word(&converter->name_offset)) && (0 == strcasecmp_P(key.getStr(), Z_strings + pgm_read_word(&converter->name_offset)))) { - - - - if (!(value.getBool()) && attr_item_offset) { - - attrs[actual_attr_len] = 0x01; - } - actual_attr_len += attr_item_offset; - attrs[actual_attr_len++] = local_attr_id & 0xFF; - attrs[actual_attr_len++] = local_attr_id >> 8; - actual_attr_len += attr_item_len - 2 - attr_item_offset; - found = true; - - if (0xFFFF == packet.cluster) { - packet.cluster = local_cluster_id; - } else if (packet.cluster != local_cluster_id) { - ResponseCmndChar_P(PSTR("No more than one cluster id per command")); - if (attrs) { free(attrs); } - return; - } - break; - } - } - if (!found) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: Unknown attribute name (ignored): %s"), key); - } - } - - attrs_len = actual_attr_len; - } else { - - if (0xFFFF != packet.cluster) { - uint16_t val = val_attr.getUInt(); - attrs_len = attr_item_len; - attrs = (uint8_t*) calloc(attrs_len, 1); - attrs[0 + attr_item_offset] = val & 0xFF; - attrs[1 + attr_item_offset] = val >> 8; - } - } - - if (attrs_len > 0) { - - packet.transacId = zigbee_devices.getNextSeqNumber(packet.shortaddr); - packet.msg = attrs; - packet.len = attrs_len; - ZigbeeZCLSend_Raw(packet); - ResponseCmndDone(); - } else { - ResponseCmndChar_P(PSTR("Missing parameters")); - } - - if (attrs) { free(attrs); } -} -# 656 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" -void CmndZbSend(void) { -# 668 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - - - uint16_t device = BAD_SHORTADDR; - uint16_t groupaddr = 0x0000; - uint16_t cluster = 0xFFFF; - uint8_t endpoint = 0x00; - uint16_t manuf = 0x0000; - - - - JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)]; - if (val_device) { - device = zigbee_devices.parseDeviceParam(val_device.getStr()); - if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } - } - if (BAD_SHORTADDR == device) { - JsonParserToken val_group = root[PSTR(D_CMND_ZIGBEE_GROUP)]; - if (val_group) { - groupaddr = val_group.getUInt(); - } else { - ResponseCmndChar_P(PSTR("Unknown device")); - return; - } - } - - - - - cluster = root.getUInt(PSTR(D_CMND_ZIGBEE_CLUSTER), cluster); - endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), endpoint); - manuf = root.getUInt(PSTR(D_CMND_ZIGBEE_MANUF), manuf); - - - if (BAD_SHORTADDR == device) { - endpoint = 0xFF; - } else if (0 == endpoint) { - endpoint = zigbee_devices.findFirstEndpoint(device); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: guessing endpoint %d"), endpoint); - } - if (0 == endpoint) { - ResponseCmndChar_P(PSTR("Missing endpoint")); - return; - } - - - - JsonParserToken val_cmd = root[PSTR(D_CMND_ZIGBEE_SEND)]; - JsonParserToken val_read = root[PSTR(D_CMND_ZIGBEE_READ)]; - JsonParserToken val_write = root[PSTR(D_CMND_ZIGBEE_WRITE)]; - JsonParserToken val_publish = root[PSTR(D_CMND_ZIGBEE_REPORT)]; - JsonParserToken val_response = root[PSTR(D_CMND_ZIGBEE_RESPONSE)]; - JsonParserToken val_read_config = root[PSTR(D_CMND_ZIGBEE_READ_CONFIG)]; - JsonParserToken val_config = root[PSTR(D_CMND_ZIGBEE_CONFIG)]; - uint32_t multi_cmd = ((bool)val_cmd) + ((bool)val_read) + ((bool)val_write) + ((bool)val_publish) - + ((bool)val_response) + ((bool)val_read_config) + ((bool)val_config); - if (multi_cmd > 1) { - ResponseCmndChar_P(PSTR("Can only have one of: 'Send', 'Read', 'Write', 'Report', 'Reponse', 'ReadConfig' or 'Config'")); - return; - } - - - - ZigbeeZCLSendMessage packet({ - device, - groupaddr, - cluster , - endpoint, - ZCL_READ_ATTRIBUTES, - manuf, - false , - false , - false , - 0, - nullptr, 0 - }); - - if (val_cmd) { - - - ZbSendSend(val_cmd, device, groupaddr, cluster, endpoint, manuf); - } else if (val_read) { - - - packet.cmd = ZCL_READ_ATTRIBUTES; - ZbSendRead(val_read, packet); - } else if (val_write) { - - if (!val_write.isObject()) { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; - } - - packet.cmd = ZCL_WRITE_ATTRIBUTES; - ZbSendReportWrite(val_write, packet); - } else if (val_publish) { - - - if (!val_publish.isObject()) { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; - } - packet.cmd = ZCL_REPORT_ATTRIBUTES; - ZbSendReportWrite(val_publish, packet); - } else if (val_response) { - - - if (!val_response.isObject()) { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; - } - packet.cmd = ZCL_READ_ATTRIBUTES_RESPONSE; - ZbSendReportWrite(val_response, packet); - } else if (val_read_config) { - - - packet.cmd = ZCL_READ_REPORTING_CONFIGURATION; - ZbSendRead(val_read_config, packet); - } else if (val_config) { - - - if (!val_config.isObject()) { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; - } - packet.cmd = ZCL_CONFIGURE_REPORTING; - ZbSendReportWrite(val_config, packet); - } else { - Response_P(PSTR("Missing zigbee 'Send', 'Write', 'Report' or 'Response'")); - return; - } -} - - - - -void ZbBindUnbind(bool unbind) { - - - - - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - - - uint16_t srcDevice = BAD_SHORTADDR; - uint16_t dstDevice = BAD_SHORTADDR; - uint64_t dstLongAddr = 0; - uint8_t endpoint = 0x00; - uint8_t toendpoint = 0x01; - uint16_t toGroup = 0x0000; - uint16_t cluster = 0; - uint32_t group = 0xFFFFFFFF; - - - - srcDevice = zigbee_devices.parseDeviceParam(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr)); - if (BAD_SHORTADDR == srcDevice) { ResponseCmndChar_P(PSTR("Unknown source device")); return; } - - uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice); - if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; } - - endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), endpoint); - if (0 == endpoint) { endpoint = zigbee_devices.findFirstEndpoint(srcDevice); } - - JsonParserToken val_cluster = root[PSTR(D_CMND_ZIGBEE_CLUSTER)]; - if (val_cluster) { - cluster = val_cluster.getUInt(cluster); - if (0 == cluster) { - zigbeeFindAttributeByName(val_cluster.getStr(), &cluster, nullptr, nullptr); - } - } - - - JsonParserToken to_group = root[PSTR("ToGroup")]; - if (to_group) { toGroup = to_group.getUInt(toGroup); } - - - - - - JsonParserToken dst_device = root[PSTR("ToDevice")]; - - - if ((!to_group) && (!dst_device)) { - dstDevice = 0x0000; - } - - if ((dst_device) || (BAD_SHORTADDR != dstDevice)) { - if (BAD_SHORTADDR == dstDevice) { - dstDevice = zigbee_devices.parseDeviceParam(dst_device.getStr(nullptr)); - if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } - } - if (0x0000 == dstDevice) { - dstLongAddr = localIEEEAddr; - } else { - dstLongAddr = zigbee_devices.getDeviceLongAddr(dstDevice); - } - if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; } - - toendpoint = root.getUInt(PSTR("ToEndpoint"), toendpoint); - } - - - if (to_group && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; } - if (!to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; } - -#ifdef USE_ZIGBEE_ZNP - SBuffer buf(34); - buf.add8(Z_SREQ | Z_ZDO); - if (unbind) { - buf.add8(ZDO_UNBIND_REQ); - } else { - buf.add8(ZDO_BIND_REQ); - } - buf.add16(srcDevice); - buf.add64(srcLongAddr); - buf.add8(endpoint); - buf.add16(cluster); - if (dstLongAddr) { - buf.add8(Z_Addr_IEEEAddress); - buf.add64(dstLongAddr); - buf.add8(toendpoint); - } else { - buf.add8(Z_Addr_Group); - buf.add16(toGroup); - } - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -#endif - -#ifdef USE_ZIGBEE_EZSP - SBuffer buf(24); - - - buf.add64(srcLongAddr); - buf.add8(endpoint); - buf.add16(cluster); - if (dstLongAddr) { - buf.add8(Z_Addr_IEEEAddress); - buf.add64(dstLongAddr); - buf.add8(toendpoint); - } else { - buf.add8(Z_Addr_Group); - buf.add16(toGroup); - } - - EZ_SendZDO(srcDevice, unbind ? ZDO_UNBIND_REQ : ZDO_BIND_REQ, buf.buf(), buf.len()); -#endif - - ResponseCmndDone(); -} - - - - -void CmndZbBind(void) { - ZbBindUnbind(false); -} - - - - -void CmndZbUnbind(void) { - ZbBindUnbind(true); -} - - - - - -void CmndZbBindState(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - uint8_t index = XdrvMailbox.index - 1; - -#ifdef USE_ZIGBEE_ZNP - SBuffer buf(10); - buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_MGMT_BIND_REQ); - buf.add16(shortaddr); - buf.add8(index); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -#endif - - -#ifdef USE_ZIGBEE_EZSP - - uint8_t buf[] = { index }; - - EZ_SendZDO(shortaddr, ZDO_Mgmt_Bind_req, buf, sizeof(buf)); -#endif - - ResponseCmndDone(); -} - - -void CmndZbProbe(void) { - CmndZbProbeOrPing(true); -} - - - - -void CmndZbProbeOrPing(boolean probe) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - - - Z_SendIEEEAddrReq(shortaddr); - if (probe) { - Z_SendActiveEpReq(shortaddr); - } - ResponseCmndDone(); -} - - -void CmndZbPing(void) { - CmndZbProbeOrPing(false); -} - - - - - -void CmndZbName(void) { - - - - - - - - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - - if (p == nullptr) { - const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName : ""); - } else { - if (strlen(p) > 32) { p[32] = 0x00; } - zigbee_devices.setFriendlyName(shortaddr, p); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); - } -} - - - - - -void CmndZbModelId(void) { - - - - - - - - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - - if (p == nullptr) { - const char * modelId = zigbee_devices.getModelId(shortaddr); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, modelId ? modelId : ""); - } else { - zigbee_devices.setModelId(shortaddr, p); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, p); - } -} - - - - -void CmndZbLight(void) { - - - - - - - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - - if (p) { - int8_t bulbtype = strtol(p, nullptr, 10); - if (bulbtype > 5) { bulbtype = 5; } - if (bulbtype < -1) { bulbtype = -1; } - zigbee_devices.setLightProfile(shortaddr, bulbtype); - } - String dump = zigbee_devices.dumpLightState(shortaddr); - Response_P(PSTR("{\"" D_PRFX_ZB D_CMND_ZIGBEE_LIGHT "\":%s}"), dump.c_str()); - - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_ZB D_CMND_ZIGBEE_LIGHT)); - ResponseCmndDone(); -} - - - - - -void CmndZbForget(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - - - if (zigbee_devices.removeDevice(shortaddr)) { - ResponseCmndDone(); - } else { - ResponseCmndChar_P(PSTR("Unknown device")); - } -} - - - - - -void CmndZbSave(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - saveZigbeeDevices(); - ResponseCmndDone(); -} -# 1128 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" -void CmndZbRestore(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - JsonParser parser(XdrvMailbox.data); - JsonParserToken root = parser.getRoot(); - - if (!parser || !(root.isObject() || root.isArray())) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - - - JsonParserToken zbstatus = root.getObject().findStartsWith(PSTR("ZbStatus")); - if (zbstatus) { - root = zbstatus; - } - - - if (root.isArray()) { - JsonParserArray arr = JsonParserArray(root); - for (const auto elt : arr) { - - if (elt.isObject()) { - int32_t res = zigbee_devices.deviceRestore(JsonParserObject(elt)); - if (res < 0) { - ResponseCmndChar_P(PSTR("Restore failed")); - return; - } - } - } - } else if (root.isObject()) { - int32_t res = zigbee_devices.deviceRestore(JsonParserObject(root)); - if (res < 0) { - ResponseCmndChar_P(PSTR("Restore failed")); - return; - } - - } else { - ResponseCmndChar_P(PSTR("Missing parameters")); - return; - } - ResponseCmndDone(); -} - - - - - -void CmndZbPermitJoin(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - - uint32_t payload = XdrvMailbox.payload; - uint8_t duration = 60; - - if (payload <= 0) { - duration = 0; - } - - -#ifdef USE_ZIGBEE_ZNP - if (99 == payload) { - duration = 0xFF; - } - - uint16_t dstAddr = 0xFFFC; - - SBuffer buf(34); - buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); - buf.add8(0x0F); - buf.add16(0xFFFC); - buf.add8(duration); - buf.add8(0x00); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - -#endif - - -#ifdef USE_ZIGBEE_EZSP - if (99 == payload) { - ResponseCmndChar_P(PSTR("Unlimited time not supported")); return; - } - - SBuffer buf(3); - buf.add16(EZSP_permitJoining); - buf.add8(duration); - ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); - - - buf.setLen(0); - buf.add8(duration); - buf.add8(0x01); - EZ_SendZDO(0xFFFC, ZDO_Mgmt_Permit_Joining_req, buf.buf(), buf.len()); - - - if (duration > 0) { - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":21,\"Message\":\"Pairing mode enabled\"}}")); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - zigbee.permit_end_time = millis() + duration * 1000; - AddLog_P2(LOG_LEVEL_INFO, "zigbee.permit_end_time = %d", zigbee.permit_end_time); - } else { - zigbee.permit_end_time = millis(); - } -#endif - - ResponseCmndDone(); -} - -#ifdef USE_ZIGBEE_EZSP - - - - - -void CmndZbEZSPListen(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - - int32_t index = XdrvMailbox.index; - int32_t group = XdrvMailbox.payload; - - if (group <= 0) { - group = 0; - } else if (group > 0xFFFF) { - group = 0xFFFF; - } - - SBuffer buf(8); - buf.add16(EZSP_setMulticastTableEntry); - buf.add8(index); - buf.add16(group); - buf.add8(0x01); - buf.add8(0x00); - ZigbeeEZSPSendCmd(buf.getBuffer(), buf.len()); - - ResponseCmndDone(); -} - -void ZigbeeGlowPermitJoinLight(void) { - static const uint16_t cycle_time = 1000; - static const uint16_t half_cycle_time = cycle_time / 2; - if (zigbee.permit_end_time) { - uint16_t led_power = 0; - - if (TimeReached(zigbee.permit_end_time)) { - zigbee.permit_end_time = 0; - Z_PermitJoinDisable(); - } else { - uint32_t millis_to_go = millis() - zigbee.permit_end_time; - uint32_t sub_second = millis_to_go % cycle_time; - if (sub_second <= half_cycle_time) { - led_power = changeUIntScale(sub_second, 0, half_cycle_time, 0, 1023); - } else { - led_power = changeUIntScale(sub_second, half_cycle_time, cycle_time, 1023, 0); - } - led_power = ledGamma10_10(led_power); - } - - - uint32_t led_pin = Pin(GPIO_LEDLNK); - if (led_pin < 99) { - analogWrite(led_pin, ledlnk_inverted ? 1023 - led_power : led_power); - } - } -} -#endif - - - - -void CmndZbStatus(void) { - if (ZigbeeSerial) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (XdrvMailbox.data_len > 0) { - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - } - - String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); - Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); - } -} - - - - - -bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root) { - for (auto data_elt : root) { - - const char * data_type_str = data_elt.getStr(); - Z_Data_Type data_type; - - switch (data_type_str[0]) { - case 'P': data_type = Z_Data_Type::Z_Plug; break; - case 'L': data_type = Z_Data_Type::Z_Light; break; - case 'O': data_type = Z_Data_Type::Z_OnOff; break; - case 'T': data_type = Z_Data_Type::Z_Thermo; break; - case 'A': data_type = Z_Data_Type::Z_Alarm; break; - case '_': data_type = Z_Data_Type::Z_Device; break; - default: data_type = Z_Data_Type::Z_Unknown; break; - } - - if (data_type == Z_Data_Type::Z_Unknown) { - Response_P(PSTR("{\"%s\":\"%s \"%s\"\"}"), XdrvMailbox.command, PSTR("Invalid Parameters"), data_type_str); - return false; - } - - JsonParserObject data_values = data_elt.getValue().getObject(); - if (!data_values) { return false; } - - - uint8_t endpoint = strtoul(&data_type_str[1], nullptr, 16); - JsonParserToken val; - - - Z_Data & data = device.data.getByType(data_type, endpoint); - - - for (auto attr : data_values) { - JsonParserToken attr_value = attr.getValue(); - uint8_t conv_zigbee_type; - Z_Data_Type conv_data_type; - uint8_t conv_map_offset; - if (zigbeeFindAttributeByName(attr.getStr(), nullptr, nullptr, nullptr, &conv_zigbee_type, &conv_data_type, &conv_map_offset) != nullptr) { - - if (conv_data_type == data_type) { - - - uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + conv_map_offset; - uint32_t uval32 = attr_value.getUInt(); - int32_t ival32 = attr_value.getInt(); - switch (conv_zigbee_type) { - case Zenum8: - case Zuint8: *(uint8_t*)attr_address = uval32; break; - case Zenum16: - case Zuint16: *(uint16_t*)attr_address = uval32; break; - case Zuint32: *(uint32_t*)attr_address = uval32; break; - case Zint8: *(int8_t*)attr_address = ival32; break; - case Zint16: *(int16_t*)attr_address = ival32; break; - case Zint32: *(int32_t*)attr_address = ival32; break; - } - } else if (conv_data_type != Z_Data_Type::Z_Unknown) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "attribute %s is wrong type %d (expected %d)"), attr.getStr(), (uint8_t)data_type, (uint8_t)conv_data_type); - } - } - } - - - switch (data_type) { -# 1385 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - case Z_Data_Type::Z_OnOff: - { - Z_Data_OnOff & onoff = (Z_Data_OnOff&) data; - - if (val = data_values[PSTR("Power")]) { onoff.setPower(val.getUInt() ? true : false); } - } - break; -# 1402 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - case Z_Data_Type::Z_Device: - { - if (val = data_values[PSTR(D_CMND_ZIGBEE_LINKQUALITY)]) { device.lqi = val.getUInt(); } - if (val = data_values[PSTR("BatteryPercentage")]) { device.batterypercent = val.getUInt(); } - if (val = data_values[PSTR("LastSeen")]) { device.last_seen = val.getUInt(); } - } - break; - } - } - return true; -} - - - - -void CmndZbData(void) { - if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - RemoveSpace(XdrvMailbox.data); - if (XdrvMailbox.data[0] == '{') { - - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - - - JsonParserToken zbdata = root.getObject().findStartsWith(PSTR("ZbData")); - if (zbdata) { - root = zbdata; - } - - for (auto device_name : root) { - uint16_t shortaddr = zigbee_devices.parseDeviceParam(device_name.getStr()); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - Z_Device & device = zigbee_devices.getShortAddr(shortaddr); - JsonParserObject inner_data = device_name.getValue().getObject(); - if (inner_data) { - if (!parseDeviceInnerData(device, inner_data)) { - return; - } - } - } - ResponseCmndDone(); - } else { - - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } - const Z_Device & device = zigbee_devices.findShortAddr(shortaddr); - - Z_attribute_list attr_data; - - { - Z_attribute_list device_attr; - device.toAttributes(device_attr); - attr_data.addAttribute(F("_00")).setStrRaw(device_attr.toString(true).c_str()); - } - - - for (auto & data_elt : device.data) { - Z_attribute_list inner_attr; - char key[4]; - snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); -# 1473 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - Z_Data_Type data_type = data_elt.getType(); - switch (data_type) { - case Z_Data_Type::Z_Plug: - { - key[0] = 'P'; - ((Z_Data_Plug&)data_elt).toAttributes(inner_attr, data_type); - } - break; - case Z_Data_Type::Z_Light: - { - key[0] = 'L'; - ((Z_Data_Light&)data_elt).toAttributes(inner_attr, data_type); - } - break; - case Z_Data_Type::Z_OnOff: - { - key[0] = 'O'; - ((Z_Data_OnOff&)data_elt).toAttributes(inner_attr, data_type); - } - break; - case Z_Data_Type::Z_Thermo: - { - key[0] = 'T'; - ((Z_Data_Thermo&)data_elt).toAttributes(inner_attr, data_type); - } - break; - case Z_Data_Type::Z_Alarm: - { - key[0] = 'A'; - ((Z_Data_Alarm&)data_elt).toAttributes(inner_attr, data_type); - } - break; - } - if (key[0] != '?') { - attr_data.addAttribute(key).setStrRaw(inner_attr.toString(true).c_str()); - } - } - - char hex[8]; - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - Response_P(PSTR("{\"%s\":{\"%s\":%s}}"), XdrvMailbox.command, hex, attr_data.toString(true).c_str()); - } -} - - - - -void CmndZbConfig(void) { - - - uint8_t zb_channel = Settings.zb_channel; - uint16_t zb_pan_id = Settings.zb_pan_id; - uint64_t zb_ext_panid = Settings.zb_ext_panid; - uint64_t zb_precfgkey_l = Settings.zb_precfgkey_l; - uint64_t zb_precfgkey_h = Settings.zb_precfgkey_h; - int8_t zb_txradio_dbm = Settings.zb_txradio_dbm; - - - RemoveSpace(XdrvMailbox.data); - if (strlen(XdrvMailbox.data) > 0) { - JsonParser parser(XdrvMailbox.data); - JsonParserObject root = parser.getRootObject(); - if (!root) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } - - - zb_channel = root.getUInt(PSTR("Channel"), zb_channel); - zb_pan_id = root.getUInt(PSTR("PanID"), zb_pan_id); - zb_ext_panid = root.getULong(PSTR("ExtPanID"), zb_ext_panid); - zb_precfgkey_l = root.getULong(PSTR("KeyL"), zb_precfgkey_l); - zb_precfgkey_h = root.getULong(PSTR("KeyH"), zb_precfgkey_h); - zb_txradio_dbm = root.getInt(PSTR("TxRadio"), zb_txradio_dbm); - - if (zb_channel < 11) { zb_channel = 11; } - if (zb_channel > 26) { zb_channel = 26; } - - if ((0 == zb_precfgkey_l) && (0 == zb_precfgkey_h)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "generating random Zigbee network key")); - zb_precfgkey_l = (uint64_t)HwRandom() << 32 | HwRandom(); - zb_precfgkey_h = (uint64_t)HwRandom() << 32 | HwRandom(); - } - - - if ( (zb_channel != Settings.zb_channel) || - (zb_pan_id != Settings.zb_pan_id) || - (zb_ext_panid != Settings.zb_ext_panid) || - (zb_precfgkey_l != Settings.zb_precfgkey_l) || - (zb_precfgkey_h != Settings.zb_precfgkey_h) || - (zb_txradio_dbm != Settings.zb_txradio_dbm) ) { - Settings.zb_channel = zb_channel; - Settings.zb_pan_id = zb_pan_id; - Settings.zb_ext_panid = zb_ext_panid; - Settings.zb_precfgkey_l = zb_precfgkey_l; - Settings.zb_precfgkey_h = zb_precfgkey_h; - Settings.zb_txradio_dbm = zb_txradio_dbm; - restart_flag = 2; - } - } - - - char hex_ext_panid[20] = "0x"; - Uint64toHex(zb_ext_panid, &hex_ext_panid[2], 64); - char hex_precfgkey_l[20] = "0x"; - Uint64toHex(zb_precfgkey_l, &hex_precfgkey_l[2], 64); - char hex_precfgkey_h[20] = "0x"; - Uint64toHex(zb_precfgkey_h, &hex_precfgkey_h[2], 64); - - - Response_P(PSTR("{\"" D_PRFX_ZB D_JSON_ZIGBEE_CONFIG "\":{" - "\"Channel\":%d" - ",\"PanID\":\"0x%04X\"" - ",\"ExtPanID\":\"%s\"" - ",\"KeyL\":\"%s\"" - ",\"KeyH\":\"%s\"" - ",\"TxRadio\":%d" - "}}"), - zb_channel, zb_pan_id, - hex_ext_panid, - hex_precfgkey_l, hex_precfgkey_h, - zb_txradio_dbm); -} - - - - - -extern "C" { - int device_cmp(const void * a, const void * b) { - const Z_Device &dev_a = zigbee_devices.devicesAt(*(uint8_t*)a); - const Z_Device &dev_b = zigbee_devices.devicesAt(*(uint8_t*)b); - const char * fn_a = dev_a.friendlyName; - const char * fn_b = dev_b.friendlyName; - - if (fn_a && fn_b) { - return strcasecmp(fn_a, fn_b); - } else if (!fn_a && !fn_b) { - return (int32_t)dev_a.shortaddr - (int32_t)dev_b.shortaddr; - } else { - if (fn_a) return -1; - return 1; - } - } -# 1627 "/workspace/Tasmota/tasmota/xdrv_23_zigbee_A_impl.ino" - int convert_seconds_to_dhm(uint32_t n, char *result, size_t result_len){ - char fmtstr[] = "%02dmhd"; - uint32_t conversions[3] = {24 * 3600, 3600, 60}; - uint32_t value; - for(int i = 0; i < 3; ++i) { - value = n / conversions[i]; - if(value > 0) { - fmtstr[4] = fmtstr[6-i]; - break; - } - n = n % conversions[i]; - } - - - fmtstr[5] = '\0'; - return snprintf(result, result_len, fmtstr, value); - } -} -void ZigbeeShow(bool json) -{ - if (json) { - return; -#ifdef USE_WEBSERVER - } else { - uint32_t zigbee_num = zigbee_devices.devicesSize(); - if (!zigbee_num) { return; } - if (zigbee_num > 255) { zigbee_num = 255; } - - WSContentSend_P(PSTR("{t}")); - WSContentSend_P(PSTR( - "" - )); - - - uint8_t sorted_idx[zigbee_num]; - for (uint32_t i = 0; i < zigbee_num; i++) { - sorted_idx[i] = i; - } - qsort(sorted_idx, zigbee_num, sizeof(sorted_idx[0]), device_cmp); - - uint32_t now = Rtc.utc_time; - - for (uint32_t i = 0; i < zigbee_num; i++) { - const Z_Device &device = zigbee_devices.devicesAt(sorted_idx[i]); - uint16_t shortaddr = device.shortaddr; - char *name = (char*) device.friendlyName; - - char sdevice[33]; - if (nullptr == name) { - snprintf_P(sdevice, sizeof(sdevice), PSTR(D_DEVICE " 0x%04X"), shortaddr); - name = sdevice; - } - - char sbatt[64]; - snprintf_P(sbatt, sizeof(sbatt), PSTR(" ")); - if (device.validBatteryPercent()) { - snprintf_P(sbatt, sizeof(sbatt), - PSTR(""), - device.batterypercent, changeUIntScale(device.batterypercent, 0, 100, 0, 14) - ); - } - - uint32_t num_bars = 0; - - char slqi[4]; - slqi[0] = '-'; - slqi[1] = '\0'; - if (device.validLqi()){ - num_bars = changeUIntScale(device.lqi, 0, 254, 0, 4); - snprintf_P(slqi, sizeof(slqi), PSTR("%d"), device.lqi); - } - - WSContentSend_PD(PSTR( - "" - "%s" - "%s" - "
" - ), name, sbatt, slqi); - - if(device.validLqi()) { - for(uint32_t j = 0; j < 4; ++j) { - WSContentSend_PD(PSTR(""), j, (num_bars < j) ? PSTR(" o30") : PSTR("")); - } - } - char dhm[16]; - snprintf_P(dhm, sizeof(dhm), PSTR(" ")); - if(device.validLastSeen()){ - snprintf_P(dhm, sizeof(dhm), PSTR("🕗")); - convert_seconds_to_dhm(now - device.last_seen, &dhm[9], 7); - } - - WSContentSend_PD(PSTR( - "
" - "%s{e}" - ), dhm ); - - - const Z_Data_Thermo & thermo = device.data.find(); - - if (&thermo != nullptr) { - WSContentSend_P(PSTR("┆")); - if (thermo.validTemperature()) { - char buf[12]; - dtostrf(thermo.getTemperature() / 100.0f, 3, 1, buf); - WSContentSend_PD(PSTR(" ☀️ %s°C"), buf); - } - if (thermo.validTempTarget()) { - char buf[12]; - dtostrf(thermo.getTempTarget() / 100.0f, 3, 1, buf); - WSContentSend_PD(PSTR(" 🎯 %s°C"), buf); - } - if (thermo.validThSetpoint()) { - WSContentSend_PD(PSTR(" ⚙️ %d%%"), thermo.getThSetpoint()); - } - if (thermo.validHumidity()) { - WSContentSend_P(PSTR(" 💧 %d%%"), (uint16_t)(thermo.getHumidity() / 100.0f + 0.5f)); - } - if (thermo.validPressure()) { - WSContentSend_P(PSTR(" ⛅ %d hPa"), thermo.getPressure()); - } - - WSContentSend_P(PSTR("{e}")); - } - - - const Z_Data_OnOff & onoff = device.data.find(); - const Z_Data_Light & light = device.data.find(); - bool light_display = (&light != nullptr) ? light.validDimmer() : false; - const Z_Data_Plug & plug = device.data.find(); - if ((&onoff != nullptr) || light_display || (&plug != nullptr)) { - int8_t channels = device.getLightChannels(); - if (channels < 0) { channels = 5; } - WSContentSend_P(PSTR("┆")); - if (&onoff != nullptr) { - WSContentSend_P(PSTR(" %s"), device.getPower() ? PSTR(D_ON) : PSTR(D_OFF)); - } - if (&light != nullptr) { - if (light.validDimmer() && (channels >= 1)) { - WSContentSend_P(PSTR(" 🔅 %d%%"), changeUIntScale(light.getDimmer(),0,254,0,100)); - } - if (light.validCT() && ((channels == 2) || (channels == 5))) { - uint32_t ct_k = (((1000000 / light.getCT()) + 25) / 50) * 50; - WSContentSend_P(PSTR(" %dK"), light.getCT(), ct_k); - } - if (light.validHue() && light.validSat() && (channels >= 3)) { - uint8_t r,g,b; - uint8_t sat = changeUIntScale(light.getSat(), 0, 254, 0, 255); - LightStateClass::HsToRgb(light.getHue(), sat, &r, &g, &b); - WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b); - } else if (light.validX() && light.validY() && (channels >= 3)) { - uint8_t r,g,b; - LightStateClass::XyToRgb(light.getX() / 65535.0f, light.getY() / 65535.0f, &r, &g, &b); - WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b); - } - } - if (&plug != nullptr) { - WSContentSend_P(PSTR(" ⚡ ")); - if (plug.validMainsVoltage()) { - WSContentSend_P(PSTR(" %dV"), plug.getMainsVoltage()); - } - if (plug.validMainsPower()) { - WSContentSend_P(PSTR(" %dW"), plug.getMainsPower()); - } - } - WSContentSend_P(PSTR("{e}")); - } - } - - WSContentSend_P(PSTR("{t}")); -#endif - } -} - - - - - -bool Xdrv23(uint8_t function) -{ - bool result = false; - - if (zigbee.active) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (!zigbee.init_phase) { - zigbee_devices.runTimer(); - } - break; - case FUNC_LOOP: -#ifdef USE_ZIGBEE_EZSP - if (ZigbeeUploadXmodem()) { - return false; - } -#endif - if (ZigbeeSerial) { - ZigbeeInputLoop(); - ZigbeeOutputLoop(); -#ifdef USE_ZIGBEE_EZSP - ZigbeeGlowPermitJoinLight(); -#endif - } - if (zigbee.state_machine) { - ZigbeeStateMachine_Run(); - } - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ZigbeeShow(false); - break; -#ifdef USE_ZIGBEE_EZSP - - case FUNC_WEB_ADD_HANDLER: - WebServer_on(PSTR("/" WEB_HANDLE_ZIGBEE_XFER), HandleZigbeeXfer); - break; -#endif -#endif - case FUNC_PRE_INIT: - ZigbeeInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kZbCommands, ZigbeeCommand); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" -#ifdef USE_BUZZER - - - - -#define XDRV_24 24 - -struct BUZZER { - uint32_t tune = 0; - uint32_t tune_reload = 0; - bool active = true; - bool enable = false; - uint8_t inverted = 0; - uint8_t count = 0; - uint8_t mode = 0; - uint8_t freq_mode = 0; - uint8_t set[2]; - uint8_t duration; - uint8_t state = 0; -} Buzzer; - - - -void BuzzerSet(uint8_t state) -{ - if (Buzzer.inverted) { - state = !state; - } - - if (Buzzer.freq_mode == 1) { - static uint8_t last_state = 0; - if (last_state != state) { - if (state) { - analogWrite(Pin(GPIO_BUZZER, 0), Settings.pwm_range / 2); - } - else { - analogWrite(Pin(GPIO_BUZZER, 0), 0); - } - last_state = state; - } - } - else { - DigitalWrite(GPIO_BUZZER, 0, state); - } - -} - - -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) -{ - Buzzer.set[0] = off; - Buzzer.set[1] = on; - Buzzer.duration = 1; - Buzzer.tune_reload = 0; - Buzzer.mode = mode; - - 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_reload <<= 1; - Buzzer.tune_reload |= tune1 & 1; - tune1 >>= 1; - } - } - Buzzer.tune = Buzzer.tune_reload; - } - Buzzer.count = count * 2; - - - if (Settings.flag4.buzzer_freq_mode) { - Buzzer.freq_mode = 1; - } - else { - Buzzer.freq_mode = 0; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X),%d"), count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.freq_mode); - - Buzzer.enable = (Buzzer.count > 0); - if (Buzzer.enable) { - if (Settings.sleep > PWM_MAX_SLEEP) { - ssleep = PWM_MAX_SLEEP; - } else { - ssleep = Settings.sleep; - } - } - else { - ssleep = Settings.sleep; - BuzzerSet(0); - } -} - -void BuzzerSetStateToLed(uint32_t state) -{ - if (Buzzer.enable && (2 == Buzzer.mode)) { - Buzzer.state = (state != 0); - BuzzerSet(Buzzer.state); - } -} - -void BuzzerBeep(uint32_t count) -{ - BuzzerBeep(count, 1, 1, 0, 0); -} - -void BuzzerEnabledBeep(uint32_t count, uint32_t duration) -{ - if (Settings.flag3.buzzer_enable) { - BuzzerBeep(count, duration, 1, 0, 0); - } -} - - - -bool BuzzerPinState(void) -{ - if (XdrvMailbox.index == AGPIO(GPIO_BUZZER_INV)) { - Buzzer.inverted = 1; - XdrvMailbox.index -= (AGPIO(GPIO_BUZZER_INV) - AGPIO(GPIO_BUZZER)); - return true; - } - return false; -} - -void BuzzerInit(void) -{ - if (PinUsed(GPIO_BUZZER)) { - pinMode(Pin(GPIO_BUZZER), OUTPUT); - BuzzerSet(0); - } else { - Buzzer.active = false; - } -} - -void BuzzerEvery100mSec(void) -{ - if (Buzzer.enable && (Buzzer.mode != 2)) { - if (Buzzer.count) { - if (Buzzer.duration) { - Buzzer.duration--; - if (!Buzzer.duration) { - if (Buzzer.tune) { - Buzzer.state = Buzzer.tune & 1; - Buzzer.tune >>= 1; - } else { - Buzzer.tune = Buzzer.tune_reload; - Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; - Buzzer.state = Buzzer.count & 1; - if (Buzzer.mode) { - Buzzer.count |= 2; - } - } - Buzzer.duration = Buzzer.set[Buzzer.state]; - } - } - BuzzerSet(Buzzer.state); - } else { - Buzzer.enable = false; - } - } -} - - - - - -const char kBuzzerCommands[] PROGMEM = "|" - "Buzzer" ; - -void (* const BuzzerCommand[])(void) PROGMEM = { - &CmndBuzzer }; - -void CmndBuzzer(void) -{ -# 210 "/workspace/Tasmota/tasmota/xdrv_24_buzzer.ino" - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload != 0) { - uint32_t parm[4] = { 0 }; - uint32_t mode = 0; - ParseParameters(4, parm); - if (XdrvMailbox.payload <= 0) { - parm[0] = 1; - mode = -XdrvMailbox.payload; - } - for (uint32_t i = 1; i < 3; i++) { - if (parm[i] < 1) { parm[i] = 1; } - } - BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); - } else { - BuzzerBeep(0); - } - } 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 "/workspace/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -# 21 "/workspace/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -#ifdef USE_A4988_STEPPER - - - - -#define XDRV_25 25 - -#include - -short A4988_dir_pin = 0; -short A4988_stp_pin = 0; -short A4988_ms1_pin = 0; -short A4988_ms2_pin = 0; -short A4988_ms3_pin = 0; -short A4988_ena_pin = 0; -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_MS1, 1); - A4988_ms3_pin = Pin(GPIO_A4988_MS1, 2); - 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 (PinUsed(GPIO_A4988_MS1) && PinUsed(GPIO_A4988_MS1, 1) && PinUsed(GPIO_A4988_MS1, 2) && (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 (PinUsed(GPIO_A4988_DIR) && PinUsed(GPIO_A4988_STP)) { - switch (function) { - case FUNC_INIT: - A4988Init(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kA4988Commands, A4988Command); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -#ifdef USE_LIGHT -#ifdef USE_ARILUX_RF - - - - -#define XDRV_26 26 - -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 { - 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 USE_WS2812_DMA -void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; -#endif - -void AriluxRfInterrupt(void) -{ - unsigned long time = micros(); - 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 int delay = Arilux.rf_timings[0] / 31; - const 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 (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) { - 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 (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) { - detachInterrupt(Pin(GPIO_ARIRFRCV)); - digitalWrite(Pin(GPIO_ARIRFSEL), 1); - } -} - - - - - -bool Xdrv26(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (PinUsed(GPIO_ARIRFRCV)) { AriluxRfHandler(); } - break; - case FUNC_EVERY_SECOND: - if (10 == uptime) { AriluxRfInit(); } - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" -#ifdef USE_SHUTTER - - - - -#define XDRV_27 27 -#ifndef SHUTTER_STEPPER - #define SHUTTER_STEPPER -#endif - -#define D_SHUTTER "SHUTTER" - -const uint16_t MOTOR_STOP_TIME = 500; -const uint16_t RESOLUTION = 1000; -const uint8_t STEPS_PER_SECOND = 20; -const uint16_t pwm_max = 500; -const uint16_t pwm_min = 90; - -uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; -uint16_t messwerte[5] = {30,50,70,90,100}; - -int32_t velocity_max = 0; -int32_t velocity_change_per_step_max = 0; -int32_t min_runtime_ms = 0; -int32_t current_stop_way = 0; -int32_t next_possible_stop_position = 0; -int32_t toBeAcc = 0; - - -const uint8_t MAX_MODES = 7; -enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; -enum Shutterswitch_mode {SHT_SWITCH, SHT_PULSE,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_EXT_HOLD, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; - -const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" - D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_TOGGLE "|" D_CMND_SHUTTER_TOGGLEDIR "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" - D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_MODE "|" D_CMND_SHUTTER_PWMRANGE "|" - D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" - D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|" - D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC; - -void (* const ShutterCommand[])(void) PROGMEM = { - &CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition, - &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterMode, &CmndShutterPwmRange, - &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, - &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons, - &CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec}; - - const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; - const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; - -#include - -Ticker TickerShutter; - -struct SHUTTER { - uint32_t time; - int32_t open_max; - int32_t target_position; - int32_t start_position; - int32_t real_position; - uint16_t open_time; - uint16_t close_time; - uint16_t close_velocity; - int8_t direction; - int8_t lastdirection; - uint8_t switch_mode; - int16_t motordelay; - int16_t pwm_velocity; - uint16_t pwm_value; - uint16_t close_velocity_max; - int32_t accelerator; -} Shutter[MAX_SHUTTERS]; - -struct SHUTTERGLOBAL { - power_t RelayShutterMask = 0; - power_t RelayOldMask = 0; - power_t RelayCurrentMask = 0; - uint8_t position_mode = 0; - uint8_t skip_relay_change; - uint8_t start_reported = 0; - uint16_t open_velocity_max = 1000; -} ShutterGlobal; - -#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) - -void ShutterLogPos(uint32_t i) -{ - char stemp2[10]; - dtostrfd((float)Shutter[i].time / STEPS_PER_SECOND, 2, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), - i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value); -} - -void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source) -{ - - if (device <= devices_present) ExecuteCommandPower(device,state,source); -} - -void ShutterUpdateVelocity(uint8_t i) -{ - - - Shutter[i].pwm_velocity += Shutter[i].accelerator; - Shutter[i].pwm_velocity = tmax(0,tmin(Shutter[i].direction==1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max,Shutter[i].pwm_velocity)); -} - -void ShutterRtc50mS(void) -{ - - for (uint8_t i = 0; i < shutters_present; i++) { - if (Shutter[i].direction) { - - Shutter[i].real_position = ShutterCalculatePosition(i); - Shutter[i].time++; - ShutterCalculateAccelerator(i); - switch (ShutterGlobal.position_mode) { - case SHT_PWM_VALUE: - ShutterUpdateVelocity(i); - Shutter[i].real_position += Shutter[i].direction > 0 ? Shutter[i].pwm_velocity : (Shutter[i].direction < 0 ? -Shutter[i].pwm_velocity : 0); - Shutter[i].pwm_value = SHT_DIV_ROUND((Settings.shutter_pwmrange[1][i]-Settings.shutter_pwmrange[0][i]) * Shutter[i].real_position , Shutter[i].open_max)+Settings.shutter_pwmrange[0][i]; - analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); - break; - - case SHT_COUNTER: - if (Shutter[i].accelerator) { - - ShutterUpdateVelocity(i); - analogWriteFreq(Shutter[i].pwm_velocity); - analogWrite(Pin(GPIO_PWM1, i), 50); - } - break; - } - } - } -} - -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) -{ - if (Settings.shutter_set50percent[index] != 50) { - return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent*10 : (Settings.shuttercoeff[1][index] * percent + (Settings.shuttercoeff[0][index]*10))*10; - } else { - uint32_t realpos; - - for (uint32_t j = 0; j < 5; j++) { - if (0 == Settings.shuttercoeff[j][index]) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); - for (uint32_t k = 0; k < 5; k++) { - Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); - } - } - } - for (uint32_t k = 0; k < 5; k++) { - if ((percent * 10) >= Settings.shuttercoeff[k][index]) { - realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100); - - } else { - if (0 == k) { - realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]), 10); - } else { - - - realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index]), 100); - } - break; - } - } - return realpos; - } -} - -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) -{ - if (Settings.shutter_set50percent[index] != 50) { - return (Settings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings.shuttercoeff[0][index]*10, Settings.shuttercoeff[1][index]); - } else { - uint16_t realpercent; - - for (uint32_t j = 0; j < 5; j++) { - if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) { - realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10); - - } else { - if (0 == j) { - realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * Settings.shuttercoeff[j][index], calibrate_pos[j+1]), Shutter[index].open_max); - } else { - - - - realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])), Shutter[index].open_max) ; - } - break; - } - } - return (int16_t)realpercent < 0 ? 0 : realpercent; - } -} - -void ShutterInit(void) -{ - shutters_present = 0; - ShutterGlobal.RelayShutterMask = 0; - - ShutterGlobal.RelayOldMask = power; - - - - if (Settings.shutter_startrelay[MAX_SHUTTERS -1] == 0) { - ShutterGlobal.open_velocity_max = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : ShutterGlobal.open_velocity_max; - } - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - - 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++; - - - ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1) ; - - - switch (Settings.pulse_timer[i]) { - case 0: - Shutter[i].switch_mode = SHT_SWITCH; - break; - default: - Shutter[i].switch_mode = SHT_PULSE; - break; - } - - if (Settings.shutter_mode == SHT_UNDEF) { - bool relay_in_interlock = false; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: mode undef.. calculate...")); - - for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { - - if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) { - - relay_in_interlock = true; - } - } - - if (relay_in_interlock) { - ShutterGlobal.position_mode = SHT_TIME; - } else { - ShutterGlobal.position_mode = SHT_TIME_UP_DOWN; - if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) { - ShutterGlobal.position_mode = SHT_COUNTER; - } - } - - } else { - ShutterGlobal.position_mode = Settings.shutter_mode; - } - - - TickerShutter.attach_ms(50, ShutterRtc50mS ); - - - Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; - - - Shutter[i].open_time = Settings.shutter_opentime[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; - Shutter[i].close_time = Settings.shutter_closetime[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; - - - Shutter[i].open_max = STEPS_PER_SECOND * RESOLUTION * Shutter[i].open_time / 10; - Shutter[i].close_velocity = Shutter[i].open_max / Shutter[i].close_time / 2 ; - - - if (Settings.shutter_set50percent[i] != 50) { - Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ; - Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10); - Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5; - - } - ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1); - - Shutter[i].real_position = ShutterPercentToRealPosition(Settings.shutter_position[i], i); - - Shutter[i].start_position = Shutter[i].target_position = Shutter[i].real_position; - Shutter[i].motordelay = Settings.shutter_motordelay[i]; - Shutter[i].lastdirection = (50 < Settings.shutter_position[i]) ? 1 : -1; - - switch (ShutterGlobal.position_mode) { - case SHT_PWM_VALUE: - ShutterGlobal.open_velocity_max = RESOLUTION; - - Settings.shutter_pwmrange[0][i] = Settings.shutter_pwmrange[0][i] > 0 ? Settings.shutter_pwmrange[0][i] : pwm_min; - Settings.shutter_pwmrange[1][i] = Settings.shutter_pwmrange[1][i] > 0 ? Settings.shutter_pwmrange[1][i] : pwm_max; - break; - } - Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init. Pos: %d,inverted %d, locked %d, end stop time enabled %d, webButtons inverted %d"), - i+1, Shutter[i].real_position, - (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, (Settings.shutter_options[i]&8) ? 1 : 0); - - } else { - - break; - } - ShutterLimitRealAndTargetPositions(i); - Settings.shutter_accuracy = 1; - } -} - -void ShutterReportPosition(bool always, uint32_t index) -{ - Response_P(PSTR("{")); - rules_flag.shutter_moving = 0; - uint32_t i = 0; - uint32_t n = shutters_present; - if( index != MAX_SHUTTERS) { - i = index; - n = index+1; - } - for (i; i < n; i++) { - - uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); - if (Shutter[i].direction != 0) { - rules_flag.shutter_moving = 1; - ShutterLogPos(i); - } - if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } - uint32_t target = ShutterRealToPercentPosition(Shutter[i].target_position, i); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings.shutter_options[i] & 1) ? 100-target : target ); - } - ResponseJsonEnd(); - if (always || (rules_flag.shutter_moving)) { - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); - } - -} - -void ShutterLimitRealAndTargetPositions(uint32_t i) { - if (Shutter[i].real_position<0) Shutter[i].real_position = 0; - if (Shutter[i].real_position>Shutter[i].open_max) Shutter[i].real_position = Shutter[i].open_max; - if (Shutter[i].target_position<0) Shutter[i].target_position = 0; - if (Shutter[i].target_position>Shutter[i].open_max) Shutter[i].target_position = Shutter[i].open_max; -} - -void ShutterCalculateAccelerator(uint8_t i) -{ - - if (Shutter[i].direction != 0) { - switch (ShutterGlobal.position_mode) { - case SHT_COUNTER: - case SHT_PWM_VALUE: - - velocity_max = Shutter[i].direction == 1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max; - - velocity_change_per_step_max = velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); - - min_runtime_ms = Shutter[i].pwm_velocity * 1000 / STEPS_PER_SECOND / velocity_change_per_step_max; - - current_stop_way = (min_runtime_ms * (Shutter[i].pwm_velocity+velocity_change_per_step_max)/100 - Shutter[i].pwm_velocity)*RESOLUTION/ShutterGlobal.open_velocity_max * Shutter[i].direction ; - next_possible_stop_position = Shutter[i].real_position + current_stop_way ; - toBeAcc = 0; - - if (Shutter[i].accelerator < 0 || (next_possible_stop_position * Shutter[i].direction) +RESOLUTION*Shutter[i].pwm_velocity/ShutterGlobal.open_velocity_max>= Shutter[i].target_position * Shutter[i].direction ) { - - toBeAcc = 100+(Shutter[i].direction*(next_possible_stop_position-Shutter[i].target_position)*velocity_max/Shutter[i].pwm_velocity*10/RESOLUTION); - Shutter[i].accelerator = - tmin(tmax( velocity_change_per_step_max*toBeAcc/100 , (velocity_change_per_step_max*9/10)), (velocity_change_per_step_max*11/10)); - } else if ( Shutter[i].accelerator > 0 && Shutter[i].pwm_velocity == velocity_max) { - Shutter[i].accelerator = 0; - } - break; - } - } -} - -void ShutterDecellerateForStop(uint8_t i) -{ - switch (ShutterGlobal.position_mode) { - case SHT_PWM_VALUE: - case SHT_COUNTER: - int16_t missing_steps; - Shutter[i].accelerator = -(ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>4 ? (Shutter[i].motordelay*11)/10 : 4) ); - while (Shutter[i].pwm_velocity > -2*Shutter[i].accelerator ) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: velocity: %ld, delta: %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator ); - - - delay(50); - } - if (ShutterGlobal.position_mode == SHT_COUNTER){ - missing_steps = ((Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i]; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter[i].pwm_velocity); - Shutter[i].accelerator = 0; - Shutter[i].pwm_velocity = Shutter[i].pwm_velocity > 250 ? 250 : Shutter[i].pwm_velocity; - analogWriteFreq(Shutter[i].pwm_velocity); - analogWrite(Pin(GPIO_PWM1, i), 50); - Shutter[i].pwm_velocity = 0; - analogWriteFreq(Shutter[i].pwm_velocity); - while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) { - delay(1); - } - analogWrite(Pin(GPIO_PWM1, i), 0); - Shutter[i].real_position = ShutterCalculatePosition(i); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Real %d, pulsecount %d, start %d"), Shutter[i].real_position,RtcSettings.pulse_counter[i], Shutter[i].start_position); - - } - Shutter[i].direction = 0; - Shutter[i].pwm_velocity = 0; - break; - } -} - -void ShutterPowerOff(uint8_t i) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i,Shutter[i].switch_mode); - ShutterDecellerateForStop(i); - if (Shutter[i].direction !=0) { - Shutter[i].direction = 0; - delay(MOTOR_STOP_TIME); - } - switch (Shutter[i].switch_mode) { - case SHT_SWITCH: - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { - ExecuteCommandPowerShutter(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - } - if ((1 << (Settings.shutter_startrelay[i])) & power) { - ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - break; - case SHT_PULSE: - uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ; - - if ((SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source)) { - ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER); - - if ((1 << (Settings.shutter_startrelay[i])) & power) { - ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - } else { - last_source = SRC_SHUTTER; - } - break; - } - - switch (ShutterGlobal.position_mode) { - case SHT_PWM_VALUE: - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM " %d" ),Shutter[i].pwm_value); - ExecuteCommand(scmnd, SRC_BUTTON); - break; - } -} - -void ShutterUpdatePosition(void) -{ - - char scommand[CMDSZ]; - char stopic[TOPSZ]; - for (uint32_t i = 0; i < shutters_present; i++) { - if (Shutter[i].direction != 0) { - if (!ShutterGlobal.start_reported) { - ShutterReportPosition(true, i); - XdrvRulesProcess(); - ShutterGlobal.start_reported = 1; - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, toBeAcc %d, current_stop_way %d,vel_cur %d, vel_max %d, act_vel_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d, max_vel_change %d, dir: %d"),Shutter[i].time,toBeAcc,current_stop_way, - Shutter[i].pwm_velocity,velocity_max, Shutter[i].accelerator,min_runtime_ms,Shutter[i].real_position, next_possible_stop_position,Shutter[i].target_position,velocity_change_per_step_max,Shutter[i].direction); - - - if ( Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction || Shutter[i].pwm_velocity=<%s>, max10s?"),i+i, rules_vars[i]); - rules_flag.shutter_moving = 1; - XdrvRulesProcess(); - uptime_Local = uptime; - while (uptime_Local+10 > uptime && (String)rules_vars[i] == "99") { - loop(); - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. Done")); -#endif -} - -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) -{ - - if ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) / 100 <= 2) ) - || ( (-1 == direction) && (Shutter[i].real_position / Shutter[i].close_velocity <= 2)) ) { - ShutterGlobal.skip_relay_change = 1; - } else { - Shutter[i].pwm_velocity = 0; - switch (ShutterGlobal.position_mode) { -#ifdef SHUTTER_STEPPER - case SHT_COUNTER: - analogWriteFreq(Shutter[i].pwm_velocity); - analogWrite(Pin(GPIO_PWM1, i), 0); - RtcSettings.pulse_counter[i] = 0; - break; -#endif - } - Shutter[i].accelerator = ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); - Shutter[i].target_position = target_pos; - Shutter[i].start_position = Shutter[i].real_position; - rules_flag.shutter_moving = 1; - ShutterAllowPreStartProcedure(i); - Shutter[i].time = 0; - Shutter[i].direction = direction; - ShutterGlobal.skip_relay_change = 0; - rules_flag.shutter_moved = 0; - ShutterGlobal.start_reported = 0; - - } - -} - -int32_t ShutterCalculatePosition(uint32_t i) -{ - - if (Shutter[i].direction != 0) { - switch (ShutterGlobal.position_mode) { - case SHT_COUNTER: - return ((int32_t)RtcSettings.pulse_counter[i]*Shutter[i].direction*STEPS_PER_SECOND / ShutterGlobal.open_velocity_max * RESOLUTION)+Shutter[i].start_position; - break; - case SHT_TIME: - case SHT_TIME_UP_DOWN: - case SHT_TIME_GARAGE: - return Shutter[i].start_position + ( (Shutter[i].time - Shutter[i].motordelay) * (Shutter[i].direction > 0 ? RESOLUTION : -Shutter[i].close_velocity)); - break; - case SHT_PWM_TIME: - break; - case SHT_PWM_VALUE: - return Shutter[i].real_position; - break; - default: - break; - } - } else { - return Shutter[i].real_position; - } -} - -void ShutterRelayChanged(void) -{ - - - - - char stemp1[10]; - - for (uint32_t i = 0; i < shutters_present; i++) { - power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; - - - uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); - if (manual_relays_changed) { - - ShutterLimitRealAndTargetPositions(i); - switch (Shutter[i].switch_mode ) { - case SHT_PULSE: - if (Shutter[i].direction != 0 && powerstate_local) { - Shutter[i].target_position = Shutter[i].real_position; - powerstate_local = 0; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); - } - break; - default: - last_source = SRC_SHUTTER; - if (Shutter[i].direction != 0 ) ShutterPowerOff(i); - } - switch (ShutterGlobal.position_mode) { - - case SHT_TIME_UP_DOWN: - case SHT_COUNTER: - case SHT_PWM_VALUE: - case SHT_PWM_TIME: - ShutterPowerOff(i); - switch (powerstate_local) { - case 1: - ShutterStartInit(i, 1, Shutter[i].open_max); - break; - case 3: - ShutterStartInit(i, -1, 0); - break; - default: - - Shutter[i].target_position = Shutter[i].real_position; - } - break; - case SHT_TIME: - switch (powerstate_local) { - case 1: - ShutterStartInit(i, 1, Shutter[i].open_max); - break; - case 2: - ShutterStartInit(i, -1, 0); - break; - default: - - Shutter[i].target_position = Shutter[i].real_position; - } - break; - case SHT_TIME_GARAGE: - switch (powerstate_local) { - case 1: - ShutterStartInit(i, Shutter[i].lastdirection*-1 , Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Garage. NewTarget %d"), i, Shutter[i].target_position); - break; - default: - Shutter[i].target_position = Shutter[i].real_position; - } - - - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); - } - } -} - -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { - - uint32 min_shutterbutton_hold_timer = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) - min_shutterbutton_hold_timer = Button.hold_timer[i]; - } - return ((-1 != min_shutterbutton_hold_timer) && (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1))); -} - -void ShutterButtonHandler(void) -{ - uint8_t buttonState = SHT_NOT_PRESSED; - uint8_t button = XdrvMailbox.payload; - uint8_t press_index; - uint32_t button_index = XdrvMailbox.index; - uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; - uint16_t loops_per_second = 1000 / Settings.button_debounce; - - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - buttonState = SHT_PRESSED_MULTI; - press_index = 1; - } else { - if ((Shutter[shutter_index].direction) && (Button.press_counter[button_index]==0)) { - buttonState = SHT_PRESSED_IMMEDIATE; - press_index = 1; - Button.press_counter[button_index] = 99; - } else { - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - - Button.window_timer[button_index] = (loops_per_second >> 2) * 3; - } - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (!Settings.flag.button_single) { - 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; - } - } - if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) - Button.press_counter[i] = 99; - press_index = 0; - buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; - } - if (Button.press_counter[button_index]<99) { - press_index = 0; - buttonState = SHT_PRESSED_HOLD; - } - Button.press_counter[button_index] = 0; - } - if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { - press_index = -1; - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; - } else { - buttonState = SHT_PRESSED_EXT_HOLD; - } - } - } - } - - 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)) { - if (Button.press_counter[button_index]<99) { - - uint32 min_shutterbutton_press_counter = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); - if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { - min_shutterbutton_press_counter = Button.press_counter[i]; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); - } - } - if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: simultanous presss deteced")); - press_index = Button.press_counter[button_index]; - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) - Button.press_counter[i] = 99; - buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; - } - if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { - - press_index = Button.press_counter[button_index]; - buttonState = SHT_PRESSED_MULTI; - } - } - Button.press_counter[button_index] = 0; - } - } - } - - if (buttonState != SHT_NOT_PRESSED) { - if ((!Settings.flag.button_restrict) && (((press_index>=5) && (press_index<=7)) || (buttonState == SHT_PRESSED_EXT_HOLD) || (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS))){ - - uint8_t shutter_index_num_buttons = 0; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) { - shutter_index_num_buttons++; - } - } - if ((buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_MULTI))){ - - - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } else if ((buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_EXT_HOLD))){ - - - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } - if (buttonState <= SHT_PRESSED_IMMEDIATE) { - if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { - uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); - if (pos_press_index>3) pos_press_index=3; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); - XdrvMailbox.index = shutter_index +1; - last_source = SRC_BUTTON; - XdrvMailbox.data_len = 0; - char databuf[1] = ""; - XdrvMailbox.data = databuf; - XdrvMailbox.command = NULL; - if (buttonState == SHT_PRESSED_IMMEDIATE) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; - if (position) { - if (Shutter[shutter_index].direction) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - XdrvMailbox.payload = position = (position-1)<<1; - - if (102 == position) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterToggle(); - } else { - CmndShutterPosition(); - } - if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (dir) { - XdrvMailbox.payload = (Shutter[index].lastdirection > 0) ? 0 : 100; - } - else { - XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter[index].real_position, index)) ? 0 : 100; - } - XdrvMailbox.data_len = 0; - last_source = SRC_WEBGUI; - CmndShutterPosition(); - } -} - - - - - -void CmndShutterOpen(void) -{ - - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - XdrvMailbox.payload = 100; - last_source = SRC_WEBGUI; - CmndShutterPosition(); -} - -void CmndShutterStopOpen(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (Shutter[index].direction) { - CmndShutterStop(); - } else { - CmndShutterOpen(); - } - } -} - -void CmndShutterClose(void) -{ - - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - XdrvMailbox.payload = 0; - XdrvMailbox.data_len = 0; - last_source = SRC_WEBGUI; - CmndShutterPosition(); -} - -void CmndShutterStopClose(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (Shutter[index].direction) { - CmndShutterStop(); - } else { - CmndShutterClose(); - } - } -} - -void CmndShutterToggle(void) -{ - ShutterToggle(false); -} - -void CmndShutterToggleDir(void) -{ - ShutterToggle(true); -} - -void CmndShutterStopToggle(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (Shutter[index].direction) { - CmndShutterStop(); - } else { - CmndShutterToggle(); - } - } -} - -void CmndShutterStopToggleDir(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (Shutter[index].direction) { - CmndShutterStop(); - } else { - CmndShutterToggleDir(); - } - } -} - -void CmndShutterStop(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - uint32_t i = XdrvMailbox.index -1; - if (Shutter[i].direction != 0) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction); - - int32_t temp_realpos = ShutterCalculatePosition(i); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); - last_source = SRC_WEBGUI; - CmndShutterPosition(); - } else { - if (XdrvMailbox.command) - ResponseCmndDone(); - } - } else { - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterIncDec(void) -{ - - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - XdrvMailbox.payload = ShutterRealToPercentPosition(Shutter[XdrvMailbox.index-1].target_position, XdrvMailbox.index-1)+XdrvMailbox.payload; - - XdrvMailbox.payload = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload); - CmndShutterPosition(); - } - } -} - - -void CmndShutterPosition(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - uint32_t index = XdrvMailbox.index-1; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); - - - - if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { - - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) { - CmndShutterOpen(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE))) { - CmndShutterClose(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLE)) { - CmndShutterToggle(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDIR)) { - CmndShutterToggleDir(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter[index].direction) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE)))) { - XdrvMailbox.payload = -99; - CmndShutterStop(); - return; - } - } - - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter[index].real_position, index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); - - target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; - if (XdrvMailbox.payload != -99) { - - Shutter[index].target_position = ShutterPercentToRealPosition(target_pos_percent, index); - - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter[index].real_position ,Shutter[index].target_position,target_pos_percent); - } - if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2) { - if (Settings.shutter_options[index] & 4) { - if (0 == target_pos_percent) Shutter[index].target_position -= 1 * RESOLUTION * STEPS_PER_SECOND; - if (100 == target_pos_percent) Shutter[index].target_position += 1 * RESOLUTION * STEPS_PER_SECOND; - } - int8_t new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1; - if (Shutter[index].direction == -new_shutterdirection) { - ShutterPowerOff(index); - } - if (Shutter[index].direction != new_shutterdirection) { - ShutterStartInit(index, new_shutterdirection, Shutter[index].target_position); - switch (ShutterGlobal.position_mode) { - case SHT_COUNTER: - case SHT_PWM_TIME: - case SHT_PWM_VALUE: - case SHT_TIME_UP_DOWN: - if (!ShutterGlobal.skip_relay_change) { - - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); - - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - } - if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings.shutter_startrelay[index]+2, 1, SRC_SHUTTER); - break; - case SHT_TIME: - if (!ShutterGlobal.skip_relay_change) { - if ( (power >> (Settings.shutter_startrelay[index] -1)) & 3 > 0 ) { - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), Shutter[index].switch_mode == SHT_SWITCH ? 0 : 1, SRC_SHUTTER); - } - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); - } - break; - case SHT_TIME_GARAGE: - if (!ShutterGlobal.skip_relay_change) { - if (new_shutterdirection == Shutter[index].lastdirection) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Garage not move in this direction: %d"), Shutter[index].switch_mode == SHT_PULSE); - for (uint8_t k=0 ; k <= (uint8_t)(Shutter[index].switch_mode == SHT_PULSE) ; k++) { - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - delay(500); - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); - delay(500); - } - - Shutter[index].time = 0; - } - ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - } - break; - } - ShutterGlobal.RelayCurrentMask = 0; - } - } else { - target_pos_percent = ShutterRealToPercentPosition(Shutter[index].real_position, index); - ShutterReportPosition(true, index); - } - XdrvMailbox.index = index +1; - if (XdrvMailbox.command) - ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); - } else { - ShutterReportPosition(true, MAX_SHUTTERS); - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterStopPosition(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index-1; - if (Shutter[index].direction) { - XdrvMailbox.payload = -99; - CmndShutterStop(); - } else { - CmndShutterPosition(); - } - } -} -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 CmndShutterMotorDelay(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / STEPS_PER_SECOND, 2, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterMode(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) { - ShutterGlobal.position_mode = XdrvMailbox.payload; - Settings.shutter_mode = XdrvMailbox.payload; - ShutterInit(); - } - ResponseCmndNumber(ShutterGlobal.position_mode); -} - -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) { - ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1); - } else { - ShutterGlobal.RelayShutterMask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); - } - Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; - ShutterInit(); - - } - ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); - } -} - -void CmndShutterButton(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - uint32_t setting = 0; -# 1218 "/workspace/Tasmota/tasmota/xdrv_27_shutter.ino" - if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - uint32_t button_index = 0; - bool done = false; - bool isShortCommand = false; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field; - switch (str[0]) { - case '-': - field = -1; - break; - case 't': - field = 102; - break; - default: - field = atoi(str); - break; - } - switch (i) { - case 0: - if ((field >= -1) && (field<=4)) { - button_index = (field<=0)?(-1):field; - done = (button_index==-1); - } else - done = true; - break; - case 1: - if (!strcmp_P(str, PSTR("up"))) { - setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("down"))) { - setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("updown"))) { - setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("toggle"))) { - setting |= (((102>>1)+1)<<2) | (((50>>1)+1)<<8); - isShortCommand = true; - break; - } - case 2: - if (isShortCommand) { - if ((field==1) && (setting & (0x3F<<(2+6*3)))) - - setting |= (0x3<<29); - done = true; - break; - } - case 3: - case 4: - if ((field >= -1) && (field<=102)) - setting |= (((field>>1)+1)<<(i*6 + (2-6))); - break; - case 5: - case 6: - case 7: - case 8: - case 9: - if (field==1) - setting |= (1<<(i + (26-5))); - break; - } - if (done) break; - } - - if (button_index) { - if (button_index==-1) { - - for (uint32_t i=0 ; i < MAX_KEYS ; i++) - if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) - Settings.shutter_button[i] = 0; - } else { - if (setting) { - - setting |= (1<<31); - setting |= (XdrvMailbox.index-1) & 0x3; - } - Settings.shutter_button[button_index-1] = setting; - } - } - } - char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; - for (uint32_t i=0 ; i < MAX_KEYS ; i++) { - setting = Settings.shutter_button[i]; - if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { - if (*setting_chr_ptr == 0) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); - setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); - - for (uint32_t j=0 ; j < 4 ; j++) { - int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; - if (0 <= pos) - if (102 == pos) { - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" t")); - } else { - setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); - } - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - for (uint32_t j=0 ; j < 5 ; j++) { - bool mqtt = ((setting>>(26+j))&(0x01)!=0); - if (mqtt) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - } - } - ResponseCmndIdxChar(setting_chr); - } -} - -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_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; - ShutterInit(); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); - } -} - -void CmndShutterFrequency(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { - ShutterGlobal.open_velocity_max = XdrvMailbox.payload; - if (shutters_present < 4) { - Settings.shuttercoeff[4][3] = ShutterGlobal.open_velocity_max; - } - ShutterInit(); - } - ResponseCmndNumber(ShutterGlobal.open_velocity_max); -} - -void CmndShutterSetClose(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter[XdrvMailbox.index -1].real_position = 0; - ShutterStartInit(XdrvMailbox.index -1, 0, 0); - Settings.shutter_position[XdrvMailbox.index -1] = 0; - ResponseCmndIdxChar(D_CONFIGURATION_RESET); - } -} - -void CmndShutterSetOpen(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter[XdrvMailbox.index -1].real_position = Shutter[XdrvMailbox.index -1].open_max; - ShutterStartInit(XdrvMailbox.index -1, 0, Shutter[XdrvMailbox.index -1].open_max); - Settings.shutter_position[XdrvMailbox.index -1] = 100; - ResponseCmndIdxChar(D_CONFIGURATION_RESET); - } -} - -void CmndShutterPwmRange(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - uint8_t i = 0; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 2; str = strtok_r(nullptr, " ", &str_ptr), i++) { - uint16_t field = atoi(str); - - - if ((field <= 0) || (field > 1023)) { - break; - } - Settings.shutter_pwmrange[i][XdrvMailbox.index -1] = field; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); - ShutterInit(); - ResponseCmndIdxChar(XdrvMailbox.data); - } else { - char setting_chr[30] = "0"; - snprintf_P(setting_chr, sizeof(setting_chr), PSTR("Shutter %d: min:%d max:%d"), XdrvMailbox.index, Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); - ResponseCmndIdxChar(setting_chr); - } - } -} - -void CmndShutterCalibration(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - uint8_t i = 0; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field = atoi(str); - - - if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { - break; - } - messwerte[i] = field; - } - for (i = 0; i < 5; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); - } - ShutterInit(); - ResponseCmndIdxChar(XdrvMailbox.data); - } else { - char setting_chr[30] = "0"; - snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); - ResponseCmndIdxChar(setting_chr); - } - } -} - -void ShutterOptionsSetHelper(uint16_t option){ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(option); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (option); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & option) ? 1 : 0); - } -} - -void CmndShutterInvert(void) { - ShutterOptionsSetHelper(1); -} - -void CmndShutterLock(void) { - ShutterOptionsSetHelper(2); -} - -void CmndShutterEnableEndStopTime(void) { - ShutterOptionsSetHelper(4); -} - -void CmndShutterInvertWebButtons(void) { - ShutterOptionsSetHelper(8); -} - - - - - -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: - ShutterUpdatePosition(); - break; - case FUNC_EVERY_SECOND: - - ShutterReportPosition(false, MAX_SHUTTERS); - break; - - case FUNC_COMMAND: - result = DecodeCommand(kShutterCommands, ShutterCommand); - break; - case FUNC_JSON_APPEND: - for (uint8_t i = 0; i < shutters_present; i++) { - uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i] : Settings.shutter_position[i]; - uint8_t target = (Settings.shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter[i].target_position, i) : ShutterRealToPercentPosition(Shutter[i].target_position, i); - - ResponseAppend_P(","); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter[i].direction,target); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_SHUTTER, position); - } -#endif - } - break; - case FUNC_SET_POWER: - char stemp1[10]; - - ShutterGlobal.RelayCurrentMask = XdrvMailbox.index ^ ShutterGlobal.RelayOldMask; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), ShutterGlobal.RelayCurrentMask,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); - ShutterRelayChanged(); - ShutterGlobal.RelayOldMask = XdrvMailbox.index; - break; - case FUNC_SET_DEVICE_POWER: - if (ShutterGlobal.skip_relay_change ) { - uint8_t i; - for (i = 0; i < devices_present; i++) { - if (ShutterGlobal.RelayCurrentMask &1) { - break; - } - ShutterGlobal.RelayCurrentMask >>= 1; - } - - result = true; - ShutterGlobal.skip_relay_change = 0; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); - ExecuteCommandPowerShutter(i+1, 0, SRC_SHUTTER); - } - break; - case FUNC_BUTTON_PRESSED: - if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { - ShutterButtonHandler(); - result = true; - } - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_28_pcf8574.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_28_pcf8574.ino" -#ifdef USE_I2C -#ifdef USE_PCF8574 - - - - - - - -#define XDRV_28 28 -#define XI2C_02 2 - -#define PCF8574_ADDR1 0x20 -#define PCF8574_ADDR2 0x38 - -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; - uint8_t max_devices = 0; - char stype[9]; - bool type = false; -} Pcf8574; - -void Pcf8574SwitchRelay(void) -{ - for (uint32_t i = 0; i < devices_present; i++) { - uint8_t relay_state = bitRead(XdrvMailbox.index, 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; - - - - 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(); - } - - } - } -} - -void Pcf8574Init(void) -{ - uint8_t pcf8574_address = PCF8574_ADDR1; - while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { - -#ifdef USE_MCP230xx_ADDR - if (USE_MCP230xx_ADDR == pcf8574_address) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Address 0x%02x reserved for MCP320xx skipped"), pcf8574_address); - pcf8574_address++; - if ((PCF8574_ADDR1 +7) == pcf8574_address) { - pcf8574_address = PCF8574_ADDR2 +1; - } - } -#endif - - - - if (I2cSetDevice(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"); - } - I2cSetActiveFound(pcf8574_address, Pcf8574.stype); - } - - pcf8574_address++; - if ((PCF8574_ADDR1 +7) == pcf8574_address) { - pcf8574_address = PCF8574_ADDR2 +1; - } - } - if (Pcf8574.type) { - for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { - Pcf8574.pin[i] = 99; - } - devices_present = devices_present - Pcf8574.max_connected_ports; - Pcf8574.max_connected_ports = 0; - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - - 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; - - 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"), Pcf8574.max_devices, Pcf8574.max_connected_ports); - } -} - - - - - -#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 " " - "
" - "


"; - -const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = - "" D_DEVICE " %d " D_PORT " %d"; - -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++) { - 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("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void Pcf8574SaveSettings(void) -{ - char stemp[7]; - char tmp[100]; - - - - 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 ); - } - } - - - - } -} -#endif - - - - - -bool Xdrv28(uint8_t function) -{ - if (!I2cEnabled(XI2C_02)) { return false; } - - bool result = false; - - if (FUNC_PRE_INIT == function) { - Pcf8574Init(); - } - else if (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(PSTR("/" WEB_HANDLE_PCF8574), HandlePcf8574); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#ifdef USE_DEEPSLEEP -# 31 "/workspace/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#define XDRV_29 29 - -#define D_PRFX_DEEPSLEEP "DeepSleep" -#define D_CMND_DEEPSLEEP_TIME "Time" - -const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; -const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; -const uint32_t DEEPSLEEP_MIN_TIME = 5; -const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; - -const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" - D_CMND_DEEPSLEEP_TIME ; - -void (* const DeepsleepCommand[])(void) PROGMEM = { - &CmndDeepsleepTime }; - -uint32_t deepsleep_sleeptime = 0; -uint8_t deepsleep_flag = 0; - -bool DeepSleepEnabled(void) -{ - if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { - Settings.deepsleep = 0; - return false; - } - - if (PinUsed(GPIO_DEEPSLEEP)) { - pinMode(Pin(GPIO_DEEPSLEEP), INPUT_PULLUP); - return (digitalRead(Pin(GPIO_DEEPSLEEP))); - } - - return true; -} - -void DeepSleepReInit(void) -{ - if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { - if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { - - RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); - RtcSettingsSave(); - RtcRebootReset(); -#ifdef ESP8266 - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); -#else - esp_sleep_enable_timer_wakeup(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep)); - esp_deep_sleep_start(); -#endif - yield(); - - } - } - - RtcSettings.ultradeepsleep = 0; -} - -void DeepSleepPrepare(void) -{ - - - - - if ((RtcSettings.nextwakeup == 0) || - (RtcSettings.deepsleep_slip < 9000) || - (RtcSettings.deepsleep_slip > 11000) || - (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); - RtcSettings.nextwakeup = 0; - RtcSettings.deepsleep_slip = 10000; - } - - - - int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; - - - - timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; - if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); - - RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); - RtcSettings.nextwakeup += Settings.deepsleep; - } - - - - if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { - - RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; - } - - String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); - - - deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_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)); - - - -} - -void DeepSleepStart(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); - - WifiShutdown(); - RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); - RtcSettingsSave(); -#ifdef ESP8266 - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); -#else - esp_sleep_enable_timer_wakeup(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); - esp_deep_sleep_start(); -#endif - yield(); -} - -void DeepSleepEverySecond(void) -{ - if (!deepsleep_flag) { return; } - - if (DeepSleepEnabled()) { - if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { - SettingsSaveAll(); - DeepSleepPrepare(); - } - deepsleep_flag--; - if (deepsleep_flag <= 0) { - DeepSleepStart(); - } - } else { - deepsleep_flag = 0; - } -} - - - - - -void CmndDeepsleepTime(void) -{ - if ((0 == XdrvMailbox.payload) || - ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { - Settings.deepsleep = XdrvMailbox.payload; - RtcSettings.nextwakeup = 0; - deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; - if (deepsleep_flag) { - if (!Settings.tele_period) { - Settings.tele_period = TELE_PERIOD; - } - } - } - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); -} - - - - - -bool Xdrv29(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - DeepSleepEverySecond(); - break; - case FUNC_AFTER_TELEPERIOD: - if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { - deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); - break; - case FUNC_PRE_INIT: - DeepSleepReInit(); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_EXS_DIMMER - - - - - - - -#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 - -#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; - int byte_counter = 0; - int cmd_status = 0; - uint8_t power = 0; - uint8_t dimm[2] = {0, 0}; - DIMMER dimmer; -} Exs; - - - - - -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(); - - - uint32_t snd_time = millis(); - while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && - (!ExsSerial->available())) - ; - - if (!ExsSerial->available()) - { - -#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); -} - -void ExsSetPower(uint8_t device, uint8_t power) -{ - Exs.dimmer.channel[device].dimm = power; - ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); -} - -void ExsSetBri(uint8_t device, uint8_t bri) -{ - Exs.dimmer.channel[device].bright_tbl = bri; - ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); -} - -void 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); - return true; -} - -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: -# 295 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - if (len > 9) - { - Exs.dimmer.version_major = Exs.buffer[3]; - Exs.dimmer.version_minor = Exs.buffer[4]; - - - 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[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 -# 328 "/workspace/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - { - Exs.dimmer.version_major = 1; - Exs.dimmer.version_minor = 0; - - - 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[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(); - ExsSyncState(); - ExsDebugState(); - break; - default: - break; - } -} - - - -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_ENABLE)); -#endif - - pinMode(Pin(GPIO_EXS_ENABLE), OUTPUT); - digitalWrite(Pin(GPIO_EXS_ENABLE), LOW); - - delay(1); - - while (ExsSerial->available()) - { - - 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]); - - - 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); - ExsPacketProcess(); - } - else - { - ExsSerial->write(0x00); - } - - } - } - } -} - - - - - -#ifdef EXS_MCU_CMNDS - -#define D_PRFX_EXS "Exs" -#define D_CMND_EXS_DIMM "Dimm" -#define D_CMND_EXS_DIMM_TBL "DimmTbl" -#define D_CMND_EXS_DIMM_VAL "DimmVal" -#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_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" - D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" - D_CMND_EXS_STATE; - -void (* const ExsCommand[])(void) PROGMEM = { - &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, - &CmndExsDimms, &CmndExsChLock, - &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 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); - - - 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 - - - - - -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 -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_31_tasmota_client.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_31_tasmota_client.ino" -#ifdef USE_TASMOTA_CLIENT - - - - -#define XDRV_31 31 - -#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 - - - - - -#define CMND_START 0xFC -#define CMND_END 0xFD - -#define CMND_FEATURES 0x01 -#define CMND_JSON 0x02 -#define CMND_FUNC_EVERY_SECOND 0x03 -#define CMND_FUNC_EVERY_100_MSECOND 0x04 -#define CMND_CLIENT_SEND 0x05 -#define CMND_PUBLISH_TELE 0x06 -#define CMND_EXECUTE_CMND 0x07 - -#define PARAM_DATA_START 0xFE -#define PARAM_DATA_END 0xFF - -#include - - - - - -class SimpleHexParse { - public: - SimpleHexParse(void); - uint8_t parseLine(char *hexline); - uint8_t ptr_l = 0; - uint8_t ptr_h = 0; - bool PageIsReady = false; - bool firstrun = true; - bool EndOfFile = false; - uint8_t FlashPage[128]; - uint8_t FlashPageIdx = 0; - uint8_t layoverBuffer[16]; - uint8_t layoverIdx = 0; - uint8_t getByte(char *hexline, uint8_t idx); -}; - -SimpleHexParse::SimpleHexParse(void) { - -} - -uint8_t SimpleHexParse::parseLine(char *hexline) { - if (layoverIdx) { - memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); - FlashPageIdx = layoverIdx; - layoverIdx = 0; - } - uint8_t len = getByte(hexline, 1); - uint8_t addr_h = getByte(hexline, 2); - uint8_t addr_l = getByte(hexline, 3); - uint8_t rectype = getByte(hexline, 4); - for (uint8_t idx = 0; idx < len; idx++) { - if (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = getByte(hexline, idx+5); - FlashPageIdx++; - } else { - layoverBuffer[layoverIdx] = getByte(hexline, idx+5); - layoverIdx++; - } - } - if (1 == rectype) { - EndOfFile = true; - while (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = 0xFF; - FlashPageIdx++; - } - } - if (FlashPageIdx == 128) { - if (firstrun) { - firstrun = false; - } else { - ptr_l += 0x40; - if (ptr_l == 0) { - ptr_l = 0; - ptr_h++; - } - } - firstrun = false; - PageIsReady = true; - } - return 0; -} - -uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) { - char buff[3]; - buff[3] = '\0'; - memcpy(&buff, &hexline[(idx*2)-1], 2); - return strtol(buff, 0, 16); -} - - - - - -struct TCLIENT { - 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; - bool SerialEnabled = false; - uint8_t waitstate = 0; - bool unsupported = false; -} TClient; - -typedef union { - uint32_t data; - struct { - uint32_t func_json_append : 1; - uint32_t func_every_second : 1; - uint32_t func_every_100_msecond : 1; - uint32_t func_client_send : 1; - uint32_t spare4 : 1; - uint32_t spare5 : 1; - uint32_t spare6 : 1; - uint32_t spare7 : 1; - uint32_t spare8 : 1; - uint32_t spare9 : 1; - uint32_t spare10 : 1; - uint32_t spare11 : 1; - uint32_t spare12 : 1; - uint32_t spare13 : 1; - uint32_t spare14 : 1; - uint32_t spare15 : 1; - uint32_t spare16 : 1; - uint32_t spare17 : 1; - uint32_t spare18 : 1; - uint32_t spare19 : 1; - uint32_t spare20 : 1; - uint32_t spare21 : 1; - uint32_t spare22 : 1; - uint32_t spare23 : 1; - uint32_t spare24 : 1; - uint32_t spare25 : 1; - uint32_t spare26 : 1; - uint32_t spare27 : 1; - uint32_t spare28 : 1; - uint32_t spare29 : 1; - uint32_t spare30 : 1; - uint32_t spare31 : 1; - }; -} TClientFeatureCfg; - - - - - - -struct TCLIENT_FEATURES { - uint32_t features_version; - TClientFeatureCfg features; -} TClientSettings; - -struct TCLIENT_COMMAND { - uint8_t command; - uint8_t parameter; - uint8_t unused2; - uint8_t unused3; -} TClientCommand; - -TasmotaSerial *TasmotaClient_Serial; - -uint32_t TasmotaClient_FlashStart(void) { - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; -} - -uint8_t TasmotaClient_UpdateInit(void) { - TClient.spi_hex_size = 0; - TClient.spi_sector_counter = TasmotaClient_FlashStart(); - TClient.spi_sector_cursor = 0; - return 0; -} - -void TasmotaClient_Reset(void) { - if (TClient.SerialEnabled) { - digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted); - delay(1); - digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), TClient.inverted); - delay(1); - digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted); - delay(5); - } -} - -uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout) { - int timer = 0; - while (timer < timeout) { - if (TasmotaClient_Serial->available() >= dataCount) { - return 1; - } - delay(1); - timer++; - } - return 0; -} - -uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count) { - TasmotaClient_Serial->write(bytes, count); - TasmotaClient_waitForSerialData(2, 250); - uint8_t sync = TasmotaClient_Serial->read(); - uint8_t ok = TasmotaClient_Serial->read(); - if ((sync == 0x14) && (ok == 0x10)) { - return 1; - } - return 0; -} - -uint8_t TasmotaClient_execCmd(uint8_t cmd) { - uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; - return TasmotaClient_sendBytes(bytes, 2); -} - -uint8_t TasmotaClient_execParam(uint8_t cmd, uint8_t* params, int count) { - uint8_t 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 TasmotaClient_sendBytes(bytes, i + 2); -} - -uint8_t TasmotaClient_exitProgMode(void) { - return TasmotaClient_execCmd(CMND_STK_LEAVE_PROGMODE); -} - -uint8_t TasmotaClient_SetupFlash(void) { - 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}; - TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_FLASH_SPEED); - if (TasmotaClient_Serial->hardwareSerial()) { - ClaimSerial(); - } - - TasmotaClient_Reset(); - - uint8_t timeout = 0; - uint8_t no_error = 0; - while (50 > timeout) { - if (TasmotaClient_execCmd(CMND_STK_GET_SYNC)) { - timeout = 200; - no_error = 1; - } - timeout++; - delay(1); - } - if (no_error) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Found bootloader")); - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Bootloader could not be found")); - } - if (no_error) { - if (TasmotaClient_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (1)")); - } - } - if (no_error) { - if (TasmotaClient_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (2)")); - } - } - if (no_error) { - if (TasmotaClient_execCmd(CMND_STK_ENTER_PROGMODE)) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Failed to put bootloader into programming mode")); - } - } - return no_error; -} - -uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo) { - uint8_t params[] = { adrLo, adrHi }; - return TasmotaClient_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); -} - -void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { - uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; - TasmotaClient_loadAddress(addr_h, addr_l); - TasmotaClient_Serial->write(Header, 4); - for (int i = 0; i < 128; i++) { - TasmotaClient_Serial->write(data[i]); - } - TasmotaClient_Serial->write(CONST_STK_CRC_EOP); - TasmotaClient_waitForSerialData(2, 250); - TasmotaClient_Serial->read(); - TasmotaClient_Serial->read(); -} - -void TasmotaClient_Flash(void) { - bool reading = true; - uint32_t read = 0; - uint32_t processed = 0; - char thishexline[50]; - uint8_t position = 0; - char* flash_buffer; - - SimpleHexParse hexParse = SimpleHexParse(); - - if (!TasmotaClient_SetupFlash()) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flashing aborted!")); - TClient.flashing = false; - restart_flag = 2; - return; - } - - flash_buffer = new char[SPI_FLASH_SEC_SIZE]; - uint32_t flash_start = TasmotaClient_FlashStart() * SPI_FLASH_SEC_SIZE; - while (reading) { - ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); - read = read + SPI_FLASH_SEC_SIZE; - if (read >= TClient.spi_hex_size) { - reading = false; - } - for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { - processed++; - if ((processed <= TClient.spi_hex_size) && (!hexParse.EndOfFile)) { - if (':' == flash_buffer[ca]) { - position = 0; - } - if (0x0D == flash_buffer[ca]) { - thishexline[position] = 0; - hexParse.parseLine(thishexline); - if (hexParse.PageIsReady) { - TasmotaClient_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); - hexParse.PageIsReady = false; - hexParse.FlashPageIdx = 0; - } - } else { - if (0x0A != flash_buffer[ca]) { - thishexline[position] = flash_buffer[ca]; - position++; - } - } - } - } - } - TasmotaClient_exitProgMode(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flash done!")); - TClient.flashing = false; - restart_flag = 2; -} - -void TasmotaClient_SetFlagFlashing(bool value) { - TClient.flashing = value; -} - -bool TasmotaClient_GetFlagFlashing(void) { - return TClient.flashing; -} - -void TasmotaClient_WriteBuffer(uint8_t *buf, size_t size) { - if (0 == TClient.spi_sector_cursor) { - ESP.flashEraseSector(TClient.spi_sector_counter); - } - TClient.spi_sector_cursor++; - ESP.flashWrite((TClient.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TClient.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); - TClient.spi_hex_size = TClient.spi_hex_size + size; - if (2 == TClient.spi_sector_cursor) { - TClient.spi_sector_cursor = 0; - TClient.spi_sector_counter++; - } -} - -void TasmotaClient_Init(void) { - if (TClient.type) { - return; - } - if (10 > TClient.waitstate) { - TClient.waitstate++; - return; - } - if (!TClient.SerialEnabled) { - if (PinUsed(GPIO_TASMOTACLIENT_RXD) && PinUsed(GPIO_TASMOTACLIENT_TXD) && - (PinUsed(GPIO_TASMOTACLIENT_RST) || PinUsed(GPIO_TASMOTACLIENT_RST_INV))) { - TasmotaClient_Serial = new TasmotaSerial(Pin(GPIO_TASMOTACLIENT_RXD), Pin(GPIO_TASMOTACLIENT_TXD), 1, 0, 200); - if (TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_SERIAL_SPEED)) { - if (TasmotaClient_Serial->hardwareSerial()) { - ClaimSerial(); - } - TasmotaClient_Serial->setTimeout(100); - if (PinUsed(GPIO_TASMOTACLIENT_RST_INV)) { - SetPin(Pin(GPIO_TASMOTACLIENT_RST_INV), AGPIO(GPIO_TASMOTACLIENT_RST)); - TClient.inverted = HIGH; - } - pinMode(Pin(GPIO_TASMOTACLIENT_RST), OUTPUT); - TClient.SerialEnabled = true; - TasmotaClient_Reset(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Enabled")); - } - } - } - if (TClient.SerialEnabled) { - TasmotaClient_sendCmnd(CMND_FEATURES, 0); - char buffer[32] = { 0 }; - TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); - uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); - - if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } - - memcpy(&TClientSettings, &buffer, sizeof(TClientSettings)); - if (20191129 == TClientSettings.features_version) { - TClient.type = true; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version); - } else { - if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version); - TClient.unsupported = true; - } - } - } -} - -bool TasmotaClient_Available(void) { - return TClient.SerialEnabled; -} - -void TasmotaClient_Show(void) { - if ((TClient.type) && (TClientSettings.features.func_json_append)) { - char buffer[100]; - TasmotaClient_sendCmnd(CMND_JSON, 0); - TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); - uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); - buffer[len] = '\0'; - ResponseAppend_P(PSTR(",\"TasmotaClient\":%s"), buffer); - } -} - -void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param) { - TClientCommand.command = cmnd; - TClientCommand.parameter = param; - char buffer[sizeof(TClientCommand)+2]; - buffer[0] = CMND_START; - memcpy(&buffer[1], &TClientCommand, sizeof(TClientCommand)); - buffer[sizeof(TClientCommand)+1] = CMND_END; - - TasmotaClient_Serial->flush(); - - for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { - TasmotaClient_Serial->write(buffer[ca]); - } -} - -#define D_PRFX_CLIENT "Client" -#define D_CMND_CLIENT_RESET "Reset" -#define D_CMND_CLIENT_SEND "Send" - -const char kTasmotaClientCommands[] PROGMEM = D_PRFX_CLIENT "|" - D_CMND_CLIENT_RESET "|" D_CMND_CLIENT_SEND; - -void (* const TasmotaClientCommand[])(void) PROGMEM = { - &CmndClientReset, &CmndClientSend }; - -void CmndClientReset(void) { - TasmotaClient_Reset(); - TClient.type = false; - TClient.waitstate = 7; - TClient.unsupported = false; - ResponseCmndDone(); -} - -void CmndClientSend(void) { - if (TClient.SerialEnabled) { - if (0 < XdrvMailbox.data_len) { - TasmotaClient_sendCmnd(CMND_CLIENT_SEND, XdrvMailbox.data_len); - TasmotaClient_Serial->write(char(PARAM_DATA_START)); - for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { - TasmotaClient_Serial->write(XdrvMailbox.data[idx]); - } - TasmotaClient_Serial->write(char(PARAM_DATA_END)); - } - ResponseCmndDone(); - } -} - -void TasmotaClient_ProcessIn(void) { - uint8_t cmnd = TasmotaClient_Serial->read(); - if (CMND_START == cmnd) { - TasmotaClient_waitForSerialData(sizeof(TClientCommand),50); - uint8_t buffer[sizeof(TClientCommand)]; - for (uint8_t idx = 0; idx < sizeof(TClientCommand); idx++) { - buffer[idx] = TasmotaClient_Serial->read(); - } - TasmotaClient_Serial->read(); - memcpy(&TClientCommand, &buffer, sizeof(TClientCommand)); - char inbuf[TClientCommand.parameter+1]; - TasmotaClient_waitForSerialData(TClientCommand.parameter, 50); - TasmotaClient_Serial->read(); - for (uint8_t idx = 0; idx < TClientCommand.parameter; idx++) { - inbuf[idx] = TasmotaClient_Serial->read(); - } - TasmotaClient_Serial->read(); - inbuf[TClientCommand.parameter] = '\0'; - - if (CMND_PUBLISH_TELE == TClientCommand.command) { - Response_P(PSTR("{\"TasmotaClient\":")); - ResponseAppend_P("%s", inbuf); - ResponseJsonEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, mqtt_data); - } - if (CMND_EXECUTE_CMND == TClientCommand.command) { - ExecuteCommand(inbuf, SRC_IGNORE); - } - } -} - - - - - -bool Xdrv31(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if (TClient.type) { - if (TasmotaClient_Serial->available()) { - TasmotaClient_ProcessIn(); - } - if (TClientSettings.features.func_every_100_msecond) { - TasmotaClient_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); - } - } - break; - case FUNC_EVERY_SECOND: - if ((TClient.type) && (TClientSettings.features.func_every_second)) { - TasmotaClient_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); - } - TasmotaClient_Init(); - break; - case FUNC_JSON_APPEND: - if ((TClient.type) && (TClientSettings.features.func_json_append)) { - TasmotaClient_Show(); - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kTasmotaClientCommands, TasmotaClientCommand); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_32_hotplug.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_32_hotplug.ino" -#ifdef USE_HOTPLUG - - - - - - - -#define XDRV_32 32 - -const uint32_t HOTPLUG_MAX = 254; - -const char kHotPlugCommands[] PROGMEM = "|" - D_CMND_HOTPLUG; - -void (* const HotPlugCommand[])(void) PROGMEM = { - &CmndHotPlugTime }; - -struct { - - bool enabled = false; - uint8_t timeout = 0; -} Hotplug; - -void HotPlugInit(void) -{ - - if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } - if (Settings.hotplug_scan != 0) { - Hotplug.enabled = true; - Hotplug.timeout = 1; - } else - Hotplug.enabled = false; -} - -void HotPlugEverySecond(void) -{ - if (Hotplug.enabled) { - if (Hotplug.timeout == 0) { - XsnsCall(FUNC_HOTPLUG_SCAN); - Hotplug.timeout = Settings.hotplug_scan; - } - Hotplug.timeout--; - } -} - - - - - -void CmndHotPlugTime(void) -{ - if (XdrvMailbox.payload <= HOTPLUG_MAX) { - Settings.hotplug_scan = XdrvMailbox.payload; - HotPlugInit(); - } - ResponseCmndNumber(Settings.hotplug_scan); -} - - - - - -bool Xdrv32(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - HotPlugEverySecond(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kHotPlugCommands, HotPlugCommand); - break; - case FUNC_PRE_INIT: - HotPlugInit(); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -# 31 "/workspace/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 - - - - - - - -#define XDRV_33 33 - -#include - -const char NRF24type[] PROGMEM = "NRF24"; - -struct { - uint8_t chipType = 0; -} NRF24; - - - -RF24 NRF24radio; - -bool NRF24initRadio() -{ - NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); - NRF24radio.powerUp(); - - if(NRF24radio.isChipConnected()){ - DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); - return true; - } - DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); - return false; -} - -bool NRF24Detect(void) -{ - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_DC)) { - if(NRF24initRadio()){ - NRF24.chipType = 32; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); - if(NRF24radio.isPVariant()){ - NRF24.chipType = 43; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); - } - return true; - } - } - return false; -} - - - - - -bool Xdrv33(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - result = NRF24Detect(); - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -#ifdef USE_I2C -#ifdef USE_WEMOS_MOTOR_V1 -# 45 "/workspace/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -#define XDRV_34 34 -#define XI2C_44 44 - -#ifndef WEMOS_MOTOR_V1_ADDR -#define WEMOS_MOTOR_V1_ADDR 0x30 -#endif -#ifndef WEMOS_MOTOR_V1_FREQ -#define WEMOS_MOTOR_V1_FREQ 1000 -#endif - -#define MOTOR_A 0 -#define MOTOR_B 1 - -#define SHORT_BRAKE 0 -#define CCW 1 -#define CW 2 -#define STOP 3 -#define STANDBY 4 - -struct WMOTORV1 { - bool detected = false; - uint8_t motor; -} WMotorV1; - -void WMotorV1Detect(void) -{ - if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) { - WMotorV1.detected = true; - I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); - WMotorV1Reset(); - } -} - -void WMotorV1Reset(void) -{ - - WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ); -} - -void WMotorV1SetFrequency(uint32_t freq) -{ - Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); - Wire.write(((byte)(freq >> 16)) & (byte)0x0f); - Wire.write((byte)(freq >> 16)); - Wire.write((byte)(freq >> 8)); - Wire.write((byte)freq); - Wire.endTransmission(); - -} - -void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val) -{ - Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); - Wire.write(motor | (byte)0x10); - Wire.write(dir); - - uint16_t _pwm_val = uint16_t(pwm_val * 100); - if (_pwm_val > 10000) { - _pwm_val = 10000; - } - - Wire.write((byte)(_pwm_val >> 8)); - Wire.write((byte)_pwm_val); - Wire.endTransmission(); - -} - -bool WMotorV1Command(void) -{ - uint8_t args_count = 0; - - if (XdrvMailbox.data_len > 0) { - args_count = 1; - } else { - return false; - } - - for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) { - if (' ' == XdrvMailbox.data[idx]) { - XdrvMailbox.data[idx] = ','; - } - if (',' == XdrvMailbox.data[idx]) { - args_count++; - } - } - UpperCase(XdrvMailbox.data, XdrvMailbox.data); - - char *command = strtok(XdrvMailbox.data, ","); - - if (strcmp(command, "RESET") == 0) { - WMotorV1Reset(); - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); - return true; - } - - if (strcmp(command, "SETMOTOR") == 0) { - if (args_count >= 3) { - - int motor = atoi(strtok(NULL, ",")); - int dir = atoi(strtok(NULL, ",")); - int duty = 100; - if (args_count == 4) { - duty = atoi(strtok(NULL, ",")); - } - - WMotorV1SetMotor(motor, dir, duty); - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); - return true; - } - } - return false; -} - - - - - -bool Xdrv34(uint8_t function) -{ - if (!I2cEnabled(XI2C_44)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - WMotorV1Detect(); - } - else if (WMotorV1.detected) { - switch (function) { - case FUNC_COMMAND_DRIVER: - if (XI2C_44 == XdrvMailbox.index) { - result = WMotorV1Command(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" -#ifdef USE_PWM_DIMMER -# 33 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" -#define XDRV_35 35 -#define MAX_PWM_DIMMER_KEYS 3 - -const char kPWMDimmerCommands[] PROGMEM = "|" - D_CMND_BRI_PRESET -#ifdef USE_DEVICE_GROUPS - "|" D_CMND_PWM_DIMMER_PWMS -#endif - ; - -void (* const PWMDimmerCommand[])(void) PROGMEM = { - &CmndBriPreset, -#ifdef USE_DEVICE_GROUPS - &CmndPWMDimmerPWMs, -#endif - }; - -#ifdef USE_PWM_DIMMER_REMOTE -struct remote_pwm_dimmer { - bool power_on; - uint8_t bri_power_on; - uint8_t bri_preset_low; - uint8_t bri_preset_high; - uint8_t fixed_color_index; - uint8_t bri; - bool power_button_increases_bri; -}; -#endif - -uint32_t ignore_any_key_time = 0; -uint32_t button_hold_time[3]; -uint8_t led_timeout_seconds = 0; -uint8_t restore_powered_off_led_counter = 0; -uint8_t power_button_index = 0; -uint8_t down_button_index = 1; -uint8_t buttons_pressed = 0; -uint8_t local_fixed_color_index = 128; -bool button_tapped = false; -bool down_button_tapped = false; -bool ignore_power_button = false; -bool multibutton_in_progress = false; -bool power_button_increases_bri = true; -bool tap_handled = false; -bool invert_power_button_bri_direction = false; -bool button_pressed[3] = { false, false, false }; -bool button_held[3]; -#ifdef USE_PWM_DIMMER_REMOTE -struct remote_pwm_dimmer remote_pwm_dimmers[MAX_PWM_DIMMER_KEYS]; -struct remote_pwm_dimmer * active_remote_pwm_dimmer; -#endif - -void PWMModulePreInit(void) -{ - Settings.seriallog_level = 0; - Settings.flag.mqtt_serial = 0; - Settings.ledstate = 0; - - - if (Settings.last_module != Settings.module) { - Settings.flag.pwm_control = true; - Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0; - Settings.last_module = Settings.module; - - - - - - if (Settings.param[P_HOLD_TIME] == 5) Settings.param[P_HOLD_TIME] = 40; - } - - - if (!Settings.bri_power_on) Settings.bri_power_on = 128; - if (!Settings.bri_preset_low) Settings.bri_preset_low = 10; - if (Settings.bri_preset_high < Settings.bri_preset_low) Settings.bri_preset_high = 255; - - PWMDimmerSetPoweredOffLed(); - - - - -#ifdef USE_PWM_DIMMER_REMOTE - - - if (Settings.flag4.multiple_device_groups) { - Settings.flag4.device_groups_enabled = true; - - device_group_count = 0; - for (uint32_t button_index = 0; button_index < MAX_PWM_DIMMER_KEYS; button_index++) { - if (PinUsed(GPIO_KEY1, button_index)) device_group_count++; - } - - - if (!PinUsed(GPIO_REL1) && !PinUsed(GPIO_PWM1)) { - first_device_group_is_local = false; - - - devices_present--; - light_type = 0; - } - - for (uint8_t i = 0; i < MAX_PWM_DIMMER_KEYS; i++) { - active_remote_pwm_dimmer = &remote_pwm_dimmers[i]; - active_remote_pwm_dimmer->bri_power_on = 128; - active_remote_pwm_dimmer->bri_preset_low = 10; - active_remote_pwm_dimmer->bri_preset_high = 255; - active_remote_pwm_dimmer->fixed_color_index = 128; - } - } -#endif -} - - -void PWMDimmerSetBrightnessLeds(int32_t bri) -{ - - uint32_t leds = 0; - uint32_t mask = 1; - int32_t led; - for (led = 0; led < leds_present; led++) { - if (Settings.ledmask & mask) leds++; - mask <<= 1; - } - - - - if (leds) { - led_timeout_seconds = 5; - if (bri < 0) { - bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri()); - if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0; - } - uint32_t step = 256 / (leds + 1); - - - uint32_t level = 0; - led = -1; - mask = 0; - for (uint32_t count = 0; count < leds; count++) { - level += step; - for (;;) { - led++; - mask <<= 1; - if (!mask) mask = 1; - if (Settings.ledmask & mask) break; - } - SetLedPowerIdx(led, bri >= level); - } - } -} - -void PWMDimmerSetPoweredOffLed(void) -{ - - if (PinUsed(GPIO_LEDLNK)) { - bool power_off_led_on = !power && Settings.flag4.powered_off_led; - if (ledlnk_inverted) power_off_led_on ^= 1; - digitalWrite(Pin(GPIO_LEDLNK), power_off_led_on); - } -} - -void PWMDimmerSetPower(void) -{ - DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power); - PWMDimmerSetBrightnessLeds(-1); - PWMDimmerSetPoweredOffLed(); -} - -#ifdef USE_DEVICE_GROUPS -void PWMDimmerHandleDevGroupItem(void) -{ -#ifdef USE_PWM_DIMMER_REMOTE - uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic; - bool is_local = ((XdrvMailbox.index & DGR_FLAG_LOCAL) != 0); - if (device_group_index > MAX_PWM_DIMMER_KEYS) return; - struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index]; -#else - if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return; -#endif - uint32_t value = XdrvMailbox.payload; - - switch (XdrvMailbox.command_code) { -#ifdef USE_PWM_DIMMER_REMOTE - case DGR_ITEM_LIGHT_BRI: - remote_pwm_dimmer->bri = value; - break; - case DGR_ITEM_POWER: - remote_pwm_dimmer->power_on = value & 1; - remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128); - break; -#endif - case DGR_ITEM_LIGHT_FIXED_COLOR: -#ifdef USE_PWM_DIMMER_REMOTE - remote_pwm_dimmer->fixed_color_index = value; - if (is_local) -#endif - local_fixed_color_index = value; - break; - case DGR_ITEM_BRI_POWER_ON: -#ifdef USE_PWM_DIMMER_REMOTE - remote_pwm_dimmer->bri_power_on = value; - if (is_local) -#endif - Settings.bri_power_on = value; - break; - case DGR_ITEM_BRI_PRESET_LOW: -#ifdef USE_PWM_DIMMER_REMOTE - remote_pwm_dimmer->bri_preset_low = value; - if (is_local) -#endif - Settings.bri_preset_low = value; - break; - case DGR_ITEM_BRI_PRESET_HIGH: -#ifdef USE_PWM_DIMMER_REMOTE - remote_pwm_dimmer->bri_preset_high = value; - if (is_local) -#endif - Settings.bri_preset_high = value; - break; - case DGR_ITEM_STATUS: -#ifdef USE_PWM_DIMMER_REMOTE - if (is_local) -#endif - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on, - DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); - break; - } -} -#endif - -void PWMDimmerHandleButton(uint32_t button_index, bool pressed) -{ - bool handle_tap = false; - bool state_updated = false; - int32_t bri_offset = 0; - uint8_t power_on_bri = 0; - uint8_t dgr_item = 0; - uint8_t dgr_value = 0; - uint8_t dgr_more_to_come = true; - uint8_t mqtt_trigger = 0; - - -#ifdef USE_PWM_DIMMER_REMOTE - bool power_is_on = (active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : power); - bool is_power_button = (button_index == power_button_index); - bool is_down_button = (button_index == down_button_index); -#else - bool power_is_on = power; - bool is_power_button = !button_index; - bool is_down_button = (button_index == (power_button_index ? 0 : 1)); -#endif - - - if (pressed) { - uint32_t now = millis(); - - - if (is_power_button) { - - - if (!ignore_power_button && buttons_pressed == 1) { - - - - - if (power_is_on) { -#ifdef USE_PWM_DIMMER_REMOTE - bri_offset = (active_remote_pwm_dimmer ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); -#else - bri_offset = (power_button_increases_bri ? 1 : -1); -#endif - invert_power_button_bri_direction = true; - } - - - - else { -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; - else -#endif - power_on_bri = Settings.bri_preset_low; - button_hold_time[button_index] = now + 500; - } - } - } - - - else { - - - if (button_pressed[power_button_index]) { - - - - if (button_tapped) { - handle_tap = true; - button_hold_time[button_index] = now + 500; - } - - - - else if (power_is_on && Settings.flag4.multiple_device_groups) { - bri_offset = (is_down_button ? -1 : 1); - } - - - else { - mqtt_trigger = (is_down_button ? 1 : 2); - button_hold_time[button_index] = now + 60000; - ignore_power_button = true; - } - } - - - - else if (power_is_on && !button_tapped) { - bri_offset = (is_down_button ? -1 : 1); - } - } - } - - - else { - bool button_was_held = button_held[button_index]; - - - if (is_power_button) { - - - - - if (button_tapped) { - if (!tap_handled) { -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_remote_pwm_dimmer) { -#endif - - - if (down_button_tapped) { - Settings.flag4.led_timeout ^= 1; - if (Light.power) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? 0 : -1); - } - - - else { - Settings.flag4.powered_off_led ^= 1; - PWMDimmerSetPoweredOffLed(); - } -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif - } - tap_handled = false; - } - - - else if (button_was_held) { - - - - if (invert_power_button_bri_direction) { - invert_power_button_bri_direction = false; -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - active_remote_pwm_dimmer->power_button_increases_bri ^= 1; - else -#endif - power_button_increases_bri ^= 1; -#ifdef USE_PWM_DIMMER_REMOTE - dgr_item = DGR_ITEM_FLAGS; - state_updated = true; -#endif - } - } - - - - else if (!ignore_power_button) { -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - power_on_bri = active_remote_pwm_dimmer->bri_power_on; - else -#endif - power_on_bri = Settings.bri_power_on; - } - } - - - else { - - - - if (button_pressed[power_button_index]) { - ignore_power_button = true; - - - if (button_tapped) { - handle_tap = true; - } - - - else if (!button_was_held) { - button_tapped = true; - down_button_tapped = is_down_button; - } - } - - - else { - - - if (power_is_on) { - - - - if (!button_was_held) { - bri_offset = (is_down_button ? -5 : 5); - dgr_more_to_come = false; - state_updated = true; - } - - - - else { - dgr_item = DGR_ITEM_FLAGS; - state_updated = true; - } - } - - - - else { -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); - else -#endif - power_on_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); - } - } - } - } - - - if (bri_offset) { - int32_t bri; -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - bri = active_remote_pwm_dimmer->bri; - else -#endif - bri = light_state.getBri(); - int32_t new_bri = bri + bri_offset * ((dgr_item ? 16 : Settings.light_correction ? 4 : bri / 16 + 1)); - - if (bri_offset > 0) { - if (new_bri > 255) new_bri = 255; - } - else { - if (new_bri < 1) new_bri = 1; - } - if (new_bri != bri) { -#ifdef USE_DEVICE_GROUPS - SendDeviceGroupMessage(power_button_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_BRI, new_bri); -#endif -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) { - active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; - PWMDimmerSetBrightnessLeds(new_bri); - } - else { -#endif - skip_light_fade = true; -#ifdef USE_DEVICE_GROUPS - ignore_dgr_sends = true; -#endif - light_state.setBri(new_bri); - LightAnimate(); - skip_light_fade = false; -#ifdef USE_DEVICE_GROUPS - ignore_dgr_sends = false; -#endif - Settings.bri_power_on = new_bri; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif - } -#ifdef USE_PWM_DIMMER_REMOTE - else if (active_remote_pwm_dimmer) - PWMDimmerSetBrightnessLeds(new_bri); -#endif - else - PWMDimmerSetBrightnessLeds(-1); - } - - - else if (power_on_bri) { - power_t new_power; -#ifdef USE_DEVICE_GROUPS -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) { - active_remote_pwm_dimmer->power_on ^= 1; - new_power = active_remote_pwm_dimmer->power_on; - PWMDimmerSetBrightnessLeds(new_power ? -power_on_bri : 0); - } - else { -#endif - new_power = power ^ 1; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif - if (new_power) - SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, power_on_bri, DGR_ITEM_POWER, new_power); - else - SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, new_power); -#endif -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) - active_remote_pwm_dimmer->power_button_increases_bri = (power_on_bri < 128); - else { -#endif - light_state.setBri(power_on_bri); -#ifdef USE_DEVICE_GROUPS - Light.devgrp_no_channels_out = true; -#endif - ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); -#ifdef USE_DEVICE_GROUPS - Light.devgrp_no_channels_out = false; -#endif -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif - } - - - - if (handle_tap) { - ignore_power_button = tap_handled = true; - - - - if (down_button_tapped) { -#ifdef USE_DEVICE_GROUPS - int8_t add_value = (is_down_button ? -1 : 1); -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) { - active_remote_pwm_dimmer->fixed_color_index += add_value; - dgr_value = active_remote_pwm_dimmer->fixed_color_index; - } - else { -#endif - local_fixed_color_index += add_value; - dgr_value = local_fixed_color_index; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif - dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR; -#endif - ; - } - - else { - mqtt_trigger = (is_down_button ? 3 : 4); - } - } - - - if (mqtt_trigger) { - char topic[TOPSZ]; - sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); -#ifdef USE_PWM_DIMMER_REMOTE - if (active_remote_pwm_dimmer) { - snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/EVENT"), device_groups[power_button_index].group_name); - MqttPublish(topic); - } - else -#endif - MqttPublishPrefixTopic_P(CMND, PSTR("EVENT")); - } - - - if (dgr_item) { -#ifdef USE_DEVICE_GROUPS - DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT; -#ifdef USE_PWM_DIMMER_REMOTE - if (handle_tap && !active_remote_pwm_dimmer) -#else - if (handle_tap) -#endif - message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL); - SendDeviceGroupMessage(power_button_index, message_type, dgr_item, dgr_value); -#endif -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_remote_pwm_dimmer) -#endif - light_controller.saveSettings(); - } - - if (state_updated && Settings.flag3.hass_tele_on_power) { -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_remote_pwm_dimmer) -#endif - MqttPublishTeleState(); - } -} - - - - - -void CmndBriPreset(void) -{ - if (XdrvMailbox.data_len > 0) { - bool valid = true; - uint32_t value; - uint8_t parm[2]; - parm[0] = Settings.bri_preset_low; - parm[1] = Settings.bri_preset_high; - char * ptr = XdrvMailbox.data; - for (uint32_t i = 0; i < 2; i++) { - while (*ptr == ' ') ptr++; - if (*ptr == '+') { - if (parm[i] < 255) parm[i]++; - } - else if (*ptr == '-') { - if (parm[i] > 1) parm[i]--; - } - else { - value = strtoul(ptr, &ptr, 0); - if (value < 1 || value > 255) { - valid = false; - break; - } - parm[i] = value; - if (*ptr != ',') break; - } - ptr++; - } - if (valid && !*ptr) { - if (parm[0] < parm[1]) { - Settings.bri_preset_low = parm[0]; - Settings.bri_preset_high = parm[1]; - } else - { - Settings.bri_preset_low = parm[1]; - Settings.bri_preset_high = parm[0]; - } -#ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); -#endif - } - } - Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings.bri_preset_low, Settings.bri_preset_high); -} - -#ifdef USE_DEVICE_GROUPS -void CmndPWMDimmerPWMs(void) -{ - if (XdrvMailbox.data_len > 0 && XdrvMailbox.payload <= 5) { - Settings.pwm_dimmer_cfg.pwm_count = XdrvMailbox.payload - 1; - restart_flag = 2; - } - Response_P(PSTR("{\"" D_CMND_PWM_DIMMER_PWMS "\":%u}"), Settings.pwm_dimmer_cfg.pwm_count + 1); -} -#endif - - - - - -bool Xdrv35(uint8_t function) -{ - bool result = false; - - if (PWM_DIMMER != my_module_type) return result; - - switch (function) { - case FUNC_EVERY_SECOND: - - if (led_timeout_seconds && !--led_timeout_seconds) { - PWMDimmerSetBrightnessLeds(-2); - } - - - - - - if (global_state.data) - restore_powered_off_led_counter = 5; - else if (restore_powered_off_led_counter) { - PWMDimmerSetPoweredOffLed(); - restore_powered_off_led_counter--; - } - break; - - case FUNC_BUTTON_PRESSED: - - if (!XdrvMailbox.payload || button_pressed[XdrvMailbox.index]) { - uint32_t button_index = XdrvMailbox.index; - uint32_t now = millis(); - - - if (!XdrvMailbox.payload) { - - - - if (!button_pressed[button_index]) { - button_pressed[button_index] = true; - button_hold_time[button_index] = now + (button_index == power_button_index ? 500 : 250); - buttons_pressed++; - if (buttons_pressed > 1) multibutton_in_progress = true; - -#ifdef USE_PWM_DIMMER_REMOTE -# 759 "/workspace/Tasmota/tasmota/xdrv_35_pwm_dimmer.ino" - if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) { - power_button_index = button_index; - down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? gpio_pin[1] : gpio_pin[15]) - 32; - active_remote_pwm_dimmer = nullptr; - if (power_button_index || !first_device_group_is_local) - active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index]; - } -#endif - } - - - else if (button_hold_time[button_index] <= now) { - PWMDimmerHandleButton(button_index, true); - button_held[button_index] = true; - } - } - - - - else { - button_pressed[button_index] = false; - buttons_pressed--; - - - if (multibutton_in_progress || button_held[button_index]) { - PWMDimmerHandleButton(button_index, false); - - - - ignore_any_key_time = now + 500; - } - - - if (button_index == power_button_index) { - if (ignore_power_button) ignore_any_key_time = now + 500; - ignore_power_button = false; - button_tapped = false; - } - button_held[button_index] = false; - } - - - if (multibutton_in_progress) { - result = true; - if (buttons_pressed == 0) multibutton_in_progress = false; - } - } - break; - - case FUNC_ANY_KEY: - { - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; - if ((state == 2 || state == 10) && ignore_any_key_time < millis()) { - PWMDimmerHandleButton((XdrvMailbox.payload & 0xFF) - 1, false); - } - } - break; - -#ifdef USE_DEVICE_GROUPS - case FUNC_DEVICE_GROUP_ITEM: - PWMDimmerHandleDevGroupItem(); - break; -#endif - - case FUNC_COMMAND: - result = DecodeCommand(kPWMDimmerCommands, PWMDimmerCommand); - break; - - case FUNC_SET_DEVICE_POWER: - - - if (XdrvMailbox.index) { - PWMDimmerSetPower(); - - - power_button_increases_bri = (light_state.getBri() < 128); - } - - - - else - result = true; - break; - - case FUNC_PRE_INIT: - PWMModulePreInit(); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" -#ifdef USE_KEELOQ -# 30 "/workspace/Tasmota/tasmota/xdrv_36_keeloq.ino" -#define XDRV_36 36 - -#include "cc1101.h" -#include - -#define SYNC_WORD 199 - -#define Lowpulse 400 -#define Highpulse 800 - -const char kJaroliftCommands[] PROGMEM = "Keeloq|" - "SendRaw|SendButton|Set"; - -void (* const jaroliftCommand[])(void) PROGMEM = { - &CmndSendRaw, &CmdSendButton, &CmdSet}; - -CC1101 cc1101; - -struct JAROLIFT_DEVICE { - int device_key_msb = 0x0; - int device_key_lsb = 0x0; - uint64_t button = 0x0; - int disc = 0x0100; - uint32_t enc = 0x0; - uint64_t pack = 0; - int count = 0; - uint32_t serial = 0x0; - uint8_t port_tx; - uint8_t port_rx; -} jaroliftDevice; - -void CmdSet(void) -{ - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload > 0) { - char *p; - uint32_t i = 0; - uint32_t param[4] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { - param[i] = strtoul(str, nullptr, 0); - i++; - } - for (uint32_t i = 0; i < 3; i++) { - if (param[i] < 1) { param[i] = 1; } - } - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("params: %08x %08x %08x %08x"), param[0], param[1], param[2], param[3]); - Settings.keeloq_master_msb = param[0]; - Settings.keeloq_master_lsb = param[1]; - Settings.keeloq_serial = param[2]; - Settings.keeloq_count = param[3]; - - jaroliftDevice.serial = param[2]; - jaroliftDevice.count = param[3]; - - GenerateDeviceCryptKey(); - ResponseCmndDone(); - } else { - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); - } - } else { - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no param")); - } -} - -void GenerateDeviceCryptKey() -{ - Keeloq k(Settings.keeloq_master_msb, Settings.keeloq_master_lsb); - jaroliftDevice.device_key_msb = k.decrypt(jaroliftDevice.serial | 0x60000000L); - jaroliftDevice.device_key_lsb = k.decrypt(jaroliftDevice.serial | 0x20000000L); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("generated device keys: %08x %08x"), jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); -} - -void CmdSendButton(void) -{ - noInterrupts(); - entertx(); - - if (XdrvMailbox.data_len > 0) - { - if (XdrvMailbox.payload > 0) - { - jaroliftDevice.button = strtoul(XdrvMailbox.data, nullptr, 0); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("msb: %08x"), jaroliftDevice.device_key_msb); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("lsb: %08x"), jaroliftDevice.device_key_lsb); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("serial: %08x"), jaroliftDevice.serial); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("disc: %08x"), jaroliftDevice.disc); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("KLQ: count: %08x"), jaroliftDevice.count); - - CreateKeeloqPacket(); - jaroliftDevice.count++; - Settings.keeloq_count = jaroliftDevice.count; - - for(int repeat = 0; repeat <= 1; repeat++) - { - uint64_t bitsToSend = jaroliftDevice.pack; - digitalWrite(jaroliftDevice.port_tx, LOW); - delayMicroseconds(1150); - SendSyncPreamble(13); - delayMicroseconds(3500); - for(int i=72; i>0; i--) - { - SendBit(bitsToSend & 0x0000000000000001); - bitsToSend >>= 1; - } - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); - - delay(16); - } - } - } - - interrupts(); - enterrx(); - - ResponseCmndDone(); -} - -void SendBit(byte bitToSend) -{ - if (bitToSend==1) - { - digitalWrite(jaroliftDevice.port_tx, LOW); - delayMicroseconds(Lowpulse); - digitalWrite(jaroliftDevice.port_tx, HIGH); - delayMicroseconds(Highpulse); - } - else - { - digitalWrite(jaroliftDevice.port_tx, LOW); - delayMicroseconds(Highpulse); - digitalWrite(jaroliftDevice.port_tx, HIGH); - delayMicroseconds(Lowpulse); - } -} - -void CmndSendRaw(void) -{ - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("cmd send called at %d"), micros()); - noInterrupts(); - entertx(); - for(int repeat = 0; repeat <= 1; repeat++) - { - if (XdrvMailbox.data_len > 0) - { - digitalWrite(jaroliftDevice.port_tx, LOW); - delayMicroseconds(1150); - SendSyncPreamble(13); - delayMicroseconds(3500); - - for(int i=XdrvMailbox.data_len-1; i>=0; i--) - { - SendBit(XdrvMailbox.data[i] == '1'); - } - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); - - delay(16); - } - interrupts(); - } - enterrx(); - ResponseCmndDone(); -} - -void enterrx() { - unsigned char marcState = 0; - cc1101.setRxState(); - delay(2); - unsigned long rx_time = micros(); - while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x0D ) - { - if (micros() - rx_time > 50000) break; - } -} - -void entertx() { - unsigned char marcState = 0; - cc1101.setTxState(); - delay(2); - unsigned long rx_time = micros(); - while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x13 && 0x14 && 0x15) - { - if (micros() - rx_time > 50000) break; - } -} - -void SendSyncPreamble(int l) -{ - for (int i = 0; i < l; ++i) - { - digitalWrite(jaroliftDevice.port_tx, LOW); - delayMicroseconds(400); - digitalWrite(jaroliftDevice.port_tx, HIGH); - delayMicroseconds(380); - } -} - -void CreateKeeloqPacket() -{ - Keeloq k(jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); - unsigned int result = (jaroliftDevice.disc << 16) | jaroliftDevice.count; - jaroliftDevice.pack = (uint64_t)0; - jaroliftDevice.pack |= jaroliftDevice.serial & 0xfffffffL; - jaroliftDevice.pack |= (jaroliftDevice.button & 0xfL) << 28; - jaroliftDevice.pack <<= 32; - - jaroliftDevice.enc = k.encrypt(result); - jaroliftDevice.pack |= jaroliftDevice.enc; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack high: %08x"), jaroliftDevice.pack>>32); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack low: %08x"), jaroliftDevice.pack); -} - -void KeeloqInit() -{ - jaroliftDevice.port_tx = Pin(GPIO_CC1101_GDO2); - jaroliftDevice.port_rx = Pin(GPIO_CC1101_GDO0); - - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("cc1101.init()")); - delay(100); - cc1101.init(); - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("CC1101 done.")); - cc1101.setSyncWord(SYNC_WORD, false); - cc1101.setCarrierFreq(CFREQ_433); - cc1101.disableAddressCheck(); - - pinMode(jaroliftDevice.port_tx, OUTPUT); - pinMode(jaroliftDevice.port_rx, INPUT_PULLUP); - - jaroliftDevice.serial = Settings.keeloq_serial; - jaroliftDevice.count = Settings.keeloq_count; - GenerateDeviceCryptKey(); -} - - - - -bool Xdrv36(uint8_t function) -{ - if (!PinUsed(GPIO_CC1101_GDO0) || !PinUsed(GPIO_CC1101_GDO2)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_COMMAND: - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("calling command")); - result = DecodeCommand(kJaroliftCommands, jaroliftCommand); - break; - case FUNC_INIT: - KeeloqInit(); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("init done.")); - break; - } - - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" -#ifdef USE_LIGHT -#ifdef USE_SONOFF_D1 -# 35 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" -#define XDRV_37 37 - -struct SONOFFD1 { - uint8_t receive_len = 0; - uint8_t power = 255; - uint8_t dimmer = 255; -} SnfD1; - - - -void SonoffD1Received(void) -{ - if (serial_in_byte_counter < 8) { return; } - - uint8_t action = serial_in_buffer[6] & 1; - if (action != SnfD1.power) { - SnfD1.power = action; - - - - ExecuteCommandPower(1, action, SRC_SWITCH); - } - - uint8_t dimmer = serial_in_buffer[7]; - if (dimmer != SnfD1.dimmer) { - SnfD1.dimmer = dimmer; - - - - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), SnfD1.dimmer); - ExecuteCommand(scmnd, SRC_SWITCH); - } -# 79 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" -} - -bool SonoffD1SerialInput(void) -{ - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - SnfD1.receive_len = 7; - } - if (SnfD1.receive_len) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (6 == serial_in_byte_counter) { - SnfD1.receive_len += serial_in_byte; - } - if (serial_in_byte_counter == SnfD1.receive_len) { -# 102 "/workspace/Tasmota/tasmota/xdrv_37_sonoff_d1.ino" - AddLogSerial(LOG_LEVEL_DEBUG); - uint8_t crc = 0; - for (uint32_t i = 2; i < SnfD1.receive_len -1; i++) { - crc += serial_in_buffer[i]; - } - if (crc == serial_in_buffer[SnfD1.receive_len -1]) { - SonoffD1Received(); - SnfD1.receive_len = 0; - return true; - } - } - serial_in_byte = 0; - } - return false; -} - - - -void SonoffD1Send() -{ - - uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; - - buffer[6] = SnfD1.power; - buffer[7] = SnfD1.dimmer; - - for (uint32_t i = 0; i < sizeof(buffer); i++) { - if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } - Serial.write(buffer[i]); - } -} - -bool SonoffD1SendPower(void) -{ - uint8_t action = XdrvMailbox.index &1; - if (action != SnfD1.power) { - SnfD1.power = action; - - - - SonoffD1Send(); - } - return true; -} - -bool SonoffD1SendDimmer(void) -{ - uint8_t dimmer = LightGetDimmer(1); - dimmer = (dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : dimmer; - dimmer = (dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : dimmer; - if (dimmer != SnfD1.dimmer) { - SnfD1.dimmer = dimmer; - - - - SonoffD1Send(); - } - return true; -} - -bool SonoffD1ModuleSelected(void) -{ - SetSerial(9600, TS_SERIAL_8N1); - - devices_present++; - light_type = LT_SERIAL1; - - return true; -} - - - - - -bool Xdrv37(uint8_t function) -{ - bool result = false; - - if (SONOFF_D1 == my_module_type) { - switch (function) { - case FUNC_SERIAL: - result = SonoffD1SerialInput(); - break; - case FUNC_SET_DEVICE_POWER: - result = SonoffD1SendPower(); - break; - case FUNC_SET_CHANNELS: - result = SonoffD1SendDimmer(); - break; - case FUNC_MODULE_INIT: - result = SonoffD1ModuleSelected(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" -#ifdef USE_PING - -#define XDRV_38 38 - -#include "lwip/icmp.h" -#include "lwip/inet_chksum.h" -#include "lwip/raw.h" -#include "lwip/timeouts.h" - -const char kPingCommands[] PROGMEM = "|" - D_CMND_PING - ; - -void (* const PingCommand[])(void) PROGMEM = { - &CmndPing, - }; - -extern "C" { - - extern uint32 system_relative_time(uint32 time); - extern void ets_bzero(void *s, size_t n); - - const uint16_t Ping_ID = 0xAFAF; - const size_t Ping_data_size = 32; - const uint32_t Ping_timeout_ms = 1000; - const uint32_t Ping_coarse = 1000; - - typedef struct Ping_t { - uint32 ip; - Ping_t *next; - uint16_t seq_num; - uint16_t seqno; - uint8_t success_count; - uint8_t timeout_count; - uint8_t to_send_count; - uint32_t ping_time_sent; - uint32_t min_time; - uint32_t max_time; - uint32_t sum_time; - bool done; - bool fast; - String hostname; - } Ping_t; - - - Ping_t *ping_head = nullptr; - struct raw_pcb *t_ping_pcb = nullptr; - - - - - - - - Ping_t ICACHE_FLASH_ATTR * t_ping_find(uint32_t ip) { - Ping_t *ping = ping_head; - while (ping != nullptr) { - if (ping->ip == ip) { - return ping; - } - ping = ping->next; - } - return nullptr; - } -# 92 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" - void ICACHE_FLASH_ATTR t_ping_timeout(void* arg) { - Ping_t *ping = (Ping_t*) arg; - ping->timeout_count++; - } - - - - - - - void ICACHE_FLASH_ATTR t_ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len, Ping_t *ping) { - size_t data_len = len - sizeof(struct icmp_echo_hdr); - - ICMPH_TYPE_SET(iecho, ICMP_ECHO); - ICMPH_CODE_SET(iecho, 0); - iecho->chksum = 0; - iecho->id = Ping_ID; - ping->seq_num++; - if (ping->seq_num == 0x7fff) { ping->seq_num = 0; } - - iecho->seqno = htons(ping->seq_num); - - - for (uint32_t i = 0; i < data_len; i++) { - ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; - } - - iecho->chksum = inet_chksum(iecho, len); - } - - - - void ICACHE_FLASH_ATTR t_ping_send(struct raw_pcb *raw, Ping_t *ping) { - struct pbuf *p; - uint16_t ping_size = sizeof(struct icmp_echo_hdr) + Ping_data_size; - - ping->ping_time_sent = system_get_time(); - p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM); - if (!p) { return; } - if ((p->len == p->tot_len) && (p->next == nullptr)) { - ip_addr_t ping_target; - struct icmp_echo_hdr *iecho; - - ping_target.addr = ping->ip; - iecho = (struct icmp_echo_hdr *) p->payload; - - t_ping_prepare_echo(iecho, ping_size, ping); - raw_sendto(raw, p, &ping_target); - } - pbuf_free(p); - } - - - - - - static void ICACHE_FLASH_ATTR t_ping_coarse_tmr(void *arg) { - Ping_t *ping = (Ping_t*) arg; - if (ping->to_send_count > 0) { - ping->to_send_count--; - - t_ping_send(t_ping_pcb, ping); - - sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); - sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); - } else { - sys_untimeout(t_ping_coarse_tmr, ping); - ping->done = true; - } - } - - - - - - - - static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) { - Ping_t *ping = t_ping_find(addr->addr); - - if (nullptr == ping) { - return 0; - } - - if (pbuf_header( p, -PBUF_IP_HLEN)==0) { - struct icmp_echo_hdr *iecho; - iecho = (struct icmp_echo_hdr *)p->payload; - - if ((iecho->id == Ping_ID) && (iecho->seqno == htons(ping->seq_num)) && iecho->type == ICMP_ER) { - - if (iecho->seqno != ping->seqno){ - - sys_untimeout(t_ping_timeout, ping); - uint32_t delay = system_relative_time(ping->ping_time_sent); - delay /= 1000; - - ping->sum_time += delay; - if (delay < ping->min_time) { ping->min_time = delay; } - if (delay > ping->max_time) { ping->max_time = delay; } - - ping->success_count++; - ping->seqno = iecho->seqno; - if (ping->fast) { - sys_untimeout(t_ping_coarse_tmr, ping); - ping->done = true; - ping->to_send_count = 0; - } - } - - pbuf_free(p); - return 1; - } - } - - return 0; - } - - - - - - void t_ping_register_pcb(void) { - if (nullptr == t_ping_pcb) { - t_ping_pcb = raw_new(IP_PROTO_ICMP); - - raw_recv(t_ping_pcb, t_ping_recv, nullptr); - raw_bind(t_ping_pcb, IP_ADDR_ANY); - } - } - - - void t_ping_deregister_pcb(void) { - if (nullptr == ping_head) { - raw_remove(t_ping_pcb); - t_ping_pcb = nullptr; - } - } -# 237 "/workspace/Tasmota/tasmota/xdrv_38_ping.ino" - int32_t t_ping_start(const char *hostname, uint32_t count) { - IPAddress ipfull; - if (!WiFi.hostByName(hostname, ipfull)) { - return -2; - } - - uint32_t ip = ipfull; - if (0xFFFFFFFF == ip) { return -2; } - - - if (t_ping_find(ip)) { - return -1; - } - - Ping_t *ping = new Ping_t(); - if (0 == count) { - count = 4; - ping->fast = true; - } - ping->min_time = UINT32_MAX; - ping->ip = ip; - ping->to_send_count = count - 1; - ping->hostname = hostname; - - - ping->next = ping_head; - ping_head = ping; - - t_ping_register_pcb(); - t_ping_send(t_ping_pcb, ping); - - - sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); - sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); - - return 0; - } - -} - - -void PingResponsePoll(void) { - Ping_t *ping = ping_head; - Ping_t **prev_link = &ping_head; - - while (ping != nullptr) { - if (ping->done) { - uint32_t success = ping->success_count; - uint32_t ip = ping->ip; - - Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" - "\"Reachable\":%s" - ",\"IP\":\"%d.%d.%d.%d\"" - ",\"Success\":%d" - ",\"Timeout\":%d" - ",\"MinTime\":%d" - ",\"MaxTime\":%d" - ",\"AvgTime\":%d" - "}}}"), - ping->hostname.c_str(), - success ? "true" : "false", - ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, - success, - ping->timeout_count, - success ? ping->min_time : 0, - ping->max_time, - success ? ping->sum_time / success : 0 - ); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); - - - *prev_link = ping->next; - - Ping_t *ping_to_delete = ping; - ping = ping->next; - delete ping_to_delete; - } else { - prev_link = &ping->next; - ping = ping->next; - } - } -} - - - - - -void CmndPing(void) { - uint32_t count = XdrvMailbox.index; - - RemoveSpace(XdrvMailbox.data); - if (count > 10) { count = 8; } - - int32_t res = t_ping_start(XdrvMailbox.data, count); - if (0 == res) { - ResponseCmndDone(); - } else if (-1 == res) { - ResponseCmndChar_P(PSTR("Ping already ongoing for this IP")); - } else { - Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" - "\"Reachable\":false" - ",\"IP\":\"\"" - ",\"Success\":false" - "}}}"), - XdrvMailbox.data - ); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); - ResponseCmndChar_P(PSTR("Unable to resolve IP address")); - } -} - - - - - - -bool Xdrv38(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - PingResponsePoll(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kPingCommands, PingCommand); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" -#ifdef USE_THERMOSTAT - -#define XDRV_39 39 -# 31 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" -#ifdef DEBUG_THERMOSTAT -#define DOMOTICZ_MAX_IDX 4 -#define DOMOTICZ_IDX1 791 -#define DOMOTICZ_IDX2 792 -#define DOMOTICZ_IDX3 799 -#define DOMOTICZ_IDX4 800 -#define DOMOTICZ_IDX5 801 -#endif - - -#define D_CMND_THERMOSTATMODESET "ThermostatModeSet" -#define D_CMND_CLIMATEMODESET "ClimateModeSet" -#define D_CMND_TEMPFROSTPROTECTSET "TempFrostProtectSet" -#define D_CMND_CONTROLLERMODESET "ControllerModeSet" -#define D_CMND_INPUTSWITCHSET "InputSwitchSet" -#define D_CMND_INPUTSWITCHUSE "InputSwitchUse" -#define D_CMND_OUTPUTRELAYSET "OutputRelaySet" -#define D_CMND_TIMEALLOWRAMPUPSET "TimeAllowRampupSet" -#define D_CMND_TEMPFORMATSET "TempFormatSet" -#define D_CMND_TEMPMEASUREDSET "TempMeasuredSet" -#define D_CMND_TEMPTARGETSET "TempTargetSet" -#define D_CMND_TEMPMEASUREDGRDREAD "TempMeasuredGrdRead" -#define D_CMND_TEMPSENSNUMBERSET "TempSensNumberSet" -#define D_CMND_SENSORINPUTSET "SensorInputSet" -#define D_CMND_STATEEMERGENCYSET "StateEmergencySet" -#define D_CMND_TIMEMANUALTOAUTOSET "TimeManualToAutoSet" -#define D_CMND_TIMEONLIMITSET "TimeOnLimitSet" -#define D_CMND_PROPBANDSET "PropBandSet" -#define D_CMND_TIMERESETSET "TimeResetSet" -#define D_CMND_TIMEPICYCLESET "TimePiCycleSet" -#define D_CMND_TEMPANTIWINDUPRESETSET "TempAntiWindupResetSet" -#define D_CMND_TEMPHYSTSET "TempHystSet" -#ifdef USE_PI_AUTOTUNING -#define D_CMND_PERFLEVELAUTOTUNE "PerfLevelAutotune" -#endif -#define D_CMND_TIMEMAXACTIONSET "TimeMaxActionSet" -#define D_CMND_TIMEMINACTIONSET "TimeMinActionSet" -#define D_CMND_TIMEMINTURNOFFACTIONSET "TimeMinTurnoffActionSet" -#define D_CMND_TEMPRUPDELTINSET "TempRupDeltInSet" -#define D_CMND_TEMPRUPDELTOUTSET "TempRupDeltOutSet" -#define D_CMND_TIMERAMPUPMAXSET "TimeRampupMaxSet" -#define D_CMND_TIMERAMPUPCYCLESET "TimeRampupCycleSet" -#define D_CMND_TEMPRAMPUPPIACCERRSET "TempRampupPiAccErrSet" -#define D_CMND_TIMEPIPROPORTREAD "TimePiProportRead" -#define D_CMND_TIMEPIINTEGRREAD "TimePiIntegrRead" -#define D_CMND_TIMESENSLOSTSET "TimeSensLostSet" -#define D_CMND_DIAGNOSTICMODESET "DiagnosticModeSet" -#define D_CMND_CTRDUTYCYCLEREAD "CtrDutyCycleRead" -#define D_CMND_ENABLEOUTPUTSET "EnableOutputSet" - -enum ThermostatModes { THERMOSTAT_OFF, THERMOSTAT_AUTOMATIC_OP, THERMOSTAT_MANUAL_OP, THERMOSTAT_MODES_MAX }; -#ifdef USE_PI_AUTOTUNING -enum ControllerModes { CTR_HYBRID, CTR_PI, CTR_RAMP_UP, CTR_PI_AUTOTUNE, CTR_MODES_MAX }; -enum ControllerHybridPhases { CTR_HYBRID_RAMP_UP, CTR_HYBRID_PI, CTR_HYBRID_PI_AUTOTUNE }; -enum AutotuneStates { AUTOTUNE_OFF, AUTOTUNE_ON, AUTOTUNE_MAX }; -enum AutotunePerformanceParam { AUTOTUNE_PERF_FAST, AUTOTUNE_PERF_NORMAL, AUTOTUNE_PERF_SLOW, AUTOTUNE_PERF_MAX }; -#else -enum ControllerModes { CTR_HYBRID, CTR_PI, CTR_RAMP_UP, CTR_MODES_MAX }; -enum ControllerHybridPhases { CTR_HYBRID_RAMP_UP, CTR_HYBRID_PI }; -#endif -enum ClimateModes { CLIMATE_HEATING, CLIMATE_COOLING, CLIMATE_MODES_MAX }; -enum InterfaceStates { IFACE_OFF, IFACE_ON }; -enum InputUsage { INPUT_NOT_USED, INPUT_USED }; -enum CtrCycleStates { CYCLE_OFF, CYCLE_ON }; -enum EmergencyStates { EMERGENCY_OFF, EMERGENCY_ON }; -enum SensorType { SENSOR_MQTT, SENSOR_LOCAL, SENSOR_MAX }; -enum TempFormat { TEMP_CELSIUS, TEMP_FAHRENHEIT }; -enum TempConvType { TEMP_CONV_ABSOLUTE, TEMP_CONV_RELATIVE }; -enum DiagnosticModes { DIAGNOSTIC_OFF, DIAGNOSTIC_ON }; -enum ThermostatSupportedInputSwitches { - THERMOSTAT_INPUT_NONE, - THERMOSTAT_INPUT_SWT1 = 1, - THERMOSTAT_INPUT_SWT2, - THERMOSTAT_INPUT_SWT3, - THERMOSTAT_INPUT_SWT4, - THERMOSTAT_INPUT_SWT5, - THERMOSTAT_INPUT_SWT6, - THERMOSTAT_INPUT_SWT7, - THERMOSTAT_INPUT_SWT8 -}; -enum ThermostatSupportedOutputRelays { - THERMOSTAT_OUTPUT_NONE, - THERMOSTAT_OUTPUT_REL1 = 1, - THERMOSTAT_OUTPUT_REL2, - THERMOSTAT_OUTPUT_REL3, - THERMOSTAT_OUTPUT_REL4, - THERMOSTAT_OUTPUT_REL5, - THERMOSTAT_OUTPUT_REL6, - THERMOSTAT_OUTPUT_REL7, - THERMOSTAT_OUTPUT_REL8 -}; - -typedef union { - uint32_t data; - struct { - uint32_t thermostat_mode : 2; - uint32_t controller_mode : 2; - uint32_t climate_mode : 1; - uint32_t sensor_alive : 1; - uint32_t sensor_type : 1; - uint32_t temp_format : 1; - uint32_t command_output : 1; - uint32_t status_output : 1; - uint32_t status_input : 1; - uint32_t use_input : 1; - uint32_t phase_hybrid_ctr : 2; - uint32_t status_cycle_active : 1; - uint32_t counter_seconds : 6; - uint32_t output_relay_number : 4; - uint32_t input_switch_number : 3; - uint32_t enable_output : 1; -#ifdef USE_PI_AUTOTUNING - uint32_t autotune_flag : 1; - uint32_t autotune_perf_mode : 2; -#else - uint32_t free : 3; -#endif - }; -} ThermostatStateBitfield; - -typedef union { - uint8_t data; - struct { - uint8_t state_emergency : 1; - uint8_t diagnostic_mode : 1; - uint8_t output_inconsist_ctr : 2; - }; -} ThermostatDiagBitfield; - -#ifdef DEBUG_THERMOSTAT -const char DOMOTICZ_MES[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\"}"; -uint16_t Domoticz_Virtual_Switches[DOMOTICZ_MAX_IDX] = { DOMOTICZ_IDX1, DOMOTICZ_IDX3, DOMOTICZ_IDX4, DOMOTICZ_IDX5 }; -#endif - -const char kThermostatCommands[] PROGMEM = "|" D_CMND_THERMOSTATMODESET "|" D_CMND_CLIMATEMODESET "|" - D_CMND_TEMPFROSTPROTECTSET "|" D_CMND_CONTROLLERMODESET "|" D_CMND_INPUTSWITCHSET "|" D_CMND_INPUTSWITCHUSE "|" - D_CMND_OUTPUTRELAYSET "|" D_CMND_TIMEALLOWRAMPUPSET "|" D_CMND_TEMPFORMATSET "|" D_CMND_TEMPMEASUREDSET "|" - D_CMND_TEMPTARGETSET "|" D_CMND_TEMPMEASUREDGRDREAD "|" D_CMND_SENSORINPUTSET "|" D_CMND_STATEEMERGENCYSET "|" - D_CMND_TIMEMANUALTOAUTOSET "|" D_CMND_PROPBANDSET "|" D_CMND_TIMERESETSET "|" D_CMND_TIMEPICYCLESET "|" -#ifdef USE_PI_AUTOTUNING - D_CMND_TEMPANTIWINDUPRESETSET "|" D_CMND_TEMPHYSTSET "|" D_CMND_PERFLEVELAUTOTUNE "|" D_CMND_TIMEMAXACTIONSET "|" -#else - D_CMND_TEMPANTIWINDUPRESETSET "|" D_CMND_TEMPHYSTSET "|" D_CMND_TIMEMAXACTIONSET "|" -#endif - D_CMND_TIMEMINACTIONSET "|" D_CMND_TIMEMINTURNOFFACTIONSET "|" D_CMND_TEMPRUPDELTINSET "|" D_CMND_TEMPRUPDELTOUTSET "|" - D_CMND_TIMERAMPUPMAXSET "|" D_CMND_TIMERAMPUPCYCLESET "|" D_CMND_TEMPRAMPUPPIACCERRSET "|" D_CMND_TIMEPIPROPORTREAD "|" - D_CMND_TIMEPIINTEGRREAD "|" D_CMND_TIMESENSLOSTSET "|" D_CMND_DIAGNOSTICMODESET "|" D_CMND_CTRDUTYCYCLEREAD "|" - D_CMND_ENABLEOUTPUTSET; - -void (* const ThermostatCommand[])(void) PROGMEM = { - &CmndThermostatModeSet, &CmndClimateModeSet, &CmndTempFrostProtectSet, &CmndControllerModeSet, &CmndInputSwitchSet, - &CmndInputSwitchUse, &CmndOutputRelaySet, &CmndTimeAllowRampupSet, &CmndTempFormatSet, &CmndTempMeasuredSet, - &CmndTempTargetSet, &CmndTempMeasuredGrdRead, &CmndSensorInputSet, &CmndStateEmergencySet, &CmndTimeManualToAutoSet, - &CmndPropBandSet, &CmndTimeResetSet, &CmndTimePiCycleSet, &CmndTempAntiWindupResetSet, &CmndTempHystSet, -#ifdef USE_PI_AUTOTUNING - &CmndPerfLevelAutotune, &CmndTimeMaxActionSet, &CmndTimeMinActionSet, &CmndTimeMinTurnoffActionSet, &CmndTempRupDeltInSet, -#else - &CmndTimeMaxActionSet, &CmndTimeMinActionSet, &CmndTimeMinTurnoffActionSet, &CmndTempRupDeltInSet, -#endif - &CmndTempRupDeltOutSet, &CmndTimeRampupMaxSet, &CmndTimeRampupCycleSet, &CmndTempRampupPiAccErrSet, - &CmndTimePiProportRead, &CmndTimePiIntegrRead, &CmndTimeSensLostSet, &CmndDiagnosticModeSet, &CmndCtrDutyCycleRead, - &CmndEnableOutputSet }; - -struct THERMOSTAT { - ThermostatStateBitfield status; - uint32_t timestamp_temp_measured_update = 0; - uint32_t timestamp_temp_meas_change_update = 0; - uint32_t timestamp_output_off = 0; - uint32_t timestamp_input_on = 0; - uint32_t time_thermostat_total = 0; - uint32_t time_ctr_checkpoint = 0; - uint32_t time_ctr_changepoint = 0; - int32_t temp_measured_gradient = 0; - int16_t temp_target_level = THERMOSTAT_TEMP_INIT; - int16_t temp_target_level_ctr = THERMOSTAT_TEMP_INIT; - int16_t temp_pi_accum_error = 0; - int16_t temp_pi_error = 0; - int32_t time_proportional_pi; - int32_t time_integral_pi; - int32_t time_total_pi; - uint16_t kP_pi = 0; - uint16_t kI_pi = 0; - int32_t temp_rampup_meas_gradient = 0; - uint32_t timestamp_rampup_start = 0; - uint32_t time_rampup_deadtime = 0; - uint32_t time_rampup_nextcycle = 0; - int16_t temp_measured = 0; - int16_t temp_rampup_output_off = 0; - uint8_t time_output_delay = THERMOSTAT_TIME_OUTPUT_DELAY; - uint8_t counter_rampup_cycles = 0; - uint8_t temp_rampup_pi_acc_error = THERMOSTAT_TEMP_PI_RAMPUP_ACC_E; - uint8_t temp_rampup_delta_out = THERMOSTAT_TEMP_RAMPUP_DELTA_OUT; - uint8_t temp_rampup_delta_in = THERMOSTAT_TEMP_RAMPUP_DELTA_IN; - uint8_t val_prop_band = THERMOSTAT_PROP_BAND; - int16_t temp_rampup_start = 0; - int16_t temp_rampup_cycle = 0; - uint16_t time_rampup_max = THERMOSTAT_TIME_RAMPUP_MAX; - uint16_t time_rampup_cycle = THERMOSTAT_TIME_RAMPUP_CYCLE; - uint16_t time_allow_rampup = THERMOSTAT_TIME_ALLOW_RAMPUP; - uint16_t time_sens_lost = THERMOSTAT_TIME_SENS_LOST; - uint16_t time_manual_to_auto = THERMOSTAT_TIME_MANUAL_TO_AUTO; - uint32_t time_reset = THERMOSTAT_TIME_RESET; - uint16_t time_pi_cycle = THERMOSTAT_TIME_PI_CYCLE; - uint16_t time_max_action = THERMOSTAT_TIME_MAX_ACTION; - uint16_t time_min_action = THERMOSTAT_TIME_MIN_ACTION; - uint16_t time_min_turnoff_action = THERMOSTAT_TIME_MIN_TURNOFF_ACTION; - uint8_t temp_reset_anti_windup = THERMOSTAT_TEMP_RESET_ANTI_WINDUP; - int8_t temp_hysteresis = THERMOSTAT_TEMP_HYSTERESIS; - uint8_t temp_frost_protect = THERMOSTAT_TEMP_FROST_PROTECT; - ThermostatDiagBitfield diag; -#ifdef USE_PI_AUTOTUNING - uint8_t dutycycle_step_autotune = THERMOSTAT_DUTYCYCLE_AUTOTUNE; - uint8_t peak_ctr = 0; - uint8_t temp_band_no_peak_det = THERMOSTAT_TEMP_BAND_NO_PEAK_DET; - uint8_t val_prop_band_atune = 0; - uint32_t time_reset_atune = 0; - uint16_t pU_pi_atune = 0; - uint16_t kU_pi_atune = 0; - uint16_t kP_pi_atune = 0; - uint16_t kI_pi_atune = 0; - int16_t temp_peaks_atune[THERMOSTAT_PEAKNUMBER_AUTOTUNE]; - int16_t temp_abs_max_atune; - int16_t temp_abs_min_atune; - uint16_t time_peak_timestamps_atune[THERMOSTAT_PEAKNUMBER_AUTOTUNE]; - uint16_t time_std_dev_peak_det_ok = THERMOSTAT_TIME_STD_DEV_PEAK_DET_OK; -#endif -} Thermostat[THERMOSTAT_CONTROLLER_OUTPUTS]; - - - -void ThermostatInit(uint8_t ctr_output) -{ - - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; - Thermostat[ctr_output].status.controller_mode = CTR_HYBRID; - Thermostat[ctr_output].status.climate_mode = CLIMATE_HEATING; - Thermostat[ctr_output].status.sensor_alive = IFACE_OFF; - Thermostat[ctr_output].status.sensor_type = SENSOR_MQTT; - Thermostat[ctr_output].status.temp_format = TEMP_CELSIUS; - Thermostat[ctr_output].status.command_output = IFACE_OFF; - Thermostat[ctr_output].status.status_output = IFACE_OFF; - Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; - Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; - Thermostat[ctr_output].diag.state_emergency = EMERGENCY_OFF; - Thermostat[ctr_output].status.counter_seconds = 0; - Thermostat[ctr_output].status.output_relay_number = (THERMOSTAT_RELAY_NUMBER + ctr_output); - Thermostat[ctr_output].status.input_switch_number = (THERMOSTAT_SWITCH_NUMBER + ctr_output); - Thermostat[ctr_output].status.use_input = INPUT_NOT_USED; - Thermostat[ctr_output].status.enable_output = IFACE_ON; - Thermostat[ctr_output].diag.output_inconsist_ctr = 0; - Thermostat[ctr_output].diag.diagnostic_mode = DIAGNOSTIC_ON; -#ifdef USE_PI_AUTOTUNING - Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; - Thermostat[ctr_output].status.autotune_perf_mode = AUTOTUNE_PERF_FAST; -#endif - - if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { - ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT); - } -} - -bool ThermostatMinuteCounter(uint8_t ctr_output) -{ - bool result = false; - Thermostat[ctr_output].status.counter_seconds++; - - if ((Thermostat[ctr_output].status.counter_seconds % 60) == 0) { - result = true; - Thermostat[ctr_output].status.counter_seconds = 0; - } - return result; -} - -inline bool ThermostatSwitchIdValid(uint8_t switchId) -{ - return (switchId >= THERMOSTAT_INPUT_SWT1 && switchId <= THERMOSTAT_INPUT_SWT8); -} - -inline bool ThermostatRelayIdValid(uint8_t relayId) -{ - return (relayId >= THERMOSTAT_OUTPUT_REL1 && relayId <= THERMOSTAT_OUTPUT_REL8); -} - -uint8_t ThermostatInputStatus(uint8_t input_switch) -{ - bool ifId = ThermostatSwitchIdValid(input_switch); - uint8_t value = 0; - if(ifId) { - value = SwitchGetVirtual(ifId - THERMOSTAT_INPUT_SWT1); - } - return value; -} - -uint8_t ThermostatOutputStatus(uint8_t output_switch) -{ - return (uint8_t)bitRead(power, (output_switch - 1)); -} - -int16_t ThermostatCelsiusToFahrenheit(const int32_t deg, uint8_t conv_type) { - int32_t value; - value = (int32_t)(((int32_t)deg * (int32_t)90) / (int32_t)50); - if (conv_type == TEMP_CONV_ABSOLUTE) { - value += (int32_t)320; - } - - - if (value <= (int32_t)(INT16_MIN)) { - value = (int32_t)(INT16_MIN); - } - else if (value >= (int32_t)INT16_MAX) { - value = (int32_t)INT16_MAX; - } - - return (int16_t)value; -} - -int16_t ThermostatFahrenheitToCelsius(const int32_t deg, uint8_t conv_type) { - int16_t offset = 0; - int32_t value; - if (conv_type == TEMP_CONV_ABSOLUTE) { - offset = 320; - } - - value = (int32_t)(((deg - (int32_t)offset) * (int32_t)50) / (int32_t)90); - - - if (value <= (int32_t)(INT16_MIN)) { - value = (int32_t)(INT16_MIN); - } - else if (value >= (int32_t)INT16_MAX) { - value = (int32_t)INT16_MAX; - } - - return (int16_t)value; -} - -void ThermostatSignalPreProcessingSlow(uint8_t ctr_output) -{ - - if ((uptime - Thermostat[ctr_output].timestamp_temp_measured_update) > ((uint32_t)Thermostat[ctr_output].time_sens_lost * 60)) { - Thermostat[ctr_output].status.sensor_alive = IFACE_OFF; - Thermostat[ctr_output].temp_measured_gradient = 0; - Thermostat[ctr_output].temp_measured = 0; - } -} - -void ThermostatSignalPostProcessingSlow(uint8_t ctr_output) -{ - - if ((Thermostat[ctr_output].status.status_output != Thermostat[ctr_output].status.command_output) - &&(Thermostat[ctr_output].status.enable_output == IFACE_ON)) { - Thermostat[ctr_output].diag.output_inconsist_ctr++; - } - else { - Thermostat[ctr_output].diag.output_inconsist_ctr = 0; - } -} - -void ThermostatSignalProcessingFast(uint8_t ctr_output) -{ - - Thermostat[ctr_output].status.status_input = (uint32_t)ThermostatInputStatus(Thermostat[ctr_output].status.input_switch_number); - - if (Thermostat[ctr_output].status.status_input == IFACE_ON) { - Thermostat[ctr_output].timestamp_input_on = uptime; - } - - Thermostat[ctr_output].status.status_output = (uint32_t)ThermostatOutputStatus(Thermostat[ctr_output].status.output_relay_number); -} - -void ThermostatCtrState(uint8_t ctr_output) -{ -#ifdef USE_PI_AUTOTUNING - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); -#endif - - switch (Thermostat[ctr_output].status.controller_mode) { - - case CTR_HYBRID: - ThermostatHybridCtrPhase(ctr_output); - break; - - case CTR_PI: -#ifdef USE_PI_AUTOTUNING - - - - - if ((Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_ON) - &&(Thermostat[ctr_output].temp_measured == Thermostat[ctr_output].temp_target_level) - && ((flag_heating && (Thermostat[ctr_output].temp_measured_gradient < 0)) - ||(!flag_heating && (Thermostat[ctr_output].temp_measured_gradient > 0)))) - { - Thermostat[ctr_output].status.controller_mode = CTR_PI_AUTOTUNE; - ThermostatPeakDetectorInit(ctr_output); - } -#endif - break; - - case CTR_RAMP_UP: - break; -#ifdef USE_PI_AUTOTUNING - - case CTR_PI_AUTOTUNE: - - - if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) - { - Thermostat[ctr_output].status.controller_mode = CTR_PI; - } - break; -#endif - } -} - -void ThermostatHybridCtrPhase(uint8_t ctr_output) -{ - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - if (Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) { - switch (Thermostat[ctr_output].status.phase_hybrid_ctr) { - - case CTR_HYBRID_RAMP_UP: - - - if((Thermostat[ctr_output].time_ctr_checkpoint != 0) - && (uptime >= Thermostat[ctr_output].time_ctr_checkpoint)) { - - Thermostat[ctr_output].time_ctr_checkpoint = 0; - - Thermostat[ctr_output].time_ctr_changepoint = 0; - - Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; - } - break; - - case CTR_HYBRID_PI: - - - - - if (((uptime - Thermostat[ctr_output].timestamp_output_off) > (60 * (uint32_t)Thermostat[ctr_output].time_allow_rampup)) - && (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) - && ( ( (Thermostat[ctr_output].temp_target_level - Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_delta_in) - && (flag_heating)) - || ( (Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_target_level > Thermostat[ctr_output].temp_rampup_delta_in) - && (!flag_heating)))) { - Thermostat[ctr_output].timestamp_rampup_start = uptime; - Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; - Thermostat[ctr_output].temp_rampup_meas_gradient = 0; - Thermostat[ctr_output].time_rampup_deadtime = 0; - Thermostat[ctr_output].counter_rampup_cycles = 1; - Thermostat[ctr_output].time_ctr_changepoint = 0; - Thermostat[ctr_output].time_ctr_checkpoint = 0; - Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_RAMP_UP; - } -#ifdef USE_PI_AUTOTUNING - - - - - if ((Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_ON) - &&(Thermostat[ctr_output].temp_measured == Thermostat[ctr_output].temp_target_level) - && ((flag_heating && (Thermostat[ctr_output].temp_measured_gradient < 0)) - ||(!flag_heating && (Thermostat[ctr_output].temp_measured_gradient > 0)))) - { - Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI_AUTOTUNE; - ThermostatPeakDetectorInit(ctr_output); - } -#endif - break; -#ifdef USE_PI_AUTOTUNING - - case CTR_HYBRID_PI_AUTOTUNE: - - - if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) - { - Thermostat[ctr_output].status.phase_hybrid_ctr = CTR_HYBRID_PI; - } - break; -#endif - } - } -#ifdef DEBUG_THERMOSTAT - ThermostatVirtualSwitchCtrState(ctr_output); -#endif -} - -bool ThermostatStateAutoToManual(uint8_t ctr_output) -{ - bool change_state = false; - - - - - if ((Thermostat[ctr_output].status.use_input == INPUT_USED) - &&((Thermostat[ctr_output].status.status_input == IFACE_ON) - || (Thermostat[ctr_output].status.sensor_alive == IFACE_OFF))) { - change_state = true; - } - return change_state; -} - -bool ThermostatStateManualToAuto(uint8_t ctr_output) -{ - bool change_state = false; - - - - - - if ((Thermostat[ctr_output].status.status_input == IFACE_OFF) - &&(Thermostat[ctr_output].status.sensor_alive == IFACE_ON) - && ((uptime - Thermostat[ctr_output].timestamp_input_on) > ((uint32_t)Thermostat[ctr_output].time_manual_to_auto * 60))) { - change_state = true; - } - return change_state; -} - -void ThermostatEmergencyShutdown(uint8_t ctr_output) -{ - - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; - Thermostat[ctr_output].status.command_output = IFACE_OFF; - if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { - ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output); - } -} - -void ThermostatState(uint8_t ctr_output) -{ - switch (Thermostat[ctr_output].status.thermostat_mode) { - - case THERMOSTAT_OFF: - - break; - - case THERMOSTAT_AUTOMATIC_OP: - if (ThermostatStateAutoToManual(ctr_output)) { - - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_MANUAL_OP; - } - ThermostatCtrState(ctr_output); - break; - - case THERMOSTAT_MANUAL_OP: - if (ThermostatStateManualToAuto(ctr_output)) { - - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_AUTOMATIC_OP; - } - break; - } -} - -void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command) -{ - - - - if ((command == IFACE_ON) - && (Thermostat[ctr_output].status.status_output == IFACE_OFF)) { - - if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { - ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_ON, SRC_THERMOSTAT); - } - - Thermostat[ctr_output].status.status_output = IFACE_ON; -#ifdef DEBUG_THERMOSTAT - ThermostatVirtualSwitch(ctr_output); -#endif - } - - - - else if ((command == IFACE_OFF) && (Thermostat[ctr_output].status.status_output == IFACE_ON)) { - - if (Thermostat[ctr_output].status.enable_output == IFACE_ON) { - ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT); - } - - Thermostat[ctr_output].timestamp_output_off = uptime; - Thermostat[ctr_output].status.status_output = IFACE_OFF; -#ifdef DEBUG_THERMOSTAT - ThermostatVirtualSwitch(ctr_output); -#endif - } -} - -void ThermostatCalculatePI(uint8_t ctr_output) -{ - - - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - int32_t aux_temp_error; - - - aux_temp_error = (int32_t)(Thermostat[ctr_output].temp_target_level_ctr - Thermostat[ctr_output].temp_measured) * 10; - - - if (Thermostat[ctr_output].status.climate_mode == CLIMATE_COOLING) { - aux_temp_error *= -1; - } - - - if (aux_temp_error <= (int32_t)(INT16_MIN)) { - Thermostat[ctr_output].temp_pi_error = (int16_t)(INT16_MIN); - } - else if (aux_temp_error >= (int32_t)INT16_MAX) { - Thermostat[ctr_output].temp_pi_error = (int16_t)INT16_MAX; - } - else { - Thermostat[ctr_output].temp_pi_error = (int16_t)aux_temp_error; - } - - - Thermostat[ctr_output].kP_pi = 100 / (uint16_t)(Thermostat[ctr_output].val_prop_band); - - Thermostat[ctr_output].time_proportional_pi = ((int32_t)(Thermostat[ctr_output].temp_pi_error * (int16_t)Thermostat[ctr_output].kP_pi) * ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) / 10000; - - - - - - if ((Thermostat[ctr_output].time_proportional_pi < abs(((int32_t)Thermostat[ctr_output].time_min_action * 60))) - && (Thermostat[ctr_output].time_proportional_pi > 0)) { - Thermostat[ctr_output].time_proportional_pi = ((int32_t)Thermostat[ctr_output].time_min_action * 60); - } - - if (Thermostat[ctr_output].time_proportional_pi < 0) { - Thermostat[ctr_output].time_proportional_pi = 0; - } - else if (Thermostat[ctr_output].time_proportional_pi > ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { - Thermostat[ctr_output].time_proportional_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); - } - - - Thermostat[ctr_output].kI_pi = (uint16_t)((((uint32_t)Thermostat[ctr_output].kP_pi * (uint32_t)Thermostat[ctr_output].time_pi_cycle * 6000)) / (uint32_t)Thermostat[ctr_output].time_reset); - - - - - if (abs((Thermostat[ctr_output].temp_pi_error) / 10) > Thermostat[ctr_output].temp_reset_anti_windup) { - Thermostat[ctr_output].time_integral_pi = 0; - Thermostat[ctr_output].temp_pi_accum_error = 0; - } - - - - else { -# 688 "/workspace/Tasmota/tasmota/xdrv_39_thermostat.ino" - aux_temp_error = (int32_t)Thermostat[ctr_output].temp_pi_accum_error + (int32_t)Thermostat[ctr_output].temp_pi_error; - - - if (aux_temp_error <= (int32_t)INT16_MIN) { - Thermostat[ctr_output].temp_pi_accum_error = INT16_MIN; - } - else if (aux_temp_error >= (int32_t)INT16_MAX) { - Thermostat[ctr_output].temp_pi_accum_error = INT16_MAX; - } - else { - Thermostat[ctr_output].temp_pi_accum_error = (int16_t)aux_temp_error; - } - - - - - if ( (Thermostat[ctr_output].temp_pi_error >= 0) - && (abs((Thermostat[ctr_output].temp_pi_error) / 10) <= (int16_t)Thermostat[ctr_output].temp_hysteresis) - && ( ((Thermostat[ctr_output].temp_measured_gradient > 0) - && (flag_heating)) - || ( (Thermostat[ctr_output].temp_measured_gradient < 0) - && (!flag_heating)))) { - - Thermostat[ctr_output].temp_pi_accum_error *= 0.8; - } - - - else if ((Thermostat[ctr_output].temp_pi_error < 0) - && ( ((Thermostat[ctr_output].temp_measured_gradient > 0) - && (flag_heating)) - || ( (Thermostat[ctr_output].temp_measured_gradient < 0) - && (!flag_heating)))) { - - Thermostat[ctr_output].temp_pi_accum_error *= 0.8; - } - - - if (Thermostat[ctr_output].temp_pi_accum_error < 0) { - Thermostat[ctr_output].temp_pi_accum_error = 0; - } - - - Thermostat[ctr_output].time_integral_pi = (((int32_t)Thermostat[ctr_output].temp_pi_accum_error * (int32_t)Thermostat[ctr_output].kI_pi) * (int32_t)((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60)) / 1000000; - - - - - if (Thermostat[ctr_output].time_integral_pi > ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { - Thermostat[ctr_output].time_integral_pi = ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); - } - } - - - Thermostat[ctr_output].time_total_pi = Thermostat[ctr_output].time_proportional_pi + Thermostat[ctr_output].time_integral_pi; - - - - - if (Thermostat[ctr_output].time_total_pi >= ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60)) { - - Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); - } - else if (Thermostat[ctr_output].time_total_pi < 0) { - Thermostat[ctr_output].time_total_pi = 0; - } - - - - if (Thermostat[ctr_output].temp_pi_error <= 0) { - - if ((abs((Thermostat[ctr_output].temp_pi_error) / 10) > Thermostat[ctr_output].temp_hysteresis) - || ( ((Thermostat[ctr_output].temp_measured_gradient >= 0) - && (flag_heating)) - || ( (Thermostat[ctr_output].temp_measured_gradient <= 0) - && (!flag_heating)))){ - Thermostat[ctr_output].time_total_pi = 0; - } - } - - - - - else if ((Thermostat[ctr_output].temp_pi_error > 0) - && (abs((Thermostat[ctr_output].temp_pi_error) / 10) <= Thermostat[ctr_output].temp_hysteresis) - && (((Thermostat[ctr_output].temp_measured_gradient > 0) - && (flag_heating)) - || ( (Thermostat[ctr_output].temp_measured_gradient < 0) - && (!flag_heating)))) { - Thermostat[ctr_output].time_total_pi = 0; - } - - - - if ((Thermostat[ctr_output].time_total_pi <= abs(((uint32_t)Thermostat[ctr_output].time_min_action * 60))) - && (Thermostat[ctr_output].time_total_pi != 0)) { - Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_min_action * 60); - } - - - else if (Thermostat[ctr_output].time_total_pi > abs(((int32_t)Thermostat[ctr_output].time_max_action * 60))) { - Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_max_action * 60); - } - - else if (Thermostat[ctr_output].time_total_pi > (((int32_t)Thermostat[ctr_output].time_pi_cycle * 60) - ((int32_t)Thermostat[ctr_output].time_min_turnoff_action * 60))) { - Thermostat[ctr_output].time_total_pi = ((int32_t)Thermostat[ctr_output].time_pi_cycle * 60); - } - - - Thermostat[ctr_output].time_ctr_changepoint = uptime + (uint32_t)Thermostat[ctr_output].time_total_pi; - - Thermostat[ctr_output].time_ctr_checkpoint = uptime + ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); -} - -void ThermostatWorkAutomaticPI(uint8_t ctr_output) -{ - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - if ( (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) - || (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) - || ( (( (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level) - && (Thermostat[ctr_output].temp_measured_gradient < 0) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level) - && (Thermostat[ctr_output].temp_measured_gradient > 0) - && (!flag_heating))) - && (Thermostat[ctr_output].status.status_cycle_active == CYCLE_OFF))) { - Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; - ThermostatCalculatePI(ctr_output); - - Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; - } - if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { - Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; - Thermostat[ctr_output].status.command_output = IFACE_ON; - } - else { - Thermostat[ctr_output].status.command_output = IFACE_OFF; - } -} - -void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) -{ - uint32_t time_in_rampup; - int16_t aux_temp_delta; - int16_t temp_delta_rampup; - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - - - - if ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_rampup_start) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_start) - && (!flag_heating))) - { - Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; - } - - - time_in_rampup = uptime - Thermostat[ctr_output].timestamp_rampup_start; - temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_start; - - Thermostat[ctr_output].status.command_output = IFACE_ON; - - Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; - - - - if ((time_in_rampup <= (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max)) - && ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level) - && (!flag_heating)))){ - - - - if ( (abs(temp_delta_rampup) >= Thermostat[ctr_output].temp_rampup_delta_out) - && (Thermostat[ctr_output].time_rampup_deadtime == 0)) { - - - int32_t time_aux; - time_aux = ((time_in_rampup / 2) - Thermostat[ctr_output].time_output_delay); - if (time_aux >= Thermostat[ctr_output].time_output_delay) { - Thermostat[ctr_output].time_rampup_deadtime = (uint32_t)time_aux; - } - else { - Thermostat[ctr_output].time_rampup_deadtime = Thermostat[ctr_output].time_output_delay; - } - - Thermostat[ctr_output].temp_rampup_meas_gradient = (int32_t)((360000 * (int32_t)temp_delta_rampup) / (int32_t)time_in_rampup); - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); - - Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; - Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max); - Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; - } - - else if ((Thermostat[ctr_output].time_rampup_deadtime > 0) && (uptime >= Thermostat[ctr_output].time_rampup_nextcycle)) { - - - temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_cycle; - uint32_t time_total_rampup = (uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60 * Thermostat[ctr_output].counter_rampup_cycles; - - Thermostat[ctr_output].temp_rampup_meas_gradient = int32_t((360000 * (int32_t)temp_delta_rampup) / (int32_t)time_total_rampup); - if ( ((Thermostat[ctr_output].temp_rampup_meas_gradient > 0) - && ((flag_heating))) - || ((Thermostat[ctr_output].temp_rampup_meas_gradient < 0) - && ((!flag_heating)))) { - - - - - aux_temp_delta =Thermostat[ctr_output].temp_target_level_ctr - Thermostat[ctr_output].temp_rampup_cycle; - Thermostat[ctr_output].time_ctr_changepoint = (uint32_t)(uint32_t)(((uint32_t)(aux_temp_delta) * (uint32_t)(time_total_rampup)) / (uint32_t)temp_delta_rampup) + (uint32_t)Thermostat[ctr_output].time_rampup_nextcycle - (uint32_t)time_total_rampup - (uint32_t)Thermostat[ctr_output].time_rampup_deadtime; - - - - Thermostat[ctr_output].temp_rampup_output_off = (int16_t)(((int32_t)temp_delta_rampup * (int32_t)(Thermostat[ctr_output].time_ctr_changepoint - (uptime - (time_total_rampup)))) / (int32_t)(time_total_rampup * Thermostat[ctr_output].counter_rampup_cycles)) + Thermostat[ctr_output].temp_rampup_cycle; - - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); - Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; - - Thermostat[ctr_output].counter_rampup_cycles = 1; - } - else { - - Thermostat[ctr_output].counter_rampup_cycles++; - - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); - - Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max) - time_in_rampup; - Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; - } - - Thermostat[ctr_output].time_ctr_checkpoint = Thermostat[ctr_output].time_ctr_changepoint + Thermostat[ctr_output].time_rampup_deadtime; - } - - - - - - - if ((Thermostat[ctr_output].time_rampup_deadtime == 0) - || (Thermostat[ctr_output].time_ctr_checkpoint == 0) - || (uptime < Thermostat[ctr_output].time_ctr_changepoint) - || ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_rampup_output_off) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_output_off) - && (!flag_heating))) - || ( ((Thermostat[ctr_output].temp_rampup_meas_gradient <= 0) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_rampup_meas_gradient >= 0) - && (!flag_heating)))) { - Thermostat[ctr_output].status.command_output = IFACE_ON; - } - else { - Thermostat[ctr_output].status.command_output = IFACE_OFF; - } - } - else { - - if ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level_ctr) - && (flag_heating)) - || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_target_level_ctr) - && (!flag_heating))) { - Thermostat[ctr_output].temp_pi_accum_error = Thermostat[ctr_output].temp_rampup_pi_acc_error; - } - - Thermostat[ctr_output].time_ctr_checkpoint = uptime; - - Thermostat[ctr_output].status.command_output = IFACE_OFF; - } -} - -#ifdef USE_PI_AUTOTUNING - -void ThermostatPeakDetectorInit(uint8_t ctr_output) -{ - for (uint8_t i = 0; i < THERMOSTAT_PEAKNUMBER_AUTOTUNE; i++) { - Thermostat[ctr_output].temp_peaks_atune[i] = 0; - } - Thermostat[ctr_output].pU_pi_atune = 0; - Thermostat[ctr_output].kP_pi_atune = 0; - Thermostat[ctr_output].kI_pi_atune = 0; - Thermostat[ctr_output].kU_pi_atune = 0; - Thermostat[ctr_output].peak_ctr = 0; - Thermostat[ctr_output].temp_abs_max_atune = 0; - Thermostat[ctr_output].temp_abs_min_atune = 100; - Thermostat[ctr_output].time_ctr_checkpoint = uptime + THERMOSTAT_TIME_MAX_AUTOTUNE; -} - -void ThermostatPeakDetector(uint8_t ctr_output) -{ - uint8_t peak_num = Thermostat[ctr_output].peak_ctr; - int16_t peak_avg = 0; - bool peak_transition = false; - - if (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_abs_max_atune) { - Thermostat[ctr_output].temp_abs_max_atune = Thermostat[ctr_output].temp_measured; - } - if (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_abs_min_atune) { - Thermostat[ctr_output].temp_abs_min_atune = Thermostat[ctr_output].temp_measured; - } - - - if (peak_num < THERMOSTAT_PEAKNUMBER_AUTOTUNE) { - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - bool cond_peak_1 = ( (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_peaks_atune[peak_num]) - && (flag_heating) - || (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_peaks_atune[peak_num]) - && (!flag_heating)); - bool cond_peak_2 = ( (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_peaks_atune[peak_num]) - && (flag_heating) - || (Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_peaks_atune[peak_num]) - && (!flag_heating)); - bool cond_gradient_1 = ( (Thermostat[ctr_output].temp_measured_gradient > 0) - && (flag_heating) - || (Thermostat[ctr_output].temp_measured_gradient < 0) - && (!flag_heating)); - bool cond_gradient_2 = ( (Thermostat[ctr_output].temp_measured_gradient < 0) - && (flag_heating) - || (Thermostat[ctr_output].temp_measured_gradient > 0) - && (!flag_heating)); - - if ((peak_num % 2) == 0) { - - - - if (cond_peak_1 && cond_gradient_1) { - Thermostat[ctr_output].temp_peaks_atune[peak_num] = Thermostat[ctr_output].temp_measured; - } - - - - if ( (cond_peak_2) - && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { - - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); - Thermostat[ctr_output].peak_ctr++; - peak_transition = true; - } - } - - else { - - - - if (cond_peak_2 && cond_gradient_2) { - Thermostat[ctr_output].temp_peaks_atune[peak_num] = Thermostat[ctr_output].temp_measured; - } - - - - if ( (cond_peak_1) - && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { - - - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); - Thermostat[ctr_output].peak_ctr++; - peak_transition = true; - } - } - } - else { - - ThermostatAutotuneParamCalc(ctr_output); - Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; - } - - - if ((Thermostat[ctr_output].peak_ctr > 2) && (peak_transition)) { - - peak_num = Thermostat[ctr_output].peak_ctr; - - peak_avg = (abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 1] - - Thermostat[ctr_output].temp_peaks_atune[peak_num - 2]) - + abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 2] - - Thermostat[ctr_output].temp_peaks_atune[peak_num - 3])) / 2; - - if ((20 * (int32_t)peak_avg) < (int32_t)(Thermostat[ctr_output].temp_abs_max_atune - Thermostat[ctr_output].temp_abs_min_atune)) { - - for (uint8_t i = 0; i < peak_num; i++) { - peak_avg += Thermostat[ctr_output].temp_peaks_atune[i]; - } - peak_avg /= peak_num; - - if (10 * abs(Thermostat[ctr_output].temp_peaks_atune[peak_num - 1] - Thermostat[ctr_output].temp_peaks_atune[peak_num - 2]) < (Thermostat[ctr_output].temp_abs_max_atune - peak_avg)) { - - ThermostatAutotuneParamCalc(ctr_output); - Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; - } - } - } - peak_transition = false; -} - -void ThermostatAutotuneParamCalc(uint8_t ctr_output) -{ - uint8_t peak_num = Thermostat[ctr_output].peak_ctr; - - - - Thermostat[ctr_output].kU_pi_atune = (uint16_t)(100 * ((uint32_t)400000 * (uint32_t)(Thermostat[ctr_output].dutycycle_step_autotune)) / ((uint32_t)(Thermostat[ctr_output].temp_abs_max_atune - Thermostat[ctr_output].temp_abs_min_atune) * (uint32_t)314159)); - Thermostat[ctr_output].pU_pi_atune = (Thermostat[ctr_output].time_peak_timestamps_atune[peak_num - 1] - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num - 2]); - - switch (Thermostat[ctr_output].status.autotune_perf_mode) { - case AUTOTUNE_PERF_FAST: - - Thermostat[ctr_output].kP_pi_atune = (4 * Thermostat[ctr_output].kU_pi_atune) / 10; - break; - case AUTOTUNE_PERF_NORMAL: - - Thermostat[ctr_output].kP_pi_atune = (18 * Thermostat[ctr_output].kU_pi_atune) / 100; - break; - case AUTOTUNE_PERF_SLOW: - - Thermostat[ctr_output].kP_pi_atune = (13 * Thermostat[ctr_output].kU_pi_atune) / 100; - break; - } - - - Thermostat[ctr_output].kI_pi_atune = (12 * (6000 * Thermostat[ctr_output].kU_pi_atune / Thermostat[ctr_output].pU_pi_atune)) / 10; - - - Thermostat[ctr_output].val_prop_band_atune = 100 / Thermostat[ctr_output].kP_pi_atune; - - Thermostat[ctr_output].time_reset_atune = (uint32_t)((((uint32_t)Thermostat[ctr_output].kP_pi_atune * (uint32_t)Thermostat[ctr_output].time_pi_cycle * 6000)) / (uint32_t)Thermostat[ctr_output].kI_pi_atune); -} - -void ThermostatWorkAutomaticPIAutotune(uint8_t ctr_output) -{ - bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - - - if ((uptime < Thermostat[ctr_output].time_ctr_checkpoint) - &&(Thermostat[ctr_output].temp_target_level_ctr == Thermostat[ctr_output].temp_target_level)) { - if (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) { - Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; - - Thermostat[ctr_output].time_ctr_changepoint = uptime + (((uint32_t)Thermostat[ctr_output].time_pi_cycle * (uint32_t)Thermostat[ctr_output].dutycycle_step_autotune) / (uint32_t)100); - - Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; - } - - if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { - Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; - Thermostat[ctr_output].status.command_output = IFACE_ON; - } - else { - Thermostat[ctr_output].status.command_output = IFACE_OFF; - } - - ThermostatPeakDetector(ctr_output); - } - else { - - Thermostat[ctr_output].status.autotune_flag = AUTOTUNE_OFF; - } - - if (Thermostat[ctr_output].status.autotune_flag == AUTOTUNE_OFF) { - - Thermostat[ctr_output].status.command_output = IFACE_OFF; - } -} -#endif - -void ThermostatCtrWork(uint8_t ctr_output) -{ - switch (Thermostat[ctr_output].status.controller_mode) { - - case CTR_HYBRID: - switch (Thermostat[ctr_output].status.phase_hybrid_ctr) { - case CTR_HYBRID_RAMP_UP: - ThermostatWorkAutomaticRampUp(ctr_output); - break; - case CTR_HYBRID_PI: - ThermostatWorkAutomaticPI(ctr_output); - break; -#ifdef USE_PI_AUTOTUNING - - case CTR_HYBRID_PI_AUTOTUNE: - ThermostatWorkAutomaticPIAutotune(ctr_output); - break; -#endif - } - break; - - case CTR_PI: - ThermostatWorkAutomaticPI(ctr_output); - break; - - case CTR_RAMP_UP: - ThermostatWorkAutomaticRampUp(ctr_output); - break; -#ifdef USE_PI_AUTOTUNING - - case CTR_PI_AUTOTUNE: - ThermostatWorkAutomaticPIAutotune(ctr_output); - break; -#endif - } -} - -void ThermostatWork(uint8_t ctr_output) -{ - switch (Thermostat[ctr_output].status.thermostat_mode) { - - case THERMOSTAT_OFF: - Thermostat[ctr_output].status.command_output = IFACE_OFF; - break; - - case THERMOSTAT_AUTOMATIC_OP: - ThermostatCtrWork(ctr_output); - - break; - - case THERMOSTAT_MANUAL_OP: - Thermostat[ctr_output].time_ctr_checkpoint = 0; - Thermostat[ctr_output].status.command_output = Thermostat[ctr_output].status.status_input; - break; - } - ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output); -} - -void ThermostatDiagnostics(uint8_t ctr_output) -{ - - if ((Thermostat[ctr_output].diag.diagnostic_mode == DIAGNOSTIC_ON) - &&(Thermostat[ctr_output].diag.output_inconsist_ctr >= THERMOSTAT_TIME_MAX_OUTPUT_INCONSIST)) { - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; - Thermostat[ctr_output].diag.state_emergency = EMERGENCY_ON; - } - - - - - - if (Thermostat[ctr_output].diag.state_emergency == EMERGENCY_ON) { - ThermostatEmergencyShutdown(ctr_output); - } -} - -void ThermostatController(uint8_t ctr_output) -{ - ThermostatState(ctr_output); - ThermostatWork(ctr_output); -} - -bool ThermostatTimerArm(uint8_t ctr_output, int16_t tempVal) -{ - bool result = false; - - if ((tempVal >= -1000) - && (tempVal <= 1000) - && (tempVal >= (int16_t)Thermostat[ctr_output].temp_frost_protect)) { - Thermostat[ctr_output].temp_target_level = tempVal; - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_AUTOMATIC_OP; - result = true; - } - - return result; -} - -void ThermostatTimerDisarm(uint8_t ctr_output) -{ - Thermostat[ctr_output].temp_target_level = THERMOSTAT_TEMP_INIT; - Thermostat[ctr_output].status.thermostat_mode = THERMOSTAT_OFF; -} - -#ifdef DEBUG_THERMOSTAT -void ThermostatVirtualSwitch(uint8_t ctr_output) -{ - char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; - if (ctr_output < DOMOTICZ_MAX_IDX) { - Response_P(DOMOTICZ_MES, Domoticz_Virtual_Switches[ctr_output], (0 == Thermostat[ctr_output].status.command_output) ? 0 : 1, ""); - MqttPublish(domoticz_in_topic); - } -} - -void ThermostatVirtualSwitchCtrState(uint8_t ctr_output) -{ - char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; - Response_P(DOMOTICZ_MES, DOMOTICZ_IDX2, (0 == Thermostat[0].status.phase_hybrid_ctr) ? 0 : 1, ""); - MqttPublish(domoticz_in_topic); -} - -void ThermostatDebug(uint8_t ctr_output) -{ - char result_chr[FLOATSZ]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("")); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("------ Thermostat Start ------")); - dtostrfd(Thermostat[ctr_output].status.counter_seconds, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.counter_seconds: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.thermostat_mode, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.thermostat_mode: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].diag.state_emergency, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].diag.state_emergency: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].diag.output_inconsist_ctr, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].diag.output_inconsist_ctr: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.controller_mode, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.controller_mode: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.command_output, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.command_output: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.status_output, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_output: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.status_input, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_input: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.phase_hybrid_ctr, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.phase_hybrid_ctr: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.sensor_alive, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.sensor_alive: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].status.status_cycle_active, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].status.status_cycle_active: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].temp_pi_error, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_pi_error: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].temp_pi_accum_error, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_pi_accum_error: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_proportional_pi, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_proportional_pi: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_integral_pi, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_integral_pi: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_total_pi, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_total_pi: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].temp_measured_gradient, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_measured_gradient: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_rampup_deadtime, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_rampup_deadtime: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].temp_rampup_meas_gradient, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_rampup_meas_gradient: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_ctr_changepoint, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_ctr_changepoint: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].temp_rampup_output_off, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_rampup_output_off: %s"), result_chr); - dtostrfd(Thermostat[ctr_output].time_ctr_checkpoint, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_ctr_checkpoint: %s"), result_chr); - dtostrfd(uptime, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("uptime: %s"), result_chr); - dtostrfd(power, 0, result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("power: %s"), result_chr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("------ Thermostat End ------")); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("")); -} -#endif - -void ThermostatGetLocalSensor(uint8_t ctr_output) { - String buf = mqtt_data; - JsonParser parser((char*)buf.c_str()); - JsonParserObject root = parser.getRootObject(); - if (root) { - JsonParserToken value_token = root[PSTR(THERMOSTAT_SENSOR_NAME)].getObject()[PSTR("Temperature")]; - if (value_token.isNum()) { - int16_t value = value_token.getFloat() * 10; - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatFahrenheitToCelsius(value, TEMP_CONV_ABSOLUTE); - } - if ( (value >= -1000) - && (value <= 1000) - && (Thermostat[ctr_output].status.sensor_type == SENSOR_LOCAL)) { - uint32_t timestamp = uptime; - - if (value != Thermostat[ctr_output].temp_measured) { - int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); - uint32_t time_delta = (timestamp - Thermostat[ctr_output].timestamp_temp_meas_change_update); - Thermostat[ctr_output].temp_measured_gradient = (int32_t)((360000 * temp_delta) / ((int32_t)time_delta)); - Thermostat[ctr_output].temp_measured = value; - Thermostat[ctr_output].timestamp_temp_meas_change_update = timestamp; - } - Thermostat[ctr_output].timestamp_temp_measured_update = timestamp; - Thermostat[ctr_output].status.sensor_alive = IFACE_ON; - } - } - } -} - - - - - -void CmndThermostatModeSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); - if ((value >= THERMOSTAT_OFF) && (value < THERMOSTAT_MODES_MAX)) { - Thermostat[ctr_output].status.thermostat_mode = value; - Thermostat[ctr_output].timestamp_input_on = 0; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.thermostat_mode); - } -} - -void CmndClimateModeSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); - if ((value >= CLIMATE_HEATING) && (value < CLIMATE_MODES_MAX)) { - Thermostat[ctr_output].status.climate_mode = value; - - Thermostat[ctr_output].time_ctr_checkpoint = uptime; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.climate_mode); - } -} - -void CmndTempFrostProtectSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - int16_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (int16_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); - } - else { - value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= 0) - && (value <= 127)) { - Thermostat[ctr_output].temp_frost_protect = (uint8_t)value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_frost_protect, TEMP_CONV_ABSOLUTE); - } - else { - value = (int16_t)Thermostat[ctr_output].temp_frost_protect; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndControllerModeSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= CTR_HYBRID) && (value < CTR_MODES_MAX)) { - Thermostat[ctr_output].status.controller_mode = value; - - Thermostat[ctr_output].timestamp_rampup_start = uptime; - Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; - Thermostat[ctr_output].temp_rampup_meas_gradient = 0; - Thermostat[ctr_output].time_rampup_deadtime = 0; - Thermostat[ctr_output].counter_rampup_cycles = 1; - Thermostat[ctr_output].time_ctr_changepoint = 0; - Thermostat[ctr_output].time_ctr_checkpoint = 0; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.controller_mode); - } -} - -void CmndInputSwitchSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if (ThermostatSwitchIdValid(value)) { - Thermostat[ctr_output].status.input_switch_number = value; - Thermostat[ctr_output].timestamp_input_on = uptime; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.input_switch_number); - } -} - -void CmndInputSwitchUse(void) -{ - if ((XdrvMailbox.index >= INPUT_NOT_USED) && (XdrvMailbox.index <= INPUT_USED)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - Thermostat[ctr_output].status.use_input = (uint32_t)(XdrvMailbox.payload); - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.use_input); - } -} - -void CmndSensorInputSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= SENSOR_MQTT) && (value < SENSOR_MAX)) { - Thermostat[ctr_output].status.sensor_type = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.sensor_type); - } -} - -void CmndOutputRelaySet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if (ThermostatRelayIdValid(value)) { - Thermostat[ctr_output].status.output_relay_number = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.output_relay_number); - } -} - -void CmndTimeAllowRampupSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value < 1440)) { - Thermostat[ctr_output].time_allow_rampup = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_allow_rampup)); - } -} - -void CmndTempFormatSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= TEMP_FAHRENHEIT)) { - Thermostat[ctr_output].status.temp_format = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.temp_format); - } -} - -void CmndTempMeasuredSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - int16_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); - } - else { - value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= -1000) - && (value <= 1000) - && (Thermostat[ctr_output].status.sensor_type == SENSOR_MQTT)) { - uint32_t timestamp = uptime; - - if (value != Thermostat[ctr_output].temp_measured) { - int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); - uint32_t time_delta = (timestamp - Thermostat[ctr_output].timestamp_temp_meas_change_update); - Thermostat[ctr_output].temp_measured_gradient = (int32_t)((360000 * temp_delta) / ((int32_t)time_delta)); - Thermostat[ctr_output].temp_measured = value; - Thermostat[ctr_output].timestamp_temp_meas_change_update = timestamp; - } - Thermostat[ctr_output].timestamp_temp_measured_update = timestamp; - Thermostat[ctr_output].status.sensor_alive = IFACE_ON; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_measured, TEMP_CONV_ABSOLUTE); - } - else { - value = Thermostat[ctr_output].temp_measured; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndTempTargetSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - int16_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_ABSOLUTE); - } - else { - value = (int16_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= -1000) - && (value <= 1000) - && (value >= (int16_t)Thermostat[ctr_output].temp_frost_protect)) { - Thermostat[ctr_output].temp_target_level = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_target_level, TEMP_CONV_ABSOLUTE); - } - else { - value = Thermostat[ctr_output].temp_target_level; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndTempMeasuredGrdRead(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - int16_t value; - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_measured_gradient, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_measured_gradient; - } - ResponseCmndFloat(((float)value) / 1000, 1); - } -} - -void CmndStateEmergencySet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1)) { - Thermostat[ctr_output].diag.state_emergency = (uint16_t)value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].diag.state_emergency); - } -} - -void CmndTimeManualToAutoSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_manual_to_auto = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_manual_to_auto)); - } -} - -void CmndPropBandSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 20)) { - Thermostat[ctr_output].val_prop_band = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].val_prop_band); - } -} - -void CmndTimeResetSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 86400)) { - Thermostat[ctr_output].time_reset = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].time_reset); - } -} - -void CmndTimePiProportRead(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - ResponseCmndNumber((int)Thermostat[ctr_output].time_proportional_pi); - } -} - -void CmndTimePiIntegrRead(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - ResponseCmndNumber((int)Thermostat[ctr_output].time_integral_pi); - } -} - -void CmndTimePiCycleSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_pi_cycle = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_pi_cycle)); - } -} - -void CmndTempAntiWindupResetSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - uint8_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); - } - else { - value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= 0) - && (value <= 100)) { - Thermostat[ctr_output].temp_reset_anti_windup = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_reset_anti_windup, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_reset_anti_windup; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndTempHystSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - int8_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (int8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); - } - else { - value = (int8_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= -100) - && (value <= 100)) { - Thermostat[ctr_output].temp_hysteresis = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_hysteresis, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_hysteresis; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -#ifdef USE_PI_AUTOTUNING -void CmndPerfLevelAutotune(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= AUTOTUNE_PERF_MAX)) { - Thermostat[ctr_output].status.autotune_perf_mode = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.autotune_perf_mode); - } -} -#endif - -void CmndTimeMaxActionSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_max_action = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_max_action)); - } -} - -void CmndTimeMinActionSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_min_action = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_min_action)); - } -} - -void CmndTimeSensLostSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_sens_lost = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_sens_lost)); - } -} - -void CmndTimeMinTurnoffActionSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_min_turnoff_action = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_min_turnoff_action)); - } -} - -void CmndTempRupDeltInSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - uint8_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); - } - else { - value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= 0) - && (value <= 100)) { - Thermostat[ctr_output].temp_rampup_delta_in = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_delta_in, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_rampup_delta_in; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndTempRupDeltOutSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - uint8_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (uint8_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 10), TEMP_CONV_RELATIVE); - } - else { - value = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - } - if ( (value >= 0) - && (value <= 100)) { - Thermostat[ctr_output].temp_rampup_delta_out = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_delta_out, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_rampup_delta_out; - } - ResponseCmndFloat((float)value / 10, 1); - } -} - -void CmndTimeRampupMaxSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_rampup_max = (uint16_t)value; - } - } - ResponseCmndNumber((int)((uint32_t)Thermostat[ctr_output].time_rampup_max)); - } -} - -void CmndTimeRampupCycleSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint32_t value = (uint32_t)(XdrvMailbox.payload); - if ((value >= 0) && (value <= 1440)) { - Thermostat[ctr_output].time_rampup_cycle = (uint16_t)value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].time_rampup_cycle); - } -} - -void CmndTempRampupPiAccErrSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - uint16_t value; - if (XdrvMailbox.data_len > 0) { - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = (uint16_t)ThermostatFahrenheitToCelsius((int32_t)(CharToFloat(XdrvMailbox.data) * 100), TEMP_CONV_RELATIVE); - } - else { - value = (uint16_t)(CharToFloat(XdrvMailbox.data) * 100); - } - if ( (value >= 0) - && (value <= 2500)) { - Thermostat[ctr_output].temp_rampup_pi_acc_error = value; - } - } - if (Thermostat[ctr_output].status.temp_format == TEMP_FAHRENHEIT) { - value = ThermostatCelsiusToFahrenheit((int32_t)Thermostat[ctr_output].temp_rampup_pi_acc_error, TEMP_CONV_RELATIVE); - } - else { - value = Thermostat[ctr_output].temp_rampup_pi_acc_error; - } - ResponseCmndFloat((float)value / 100, 1); - } -} - -void CmndDiagnosticModeSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); - if ((value >= DIAGNOSTIC_OFF) && (value <= DIAGNOSTIC_ON)) { - Thermostat[ctr_output].diag.diagnostic_mode = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].diag.diagnostic_mode); - } -} - -void CmndCtrDutyCycleRead(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - uint8_t value = 0; - if ( (Thermostat[ctr_output].status.controller_mode == CTR_PI) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_PI))) { - value = Thermostat[ctr_output].time_total_pi / Thermostat[ctr_output].time_pi_cycle; - } - else if ( (Thermostat[ctr_output].status.controller_mode == CTR_RAMP_UP) - || ((Thermostat[ctr_output].status.controller_mode == CTR_HYBRID) - &&(Thermostat[ctr_output].status.phase_hybrid_ctr == CTR_HYBRID_RAMP_UP))) { - if (Thermostat[ctr_output].status.status_output == IFACE_ON) { - value = 100; - } - else { - value = 0; - } - } - ResponseCmndNumber((int)value); - } -} - -void CmndEnableOutputSet(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= THERMOSTAT_CONTROLLER_OUTPUTS)) { - uint8_t ctr_output = XdrvMailbox.index - 1; - if (XdrvMailbox.data_len > 0) { - uint8_t value = (uint8_t)(CharToFloat(XdrvMailbox.data)); - if ((value >= IFACE_OFF) && (value <= IFACE_ON)) { - Thermostat[ctr_output].status.enable_output = value; - } - } - ResponseCmndNumber((int)Thermostat[ctr_output].status.enable_output); - } -} - - - - - -bool Xdrv39(uint8_t function) -{ - bool result = false; - uint8_t ctr_output; - - switch (function) { - case FUNC_INIT: - for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { - ThermostatInit(ctr_output); - } - break; - case FUNC_LOOP: - for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { - if (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF) { - ThermostatSignalProcessingFast(ctr_output); - ThermostatDiagnostics(ctr_output); - } - } - break; - case FUNC_SERIAL: - break; - case FUNC_EVERY_SECOND: - for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { - if ((ThermostatMinuteCounter(ctr_output)) - && (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF)) { - ThermostatSignalPreProcessingSlow(ctr_output); - ThermostatController(ctr_output); - ThermostatSignalPostProcessingSlow(ctr_output); -#ifdef DEBUG_THERMOSTAT - ThermostatDebug(ctr_output); -#endif - } - } - break; - case FUNC_SHOW_SENSOR: - for (ctr_output = 0; ctr_output < THERMOSTAT_CONTROLLER_OUTPUTS; ctr_output++) { - if (Thermostat[ctr_output].status.thermostat_mode != THERMOSTAT_OFF) { - ThermostatGetLocalSensor(ctr_output); - } - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kThermostatCommands, ThermostatCommand); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" -#ifdef USE_TELEGRAM -# 41 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" -#define XDRV_40 40 - -#ifndef TELEGRAM_LOOP_WAIT -#define TELEGRAM_LOOP_WAIT 10 -#endif - -#define TELEGRAM_SEND_RETRY 4 -#define TELEGRAM_MAX_MESSAGES 2 - -#ifdef USE_MQTT_TLS_CA_CERT - static const uint32_t tls_rx_size = 2048; - static const uint32_t tls_tx_size = 1024; -#else - static const uint32_t tls_rx_size = 1024; - static const uint32_t tls_tx_size = 1024; -#endif - -#include "WiFiClientSecureLightBearSSL.h" -BearSSL::WiFiClientSecure_light *telegramClient = nullptr; - -static const uint8_t Telegram_Fingerprint[] PROGMEM = USE_TELEGRAM_FINGERPRINT; - -typedef struct { - String text; - - - - uint32_t update_id = 0; - uint32_t chat_id = 0; -} TelegramMessage; - -struct { - TelegramMessage message[TELEGRAM_MAX_MESSAGES]; - uint32_t next_update_id = 0; - uint8_t message_count = 0; - uint8_t state = 0; - uint8_t index = 0; - uint8_t retry = 0; - uint8_t poll = TELEGRAM_LOOP_WAIT; - uint8_t wait = 0; - bool send_enable = false; - bool recv_enable = false; - bool echo_enable = false; - bool recv_busy = false; - bool skip = true; -} Telegram; - -bool TelegramInit(void) { - bool init_done = false; - if (strlen(SettingsText(SET_TELEGRAM_TOKEN))) { - if (!telegramClient) { - telegramClient = new BearSSL::WiFiClientSecure_light(tls_rx_size, tls_tx_size); -#ifdef USE_MQTT_TLS_CA_CERT - telegramClient->setTrustAnchor(&GoDaddyCAG2_TA, 1); -#else - telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); -#endif - Telegram.message_count = 0; - Telegram.next_update_id = 0; - Telegram.message[0].text = ""; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("TGM: Started")); - } - init_done = true; - } - return init_done; -} - -String TelegramConnectToTelegram(String command) { - - - if (!TelegramInit()) { return ""; } - - String response = ""; - uint32_t tls_connect_time = millis(); - if (telegramClient->connect("api.telegram.org", 443)) { - - - - telegramClient->println("GET /"+command); - - char c; - int ch_count=0; - uint32_t now = millis(); - bool avail = false; - while (millis() -now < 1500) { - while (telegramClient->available()) { - char c = telegramClient->read(); - if (ch_count < 700) { - response = response + c; - ch_count++; - } - avail = true; - } - if (avail) { - break; - } - } - - telegramClient->stop(); - } - - return response; -} - -void TelegramGetUpdates(uint32_t offset) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: getUpdates")); - - if (!TelegramInit()) { return; } - - String _token = SettingsText(SET_TELEGRAM_TOKEN); - String command = "bot" + _token + "/getUpdates?offset=" + String(offset); - String response = TelegramConnectToTelegram(command); -# 207 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: Response %s"), response.c_str()); - - JsonParser parser((char*)response.c_str()); - JsonParserObject root = parser.getRootObject(); - if (root) { - - - - JsonParserArray arr = root[PSTR("result")]; - uint32_t max_updates = arr.size(); - - if (max_updates > 1) { max_updates = 1; } - Telegram.message_count = 0; - if (max_updates) { - for (uint32_t i = 0; i < max_updates; i++) { - Telegram.message[i].text = ""; - JsonParserObject result = arr[i].getObject(); - if (result) { - - - - - - - Telegram.message_count++; - Telegram.message[i].update_id = result["update_id"].getUInt(); - - - - Telegram.message[i].chat_id = result["message"].getObject()["chat"].getObject()["id"].getUInt(); - Telegram.message[i].text = result["message"].getObject()["text"].getStr(); - } - Telegram.next_update_id = Telegram.message[i].update_id +1; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: Parsed update_id %d, chat_id %d, text \"%s\""), Telegram.message[i].update_id, Telegram.message[i].chat_id, Telegram.message[i].text.c_str()); - } - } else { - - } - } else { - - } -} - -bool TelegramSendMessage(uint32_t chat_id, String text) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TGM: sendMessage")); - - if (!TelegramInit()) { return false; } - - bool sent = false; - if (text != "") { - String _token = SettingsText(SET_TELEGRAM_TOKEN); - String command = "bot" + _token + "/sendMessage?chat_id=" + String(chat_id) + "&text=" + text; - String response = TelegramConnectToTelegram(command); - - - - if (response.startsWith("{\"ok\":true")) { - - sent = true; - } - } - - return sent; -} -# 289 "/workspace/Tasmota/tasmota/xdrv_40_telegram.ino" -String TelegramExecuteCommand(const char *svalue) { - String response = ""; - - uint32_t curridx = web_log_index; - ExecuteCommand(svalue, SRC_CHAT); - if (web_log_index != curridx) { - uint32_t counter = curridx; - response = F("{"); - 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); - if (cflg) { response += F(","); } - response += stemp; - cflg = true; - } - } - counter++; - counter &= 0xFF; - if (!counter) counter++; - } while (counter != web_log_index); - response += F("}"); - } else { - response = F("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"); - } - - return response; -} - -void TelegramLoop(void) { - if (!global_state.network_down && (Telegram.recv_enable || Telegram.echo_enable)) { - switch (Telegram.state) { - case 0: - TelegramInit(); - Telegram.state++; - break; - case 1: - TelegramGetUpdates(Telegram.next_update_id); - Telegram.index = 0; - Telegram.retry = TELEGRAM_SEND_RETRY; - Telegram.state++; - break; - case 2: - if (Telegram.echo_enable) { - if (Telegram.retry && (Telegram.index < Telegram.message_count)) { - if (TelegramSendMessage(Telegram.message[Telegram.index].chat_id, Telegram.message[Telegram.index].text)) { - Telegram.index++; - Telegram.retry = TELEGRAM_SEND_RETRY; - } else { - Telegram.retry--; - } - } else { - Telegram.message_count = 0; - Telegram.wait = Telegram.poll; - Telegram.state++; - } - } else { - if (Telegram.skip) { - Telegram.skip = false; - } else { - if (Telegram.message_count && (Telegram.message[Telegram.index].text.length() > 0)) { - String logging = TelegramExecuteCommand(Telegram.message[Telegram.index].text.c_str()); - if (logging.length() > 0) { - TelegramSendMessage(Telegram.message[Telegram.index].chat_id, logging); - } - } - } - Telegram.message_count = 0; - Telegram.wait = Telegram.poll; - Telegram.state++; - } - break; - case 3: - if (Telegram.wait) { - Telegram.wait--; - } else { - Telegram.state = 1; - } - } - } -} - - - - - -#define D_CMND_TMSTATE "State" -#define D_CMND_TMPOLL "Poll" -#define D_CMND_TMSEND "Send" -#define D_CMND_TMTOKEN "Token" -#define D_CMND_TMCHATID "ChatId" - -const char kTelegramCommands[] PROGMEM = "Tm|" - D_CMND_TMSTATE "|" D_CMND_TMPOLL "|" D_CMND_TMTOKEN "|" D_CMND_TMCHATID "|" D_CMND_TMSEND; - -void (* const TelegramCommand[])(void) PROGMEM = { - &CmndTmState, &CmndTmPoll, &CmndTmToken, &CmndTmChatId, &CmndTmSend }; - -void CmndTmState(void) { - if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - Telegram.send_enable = XdrvMailbox.payload &1; - break; - case 2: - case 3: - Telegram.recv_enable = XdrvMailbox.payload &1; - break; - case 4: - case 5: - Telegram.echo_enable = XdrvMailbox.payload &1; - break; - } - } - } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"), - XdrvMailbox.command, GetStateText(Telegram.send_enable), GetStateText(Telegram.recv_enable), GetStateText(Telegram.echo_enable)); -} - -void CmndTmPoll(void) { - if ((XdrvMailbox.payload >= 4) && (XdrvMailbox.payload <= 300)) { - Telegram.poll = XdrvMailbox.payload; - if (Telegram.poll < Telegram.wait) { - Telegram.wait = Telegram.poll; - } - } - ResponseCmndNumber(Telegram.poll); -} - -void CmndTmToken(void) { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_TELEGRAM_TOKEN, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_TELEGRAM_TOKEN)); -} - -void CmndTmChatId(void) { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_TELEGRAM_CHATID, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_TELEGRAM_CHATID)); -} - -void CmndTmSend(void) { - if (!Telegram.send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) { - ResponseCmndChar(D_JSON_FAILED); - return; - } - if (XdrvMailbox.data_len > 0) { - String message = XdrvMailbox.data; - String chat_id = SettingsText(SET_TELEGRAM_CHATID); - if (!TelegramSendMessage(chat_id.toInt(), message)) { - ResponseCmndChar(D_JSON_FAILED); - return; - } - } - ResponseCmndDone(); -} - - - - - -bool Xdrv40(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - TelegramLoop(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTelegramCommands, TelegramCommand); - break; - } - return result; -} -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" -#ifdef USE_TCP_BRIDGE - -#define XDRV_41 41 - -#ifndef TCP_BRIDGE_CONNECTIONS -#define TCP_BRIDGE_CONNECTIONS 2 -#endif - -#ifndef TCP_BRIDGE_BUF_SIZE -#define TCP_BRIDGE_BUF_SIZE 255 -#endif - - -WiFiServer *server_tcp = nullptr; - -WiFiClient client_tcp[TCP_BRIDGE_CONNECTIONS]; -uint8_t client_next = 0; -uint8_t *tcp_buf = nullptr; - -#include -TasmotaSerial *TCPSerial = nullptr; - -const char kTCPCommands[] PROGMEM = "TCP" "|" - "Start" "|" "Baudrate" - ; - -void (* const TCPCommand[])(void) PROGMEM = { - &CmndTCPStart, &CmndTCPBaudrate - }; - - - - -void TCPLoop(void) -{ - uint8_t c; - bool busy; - int32_t buf_len; - - if (!TCPSerial) return; - - - if ((server_tcp) && (server_tcp->hasClient())) { - - uint32_t i; - for (i=0; iavailable(); - break; - } - } - if (i >= ARRAY_SIZE(client_tcp)) { - i = client_next++ % ARRAY_SIZE(client_tcp); - WiFiClient &client = client_tcp[i]; - client.stop(); - client = server_tcp->available(); - } - } - - do { - busy = false; - - - buf_len = 0; - while ((buf_len < TCP_BRIDGE_BUF_SIZE) && (TCPSerial->available())) { - c = TCPSerial->read(); - if (c >= 0) { - tcp_buf[buf_len++] = c; - busy = true; - } - } - if (buf_len > 0) { - char hex_char[TCP_BRIDGE_BUF_SIZE+1]; - ToHex_P(tcp_buf, buf_len, hex_char, 256); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "from MCU: %s"), hex_char); - - for (uint32_t i=0; i= 0) { - tcp_buf[buf_len++] = c; - busy = true; - } - } - if (buf_len > 0) { - char hex_char[TCP_BRIDGE_BUF_SIZE+1]; - ToHex_P(tcp_buf, buf_len, hex_char, 256); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "to MCU/%d: %s"), i+1, hex_char); - TCPSerial->write(tcp_buf, buf_len); - } - } - - yield(); - } while (busy); -} - - -void TCPInit(void) { - if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) { - tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE); - if (!tcp_buf) { AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; } - - if (!Settings.tcp_baudrate) { Settings.tcp_baudrate = 115200 / 1200; } - TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); - TCPSerial->begin(Settings.tcp_baudrate * 1200); - if (TCPSerial->hardwareSerial()) { - ClaimSerial(); - } - } -} -# 148 "/workspace/Tasmota/tasmota/xdrv_41_tcp_bridge.ino" -void CmndTCPStart(void) { - - if (!TCPSerial) { return; } - int32_t tcp_port = XdrvMailbox.payload; - - if (server_tcp) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Stopping TCP server")); - server_tcp->stop(); - delete server_tcp; - server_tcp = nullptr; - - for (uint32_t i=0; i 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Starting TCP server on port %d"), tcp_port); - server_tcp = new WiFiServer(tcp_port); - server_tcp->begin(); - server_tcp->setNoDelay(true); - } - - ResponseCmndDone(); -} - -void CmndTCPBaudrate(void) { - if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) { - XdrvMailbox.payload /= 1200; - Settings.tcp_baudrate = XdrvMailbox.payload; - TCPSerial->begin(Settings.tcp_baudrate * 1200); - } - ResponseCmndNumber(Settings.tcp_baudrate * 1200); -} - - - - - -bool Xdrv41(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - TCPLoop(); - break; - case FUNC_PRE_INIT: - TCPInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTCPCommands, TCPCommand); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_42_i2s_audio.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_42_i2s_audio.ino" -#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) -#include "AudioFileSourcePROGMEM.h" -#include "AudioFileSourceID3.h" -#include "AudioGeneratorMP3.h" -#include "AudioOutputI2S.h" -#include -#include "AudioFileSourceFS.h" -#ifdef SAY_TIME -#include "AudioGeneratorTalkie.h" -#endif -#include "AudioFileSourceICYStream.h" -#include "AudioFileSourceBuffer.h" -#include "AudioGeneratorAAC.h" - -#ifdef USE_TTGO_WATCH -#undef TTGO_PWR_ON -#undef TTGO_PWR_OFF -#define TTGO_PWR_ON TTGO_audio_power(true); -#define TTGO_PWR_OFF TTGO_audio_power(false); -#else -#undef TTGO_PWR_ON -#undef TTGO_PWR_OFF -#define TTGO_PWR_ON -#define TTGO_PWR_OFF -#endif - -#define EXTERNAL_DAC_PLAY 1 - -#define XDRV_42 42 - -AudioGeneratorMP3 *mp3 = nullptr; -AudioFileSourceFS *file; -AudioOutputI2S *out; -AudioFileSourceID3 *id3; -AudioGeneratorMP3 *decoder = NULL; -void *mp3ram = NULL; - -#define I2SAUDIO_TASK_STACK_SIZE 8192 - - -#ifdef ESP8266 -const int preallocateBufferSize = 5*1024; -const int preallocateCodecSize = 29192; -#else -const int preallocateBufferSize = 16*1024; -const int preallocateCodecSize = 29192; - -#endif - -#ifdef USE_WEBRADIO -AudioFileSourceICYStream *ifile = NULL; -AudioFileSourceBuffer *buff = NULL; -char wr_title[64]; - - -void *preallocateBuffer = NULL; -void *preallocateCodec = NULL; -uint32_t retryms = 0; -#endif - -#ifdef SAY_TIME -AudioGeneratorTalkie *talkie = nullptr; -#endif - - -#ifdef ESP32 -#undef TWATCH_DAC_IIS_BCK -#undef TWATCH_DAC_IIS_WS -#undef TWATCH_DAC_IIS_DOUT -#define TWATCH_DAC_IIS_BCK 26 -#define TWATCH_DAC_IIS_WS 25 -#define TWATCH_DAC_IIS_DOUT 33 -#else -#undef TWATCH_DAC_IIS_BCK -#undef TWATCH_DAC_IIS_WS -#undef TWATCH_DAC_IIS_DOUT -#define TWATCH_DAC_IIS_BCK 15 -#define TWATCH_DAC_IIS_WS 2 -#define TWATCH_DAC_IIS_DOUT 3 -#endif - - -#ifdef SAY_TIME -long timezone = 2; -byte daysavetime = 1; - -uint8_t spTHE[] PROGMEM = {0x08,0xE8,0x3E,0x55,0x01,0xC3,0x86,0x27,0xAF,0x72,0x0D,0x4D,0x97,0xD5,0xBC,0x64,0x3C,0xF2,0x5C,0x51,0xF1,0x93,0x36,0x8F,0x4F,0x59,0x2A,0x42,0x7A,0x32,0xC3,0x64,0xFF,0x3F}; -uint8_t spTIME[] PROGMEM = {0x0E,0x28,0xAC,0x2D,0x01,0x5D,0xB6,0x0D,0x33,0xF3,0x54,0xB3,0x60,0xBA,0x8C,0x54,0x5C,0xCD,0x2D,0xD4,0x32,0x73,0x0F,0x8E,0x34,0x33,0xCB,0x4A,0x25,0xD4,0x25,0x83,0x2C,0x2B,0xD5,0x50,0x97,0x08,0x32,0xEC,0xD4,0xDC,0x4C,0x33,0xC8,0x70,0x73,0x0F,0x33,0xCD,0x20,0xC3,0xCB,0x43,0xDD,0x3C,0xCD,0x8C,0x20,0x77,0x89,0xF4,0x94,0xB2,0xE2,0xE2,0x35,0x22,0x5D,0xD6,0x4A,0x8A,0x96,0xCC,0x36,0x25,0x2D,0xC9,0x9A,0x7B,0xC2,0x18,0x87,0x24,0x4B,0x1C,0xC9,0x50,0x19,0x92,0x2C,0x71,0x34,0x4B,0x45,0x8A,0x8B,0xC4,0x96,0xB6,0x5A,0x29,0x2A,0x92,0x5A,0xCA,0x53,0x96,0x20,0x05,0x09,0xF5,0x92,0x5D,0xBC,0xE8,0x58,0x4A,0xDD,0xAE,0x73,0xBD,0x65,0x4B,0x8D,0x78,0xCA,0x2B,0x4E,0xD8,0xD9,0xED,0x22,0x20,0x06,0x75,0x00,0x00,0x80,0xFF,0x07}; -uint8_t spIS[] PROGMEM = {0x21,0x18,0x96,0x38,0xB7,0x14,0x8D,0x60,0x3A,0xA6,0xE8,0x51,0xB4,0xDC,0x2E,0x48,0x7B,0x5A,0xF1,0x70,0x1B,0xA3,0xEC,0x09,0xC6,0xCB,0xEB,0x92,0x3D,0xA7,0x69,0x1F,0xAF,0x71,0x89,0x9C,0xA2,0xB3,0xFC,0xCA,0x35,0x72,0x9A,0xD1,0xF0,0xAB,0x12,0xB3,0x2B,0xC6,0xCD,0x4F,0xCC,0x32,0x26,0x19,0x07,0xDF,0x0B,0x8F,0xB8,0xA4,0xED,0x7C,0xCF,0x23,0x62,0x8B,0x8E,0xF1,0x23,0x0A,0x8B,0x6E,0xCB,0xCE,0xEF,0x54,0x44,0x3C,0xDC,0x08,0x60,0x0B,0x37,0x01,0x1C,0x53,0x26,0x80,0x15,0x4E,0x14,0xB0,0x54,0x2B,0x02,0xA4,0x69,0xFF,0x7F}; -uint8_t spA_M_[] PROGMEM = {0xCD,0xEF,0x86,0xAB,0x57,0x6D,0x0F,0xAF,0x71,0xAD,0x49,0x55,0x3C,0xFC,0x2E,0xC5,0xB7,0x5C,0xF1,0xF2,0x87,0x66,0xDD,0x4E,0xC5,0xC3,0xEF,0x92,0xE2,0x3A,0x65,0xB7,0xA0,0x09,0xAA,0x1B,0x97,0x54,0x82,0x2E,0x28,0x77,0x5C,0x52,0x09,0x1A,0xA3,0xB8,0x76,0x49,0x25,0x68,0x8C,0x73,0xDB,0x24,0x95,0xA0,0x32,0xA9,0x6B,0xA7,0xD9,0x82,0x26,0xA9,0x76,0x42,0xD6,0x08,0xBA,0xE1,0xE8,0x0E,0x5A,0x2B,0xEA,0x9E,0x3D,0x27,0x18,0xAD,0xA8,0x07,0xF1,0x98,0x90,0x35,0xA2,0x96,0x44,0xA3,0x5D,0x66,0x8B,0x6B,0x12,0xCD,0x32,0x85,0x25,0xC9,0x81,0x2D,0xC3,0x64,0x85,0x34,0x58,0x89,0x94,0x52,0x1C,0x52,0x2F,0x35,0xDA,0xC7,0x51,0x48,0x23,0x97,0xCC,0x2C,0x97,0x2E,0xF3,0x5C,0xF3,0xA2,0x14,0xBA,0x2C,0x48,0xCE,0xCA,0x76,0xE8,0x32,0x2F,0x34,0xB2,0xDB,0x85,0xC9,0x83,0x90,0xA8,0x2C,0x57,0x26,0x8F,0x9C,0xBD,0xA2,0x53,0xD9,0xC2,0x54,0x59,0x28,0x99,0x4B,0x2C,0x5D,0xFF,0x3F}; -uint8_t spP_M_[] PROGMEM = {0x0E,0x98,0x41,0x54,0x00,0x43,0xA0,0x05,0xAB,0x42,0x8E,0x1D,0xA3,0x15,0xEC,0x4E,0x58,0xF7,0x92,0x66,0x70,0x1B,0x66,0xDB,0x73,0x99,0xC1,0xEB,0x98,0xED,0xD6,0x25,0x25,0x6F,0x70,0x92,0xDD,0x64,0xD8,0xFC,0x61,0xD0,0x66,0x83,0xD6,0x0A,0x86,0x23,0xAB,0x69,0xDA,0x2B,0x18,0x9E,0x3D,0x37,0x69,0x9D,0xA8,0x07,0x71,0x9F,0xA0,0xBD,0xA2,0x16,0xD5,0x7C,0x54,0xF6,0x88,0x6B,0x54,0x8B,0x34,0x49,0x2D,0x29,0x49,0x3C,0x34,0x64,0xA5,0x24,0x1B,0x36,0xD7,0x72,0x13,0x92,0xA4,0xC4,0x2D,0xC3,0xB3,0x4B,0xA3,0x62,0x0F,0x2B,0x37,0x6E,0x8B,0x5A,0xD4,0x3D,0xDD,0x9A,0x2D,0x50,0x93,0xF6,0x4C,0xAA,0xB6,0xC4,0x85,0x3B,0xB2,0xB1,0xD8,0x93,0x20,0x4D,0x8F,0x24,0xFF,0x0F}; -uint8_t spOH[] PROGMEM = {0xC6,0xC9,0x71,0x5A,0xA2,0x92,0x14,0x2F,0x6E,0x97,0x9C,0x46,0x9D,0xDC,0xB0,0x4D,0x62,0x1B,0x55,0x70,0xDD,0x55,0xBE,0x0E,0x36,0xC1,0x33,0x37,0xA9,0xA7,0x51,0x1B,0xCF,0x3C,0xA5,0x9E,0x44,0xAC,0x3C,0x7D,0x98,0x7B,0x52,0x96,0x72,0x65,0x4B,0xF6,0x1A,0xD9,0xCA,0xF5,0x91,0x2D,0xA2,0x2A,0x4B,0xF7,0xFF,0x01}; -uint8_t spOCLOCK[] PROGMEM = {0x21,0x4E,0x3D,0xB8,0x2B,0x19,0xBB,0x24,0x0E,0xE5,0xEC,0x60,0xE4,0xF2,0x90,0x13,0xD4,0x2A,0x11,0x80,0x00,0x42,0x69,0x26,0x40,0xD0,0x2B,0x04,0x68,0xE0,0x4D,0x00,0x3A,0x35,0x35,0x33,0xB6,0x51,0xD9,0x64,0x34,0x82,0xB4,0x9A,0x63,0x92,0x55,0x89,0x52,0x5B,0xCA,0x2E,0x34,0x25,0x4E,0x63,0x28,0x3A,0x50,0x95,0x26,0x8D,0xE6,0xAA,0x64,0x58,0xEA,0x92,0xCE,0xC2,0x46,0x15,0x9B,0x86,0xCD,0x2A,0x2E,0x37,0x00,0x00,0x00,0x0C,0xC8,0xDD,0x05,0x01,0xB9,0x33,0x21,0xA0,0x74,0xD7,0xFF,0x07}; -uint8_t spONE[] PROGMEM = {0xCC,0x67,0x75,0x42,0x59,0x5D,0x3A,0x4F,0x9D,0x36,0x63,0xB7,0x59,0xDC,0x30,0x5B,0x5C,0x23,0x61,0xF3,0xE2,0x1C,0xF1,0xF0,0x98,0xC3,0x4B,0x7D,0x39,0xCA,0x1D,0x2C,0x2F,0xB7,0x15,0xEF,0x70,0x79,0xBC,0xD2,0x46,0x7C,0x52,0xE5,0xF1,0x4A,0x6A,0xB3,0x71,0x47,0xC3,0x2D,0x39,0x34,0x4B,0x23,0x35,0xB7,0x7A,0x55,0x33,0x8F,0x59,0xDC,0xA2,0x44,0xB5,0xBC,0x66,0x72,0x8B,0x64,0xF5,0xF6,0x98,0xC1,0x4D,0x42,0xD4,0x27,0x62,0x38,0x2F,0x4A,0xB6,0x9C,0x88,0x68,0xBC,0xA6,0x95,0xF8,0x5C,0xA1,0x09,0x86,0x77,0x91,0x11,0x5B,0xFF,0x0F}; -uint8_t spTWO[] PROGMEM = {0x0E,0x38,0x6E,0x25,0x00,0xA3,0x0D,0x3A,0xA0,0x37,0xC5,0xA0,0x05,0x9E,0x56,0x35,0x86,0xAA,0x5E,0x8C,0xA4,0x82,0xB2,0xD7,0x74,0x31,0x22,0x69,0xAD,0x1C,0xD3,0xC1,0xD0,0xFA,0x28,0x2B,0x2D,0x47,0xC3,0x1B,0xC2,0xC4,0xAE,0xC6,0xCD,0x9C,0x48,0x53,0x9A,0xFF,0x0F}; -uint8_t spTHREE[] PROGMEM = {0x02,0xD8,0x2E,0x9C,0x01,0xDB,0xA6,0x33,0x60,0xFB,0x30,0x01,0xEC,0x20,0x12,0x8C,0xE4,0xD8,0xCA,0x32,0x96,0x73,0x63,0x41,0x39,0x89,0x98,0xC1,0x4D,0x0D,0xED,0xB0,0x2A,0x05,0x37,0x0F,0xB4,0xA5,0xAE,0x5C,0xDC,0x36,0xD0,0x83,0x2F,0x4A,0x71,0x7B,0x03,0xF7,0x38,0x59,0xCD,0xED,0x1E,0xB4,0x6B,0x14,0x35,0xB7,0x6B,0x94,0x99,0x91,0xD5,0xDC,0x26,0x48,0x77,0x4B,0x66,0x71,0x1B,0x21,0xDB,0x2D,0x8A,0xC9,0x6D,0x88,0xFC,0x26,0x28,0x3A,0xB7,0x21,0xF4,0x1F,0xA3,0x65,0xBC,0x02,0x38,0xBB,0x3D,0x8E,0xF0,0x2B,0xE2,0x08,0xB7,0x34,0xFF,0x0F}; -uint8_t spFOUR[] PROGMEM = {0x0C,0x18,0xB6,0x9A,0x01,0xC3,0x75,0x09,0x60,0xD8,0x0E,0x09,0x30,0xA0,0x9B,0xB6,0xA0,0xBB,0xB0,0xAA,0x16,0x4E,0x82,0xEB,0xEA,0xA9,0xFA,0x59,0x49,0x9E,0x59,0x23,0x9A,0x27,0x3B,0x78,0x66,0xAE,0x4A,0x9C,0x9C,0xE0,0x99,0xD3,0x2A,0xBD,0x72,0x92,0xEF,0xE6,0x88,0xE4,0x45,0x4D,0x7E,0x98,0x2D,0x62,0x67,0x37,0xF9,0xA1,0x37,0xA7,0x6C,0x94,0xE4,0xC7,0x1E,0xDC,0x3C,0xA5,0x83,0x1F,0x8B,0xEB,0x52,0x0E,0x0E,0x7E,0x2E,0x4E,0xC7,0x31,0xD2,0x79,0xA5,0x3A,0x0D,0xD9,0xC4,0xFF,0x07}; -uint8_t spFIVE[] PROGMEM = {0x02,0xE8,0x3E,0x8C,0x01,0xDD,0x65,0x08,0x60,0x98,0x4C,0x06,0x34,0x93,0xCE,0x80,0xE6,0xDA,0x9A,0x14,0x6B,0xAA,0x47,0xD1,0x5E,0x56,0xAA,0x6D,0x56,0xCD,0x78,0xD9,0xA9,0x1C,0x67,0x05,0x83,0xE1,0xA4,0xBA,0x38,0xEE,0x16,0x86,0x9B,0xFA,0x60,0x87,0x5B,0x18,0x6E,0xEE,0x8B,0x1D,0x6E,0x61,0xB9,0x69,0x36,0x65,0xBA,0x8D,0xE5,0xE5,0x3E,0x1C,0xE9,0x0E,0x96,0x9B,0x5B,0xAB,0x95,0x2B,0x58,0x6E,0xCE,0xE5,0x3A,0x6A,0xF3,0xB8,0x35,0x84,0x7B,0x05,0xA3,0xE3,0x36,0xEF,0x92,0x19,0xB4,0x86,0xDB,0xB4,0x69,0xB4,0xD1,0x2A,0x4E,0x65,0x9A,0x99,0xCE,0x28,0xD9,0x85,0x71,0x4C,0x18,0x6D,0x67,0x47,0xC6,0x5E,0x53,0x4A,0x9C,0xB5,0xE2,0x85,0x45,0x26,0xFE,0x7F}; -uint8_t spSIX[] PROGMEM = {0x0E,0xD8,0xAE,0xDD,0x03,0x0E,0x38,0xA6,0xD2,0x01,0xD3,0xB4,0x2C,0xAD,0x6A,0x35,0x9D,0xB1,0x7D,0xDC,0xEE,0xC4,0x65,0xD7,0xF1,0x72,0x47,0x24,0xB3,0x19,0xD9,0xD9,0x05,0x70,0x40,0x49,0xEA,0x02,0x98,0xBE,0x42,0x01,0xDF,0xA4,0x69,0x40,0x00,0xDF,0x95,0xFC,0x3F}; -uint8_t spSEVEN[] PROGMEM = {0x02,0xB8,0x3A,0x8C,0x01,0xDF,0xA4,0x73,0x40,0x01,0x47,0xB9,0x2F,0x33,0x3B,0x73,0x5F,0x53,0x7C,0xEC,0x9A,0xC5,0x63,0xD5,0xD1,0x75,0xAE,0x5B,0xFC,0x64,0x5C,0x35,0x87,0x91,0xF1,0x83,0x36,0xB5,0x68,0x55,0xC5,0x6F,0xDA,0x45,0x2D,0x1C,0x2D,0xB7,0x38,0x37,0x9F,0x60,0x3C,0xBC,0x9A,0x85,0xA3,0x25,0x66,0xF7,0x8A,0x57,0x1C,0xA9,0x67,0x56,0xCA,0x5E,0xF0,0xB2,0x16,0xB2,0xF1,0x89,0xCE,0x8B,0x92,0x25,0xC7,0x2B,0x33,0xCF,0x48,0xB1,0x99,0xB4,0xF3,0xFF}; -uint8_t spEIGHT[] PROGMEM = {0xC3,0x6C,0x86,0xB3,0x27,0x6D,0x0F,0xA7,0x48,0x99,0x4E,0x55,0x3C,0xBC,0x22,0x65,0x36,0x4D,0xD1,0xF0,0x32,0xD3,0xBE,0x34,0xDA,0xC3,0xEB,0x82,0xE2,0xDA,0x65,0x35,0xAF,0x31,0xF2,0x6B,0x97,0x95,0xBC,0x86,0xD8,0x6F,0x82,0xA6,0x73,0x0B,0xC6,0x9E,0x72,0x99,0xCC,0xCB,0x02,0xAD,0x3C,0x9A,0x10,0x60,0xAB,0x62,0x05,0x2C,0x37,0x84,0x00,0xA9,0x73,0x00,0x00,0xFE,0x1F}; -uint8_t spNINE[] PROGMEM = {0xCC,0xA1,0x26,0xBB,0x83,0x93,0x18,0xCF,0x4A,0xAD,0x2E,0x31,0xED,0x3C,0xA7,0x24,0x26,0xC3,0x54,0xF1,0x92,0x64,0x8B,0x8A,0x98,0xCB,0x2B,0x2E,0x34,0x53,0x2D,0x0E,0x2F,0x57,0xB3,0x0C,0x0D,0x3C,0xBC,0x3C,0x4C,0x4B,0xCA,0xF4,0xF0,0x72,0x0F,0x6E,0x49,0x53,0xCD,0xCB,0x53,0x2D,0x35,0x4D,0x0F,0x2F,0x0F,0xD7,0x0C,0x0D,0x3D,0xBC,0xDC,0x4D,0xD3,0xDD,0xC2,0xF0,0x72,0x52,0x4F,0x57,0x9B,0xC3,0xAB,0x89,0xBD,0x42,0x2D,0x0F,0xAF,0x5A,0xD1,0x71,0x91,0x55,0xBC,0x2C,0xC5,0x3B,0xD8,0x65,0xF2,0x82,0x94,0x18,0x4E,0x3B,0xC1,0x73,0x42,0x32,0x33,0x15,0x45,0x4F,0x79,0x52,0x6A,0x55,0xA6,0xA3,0xFF,0x07}; -uint8_t spTEN[] PROGMEM = {0x0E,0xD8,0xB1,0xDD,0x01,0x3D,0xA8,0x24,0x7B,0x04,0x27,0x76,0x77,0xDC,0xEC,0xC2,0xC5,0x23,0x84,0xCD,0x72,0x9A,0x51,0xF7,0x62,0x45,0xC7,0xEB,0x4E,0x35,0x4A,0x14,0x2D,0xBF,0x45,0xB6,0x0A,0x75,0xB8,0xFC,0x16,0xD9,0x2A,0xD9,0xD6,0x0A,0x5A,0x10,0xCD,0xA2,0x48,0x23,0xA8,0x81,0x35,0x4B,0x2C,0xA7,0x20,0x69,0x0A,0xAF,0xB6,0x15,0x82,0xA4,0x29,0x3C,0xC7,0x52,0x08,0xA2,0x22,0xCF,0x68,0x4B,0x2E,0xF0,0x8A,0xBD,0xA3,0x2C,0xAB,0x40,0x1B,0xCE,0xAA,0xB2,0x6C,0x82,0x40,0x4D,0x7D,0xC2,0x89,0x88,0x8A,0x61,0xCC,0x74,0xD5,0xFF,0x0F}; -uint8_t spELEVEN[] PROGMEM = {0xC3,0xCD,0x76,0x5C,0xAE,0x14,0x0F,0x37,0x9B,0x71,0xDE,0x92,0x55,0xBC,0x2C,0x27,0x70,0xD3,0x76,0xF0,0x83,0x5E,0xA3,0x5E,0x5A,0xC1,0xF7,0x61,0x58,0xA7,0x19,0x35,0x3F,0x99,0x31,0xDE,0x52,0x74,0xFC,0xA2,0x26,0x64,0x4B,0xD1,0xF1,0xAB,0xAE,0xD0,0x2D,0xC5,0xC7,0x2F,0x36,0xDD,0x27,0x15,0x0F,0x3F,0xD9,0x08,0x9F,0x62,0xE4,0xC2,0x2C,0xD4,0xD8,0xD3,0x89,0x0B,0x1B,0x57,0x11,0x0B,0x3B,0xC5,0xCF,0xD6,0xCC,0xC6,0x64,0x35,0xAF,0x18,0x73,0x1F,0xA1,0x5D,0xBC,0x62,0x45,0xB3,0x45,0x51,0xF0,0xA2,0x62,0xAB,0x4A,0x5B,0xC9,0x4B,0x8A,0x2D,0xB3,0x6C,0x06,0x2F,0x29,0xB2,0xAC,0x8A,0x18,0xBC,0x28,0xD9,0xAA,0xD2,0x92,0xF1,0xBC,0xE0,0x98,0x8C,0x48,0xCC,0x17,0x52,0xA3,0x27,0x6D,0x93,0xD0,0x4B,0x8E,0x0E,0x77,0x02,0x00,0xFF,0x0F}; -uint8_t spTWELVE[] PROGMEM = {0x06,0x28,0x46,0xD3,0x01,0x25,0x06,0x13,0x20,0xBA,0x70,0x70,0xB6,0x79,0xCA,0x36,0xAE,0x28,0x38,0xE1,0x29,0xC5,0x35,0xA3,0xE6,0xC4,0x16,0x6A,0x53,0x8C,0x97,0x9B,0x72,0x86,0x4F,0x28,0x1A,0x6E,0x0A,0x59,0x36,0xAE,0x68,0xF8,0x29,0x67,0xFA,0x06,0xA3,0x16,0xC4,0x96,0xE6,0x53,0xAC,0x5A,0x9C,0x56,0x72,0x77,0x31,0x4E,0x49,0x5C,0x8D,0x5B,0x29,0x3B,0x24,0x61,0x1E,0x6C,0x9B,0x6C,0x97,0xF8,0xA7,0x34,0x19,0x92,0x4C,0x62,0x9E,0x72,0x65,0x58,0x12,0xB1,0x7E,0x09,0xD5,0x2E,0x53,0xC5,0xBA,0x36,0x6B,0xB9,0x2D,0x17,0x05,0xEE,0x9A,0x6E,0x8E,0x05,0x50,0x6C,0x19,0x07,0x18,0x50,0xBD,0x3B,0x01,0x92,0x08,0x41,0x40,0x10,0xA6,0xFF,0x0F}; -uint8_t spTHIRTEEN[] PROGMEM = {0x08,0xE8,0x2C,0x15,0x01,0x43,0x07,0x13,0xE0,0x98,0xB4,0xA6,0x35,0xA9,0x1E,0xDE,0x56,0x8E,0x53,0x9C,0x7A,0xE7,0xCA,0x5E,0x76,0x8D,0x94,0xE5,0x2B,0xAB,0xD9,0xB5,0x62,0xA4,0x9C,0xE4,0xE6,0xB4,0x41,0x1E,0x7C,0xB6,0x93,0xD7,0x16,0x99,0x5A,0xCD,0x61,0x76,0x55,0xC2,0x91,0x61,0x1B,0xC0,0x01,0x5D,0x85,0x05,0xE0,0x68,0x51,0x07,0x1C,0xA9,0x64,0x80,0x1D,0x4C,0x9C,0x95,0x88,0xD4,0x04,0x3B,0x4D,0x4E,0x21,0x5C,0x93,0xA8,0x26,0xB9,0x05,0x4B,0x6E,0xA0,0xE2,0xE4,0x57,0xC2,0xB9,0xC1,0xB2,0x93,0x5F,0x09,0xD7,0x24,0xCB,0x4E,0x41,0x25,0x54,0x1D,0x62,0x3B,0x05,0x8D,0x52,0x57,0xAA,0xAD,0x10,0x24,0x26,0xE3,0xE1,0x36,0x5D,0x10,0x85,0xB4,0x97,0x85,0x72,0x41,0x14,0x52,0x5E,0x1A,0xCA,0xF9,0x91,0x6B,0x7A,0x5B,0xC4,0xE0,0x17,0x2D,0x54,0x1D,0x92,0x8C,0x1F,0x25,0x4B,0x8F,0xB2,0x16,0x41,0xA1,0x4A,0x3E,0xE6,0xFA,0xFF,0x01}; -uint8_t spFOURTEEN[] PROGMEM = {0x0C,0x58,0xAE,0x5C,0x01,0xD9,0x87,0x07,0x51,0xB7,0x25,0xB3,0x8A,0x15,0x2C,0xF7,0x1C,0x35,0x87,0x4D,0xB2,0xDD,0x53,0xCE,0x28,0x2B,0xC9,0x0E,0x97,0x2D,0xBD,0x2A,0x17,0x27,0x76,0x8E,0xD2,0x9A,0x6C,0x80,0x94,0x71,0x00,0x00,0x02,0xB0,0x58,0x58,0x00,0x9E,0x0B,0x0A,0xC0,0xB2,0xCE,0xC1,0xC8,0x98,0x7A,0x52,0x95,0x24,0x2B,0x11,0xED,0x36,0xD4,0x92,0xDC,0x4C,0xB5,0xC7,0xC8,0x53,0xF1,0x2A,0xE5,0x1A,0x17,0x55,0xC5,0xAF,0x94,0xBB,0xCD,0x1C,0x26,0xBF,0x52,0x9A,0x72,0x53,0x98,0xFC,0xC2,0x68,0xD2,0x4D,0x61,0xF0,0xA3,0x90,0xB6,0xD6,0x50,0xC1,0x8F,0x42,0xDA,0x4A,0x43,0x39,0x3F,0x48,0x2D,0x6B,0x33,0xF9,0xFF}; -uint8_t spFIFTEEN[] PROGMEM = {0x08,0xE8,0x2A,0x0D,0x01,0xDD,0xBA,0x31,0x60,0x6A,0xF7,0xA0,0xAE,0x54,0xAA,0x5A,0x76,0x97,0xD9,0x34,0x69,0xEF,0x32,0x1E,0x66,0xE1,0xE2,0xB3,0x43,0xA9,0x18,0x55,0x92,0x4E,0x37,0x2D,0x67,0x6F,0xDF,0xA2,0x5A,0xB6,0x04,0x30,0x55,0xA8,0x00,0x86,0x09,0xE7,0x00,0x01,0x16,0x17,0x05,0x70,0x40,0x57,0xE5,0x01,0xF8,0x21,0x34,0x00,0xD3,0x19,0x33,0x80,0x89,0x9A,0x62,0x34,0x4C,0xD5,0x49,0xAE,0x8B,0x53,0x09,0xF7,0x26,0xD9,0x6A,0x7E,0x23,0x5C,0x13,0x12,0xB3,0x04,0x9D,0x50,0x4F,0xB1,0xAD,0x14,0x15,0xC2,0xD3,0xA1,0xB6,0x42,0x94,0xA8,0x8C,0x87,0xDB,0x74,0xB1,0x70,0x59,0xE1,0x2E,0xC9,0xC5,0x81,0x5B,0x55,0xA4,0x4C,0x17,0x47,0xC1,0x6D,0xE3,0x81,0x53,0x9C,0x84,0x6A,0x46,0xD9,0x4C,0x51,0x31,0x42,0xD9,0x66,0xC9,0x44,0x85,0x29,0x6A,0x9B,0xAD,0xFF,0x07}; -uint8_t spSIXTEEN[] PROGMEM = {0x0A,0x58,0x5A,0x5D,0x00,0x93,0x97,0x0B,0x60,0xA9,0x48,0x05,0x0C,0x15,0xAE,0x80,0xAD,0x3D,0x14,0x30,0x7D,0xD9,0x50,0x92,0x92,0xAC,0x0D,0xC5,0xCD,0x2A,0x82,0xAA,0x3B,0x98,0x04,0xB3,0x4A,0xC8,0x9A,0x90,0x05,0x09,0x68,0x51,0xD4,0x01,0x23,0x9F,0x1A,0x60,0xA9,0x12,0x03,0xDC,0x50,0x81,0x80,0x22,0xDC,0x20,0x00,0xCB,0x06,0x3A,0x60,0x16,0xE3,0x64,0x64,0x42,0xDD,0xCD,0x6A,0x8A,0x5D,0x28,0x75,0x07,0xA9,0x2A,0x5E,0x65,0x34,0xED,0x64,0xBB,0xF8,0x85,0xF2,0x94,0x8B,0xAD,0xE4,0x37,0x4A,0x5B,0x21,0xB6,0x52,0x50,0x19,0xAD,0xA7,0xD8,0x4A,0x41,0x14,0xDA,0x5E,0x12,0x3A,0x04,0x91,0x4B,0x7B,0x69,0xA8,0x10,0x24,0x2E,0xE5,0xA3,0x81,0x52,0x90,0x94,0x5A,0x55,0x98,0x32,0x41,0x50,0xCC,0x93,0x2E,0x47,0x85,0x89,0x1B,0x5B,0x5A,0x62,0x04,0x44,0xE3,0x02,0x80,0x80,0x64,0xDD,0xFF,0x1F}; -uint8_t spSEVENTEEN[] PROGMEM = {0x02,0x98,0x3A,0x42,0x00,0x5B,0xA6,0x09,0x60,0xDB,0x52,0x06,0x1C,0x93,0x29,0x80,0xA9,0x52,0x87,0x9A,0xB5,0x99,0x4F,0xC8,0x3E,0x46,0xD6,0x5E,0x7E,0x66,0xFB,0x98,0xC5,0x5A,0xC6,0x9A,0x9C,0x63,0x15,0x6B,0x11,0x13,0x8A,0x9C,0x97,0xB9,0x9A,0x5A,0x39,0x71,0xEE,0xD2,0x29,0xC2,0xA6,0xB8,0x58,0x59,0x99,0x56,0x14,0xA3,0xE1,0x26,0x19,0x19,0xE3,0x8C,0x93,0x17,0xB4,0x46,0xB5,0x88,0x71,0x9E,0x97,0x9E,0xB1,0x2C,0xC5,0xF8,0x56,0xC4,0x58,0xA3,0x1C,0xE1,0x33,0x9D,0x13,0x41,0x8A,0x43,0x58,0xAD,0x95,0xA9,0xDB,0x36,0xC0,0xD1,0xC9,0x0E,0x58,0x4E,0x45,0x01,0x23,0xA9,0x04,0x37,0x13,0xAE,0x4D,0x65,0x52,0x82,0xCA,0xA9,0x37,0x99,0x4D,0x89,0xBA,0xC0,0xBC,0x14,0x36,0x25,0xEA,0x1C,0x73,0x52,0x1D,0x97,0xB8,0x33,0xAC,0x0E,0x75,0x9C,0xE2,0xCE,0xB0,0xDA,0xC3,0x51,0x4A,0x1A,0xA5,0xCA,0x70,0x5B,0x21,0xCE,0x4C,0x26,0xD2,0x6C,0xBA,0x38,0x71,0x2E,0x1F,0x2D,0xED,0xE2,0x24,0xB8,0xBC,0x3D,0x52,0x88,0xAB,0x50,0x8E,0xA8,0x48,0x22,0x4E,0x42,0xA0,0x26,0x55,0xFD,0x3F}; -uint8_t spEIGHTEEN[] PROGMEM = {0x2E,0x9C,0xD1,0x4D,0x54,0xEC,0x2C,0xBF,0x1B,0x8A,0x99,0x70,0x7C,0xFC,0x2E,0x29,0x6F,0x52,0xF6,0xF1,0xBA,0x20,0xBF,0x36,0xD9,0xCD,0xED,0x0C,0xF3,0x27,0x64,0x17,0x73,0x2B,0xA2,0x99,0x90,0x65,0xEC,0xED,0x40,0x73,0x32,0x12,0xB1,0xAF,0x30,0x35,0x0B,0xC7,0x00,0xE0,0x80,0xAE,0xDD,0x1C,0x70,0x43,0xAA,0x03,0x86,0x51,0x36,0xC0,0x30,0x64,0xCE,0x4C,0x98,0xFB,0x5C,0x65,0x07,0xAF,0x10,0xEA,0x0B,0x66,0x1B,0xFC,0x46,0xA8,0x3E,0x09,0x4D,0x08,0x2A,0xA6,0x3E,0x67,0x36,0x21,0x2A,0x98,0x67,0x9D,0x15,0xA7,0xA8,0x60,0xEE,0xB6,0x94,0x99,0xA2,0x4A,0x78,0x22,0xC2,0xA6,0x8B,0x8C,0x8E,0xCC,0x4C,0x8A,0x2E,0x8A,0x4C,0xD3,0x57,0x03,0x87,0x28,0x71,0x09,0x1F,0x2B,0xE4,0xA2,0xC4,0xC5,0x6D,0xAD,0x54,0x88,0xB2,0x63,0xC9,0xF2,0x50,0x2E,0x8A,0x4A,0x38,0x4A,0xEC,0x88,0x28,0x08,0xE3,0x28,0x49,0xF3,0xFF}; -uint8_t spNINETEEN[] PROGMEM = {0xC2,0xEA,0x8A,0x95,0x2B,0x6A,0x05,0x3F,0x71,0x71,0x5F,0x0D,0x12,0xFC,0x28,0x25,0x62,0x35,0xF0,0xF0,0xB3,0x48,0x1E,0x0F,0xC9,0xCB,0x2F,0x45,0x7C,0x2C,0x25,0x1F,0xBF,0x14,0xB3,0x2C,0xB5,0x75,0xFC,0x5A,0x5C,0xA3,0x5D,0xE1,0xF1,0x7A,0x76,0xB3,0x4E,0x45,0xC7,0xED,0x96,0x23,0x3B,0x18,0x37,0x7B,0x18,0xCC,0x09,0x51,0x13,0x4C,0xAB,0x6C,0x4C,0x4B,0x96,0xD2,0x49,0xAA,0x36,0x0B,0xC5,0xC2,0x20,0x26,0x27,0x35,0x63,0x09,0x3D,0x30,0x8B,0xF0,0x48,0x5C,0xCA,0x61,0xDD,0xCB,0xCD,0x91,0x03,0x8E,0x4B,0x76,0xC0,0xCC,0x4D,0x06,0x98,0x31,0x31,0x98,0x99,0x70,0x6D,0x2A,0xA3,0xE4,0x16,0xCA,0xBD,0xCE,0x5C,0x92,0x57,0x28,0xCF,0x09,0x69,0x2E,0x7E,0xA5,0x3C,0x63,0xA2,0x30,0x05,0x95,0xD2,0x74,0x98,0xCD,0x14,0x54,0xCA,0x53,0xA9,0x96,0x52,0x50,0x28,0x6F,0xBA,0xCB,0x0C,0x41,0x50,0xDE,0x65,0x2E,0xD3,0x05,0x89,0x4B,0x7B,0x6B,0x20,0x17,0x44,0xAE,0xED,0x23,0x81,0x52,0x90,0x85,0x73,0x57,0xD0,0x72,0x41,0xB1,0x02,0xDE,0x2E,0xDB,0x04,0x89,0x05,0x79,0xBB,0x62,0xE5,0x76,0x11,0xCA,0x61,0x0E,0xFF,0x1F}; -uint8_t spTWENTY[] PROGMEM = {0x01,0x98,0xD1,0xC2,0x00,0xCD,0xA4,0x32,0x20,0x79,0x13,0x04,0x28,0xE7,0x92,0xDC,0x70,0xCC,0x5D,0xDB,0x76,0xF3,0xD2,0x32,0x0B,0x0B,0x5B,0xC3,0x2B,0xCD,0xD4,0xDD,0x23,0x35,0xAF,0x44,0xE1,0xF0,0xB0,0x6D,0x3C,0xA9,0xAD,0x3D,0x35,0x0E,0xF1,0x0C,0x8B,0x28,0xF7,0x34,0x01,0x68,0x22,0xCD,0x00,0xC7,0xA4,0x04,0xBB,0x32,0xD6,0xAC,0x56,0x9C,0xDC,0xCA,0x28,0x66,0x53,0x51,0x70,0x2B,0xA5,0xBC,0x0D,0x9A,0xC1,0xEB,0x14,0x73,0x37,0x29,0x19,0xAF,0x33,0x8C,0x3B,0xA7,0x24,0xBC,0x42,0xB0,0xB7,0x59,0x09,0x09,0x3C,0x96,0xE9,0xF4,0x58,0xFF,0x0F}; -uint8_t spTHIRTY[] PROGMEM = {0x08,0x98,0xD6,0x15,0x01,0x43,0xBB,0x0A,0x20,0x1B,0x8B,0xE5,0x16,0xA3,0x1E,0xB6,0xB6,0x96,0x97,0x3C,0x57,0xD4,0x2A,0x5E,0x7E,0x4E,0xD8,0xE1,0x6B,0x7B,0xF8,0x39,0x63,0x0D,0x9F,0x95,0xE1,0xE7,0x4C,0x76,0xBC,0x91,0x5B,0x90,0x13,0xC6,0x68,0x57,0x4E,0x41,0x8B,0x10,0x5E,0x1D,0xA9,0x44,0xD3,0xBA,0x47,0xB8,0xDD,0xE4,0x35,0x86,0x11,0x93,0x94,0x92,0x5F,0x29,0xC7,0x4C,0x30,0x0C,0x41,0xC5,0x1C,0x3B,0x2E,0xD3,0x05,0x15,0x53,0x6C,0x07,0x4D,0x15,0x14,0x8C,0xB5,0xC9,0x6A,0x44,0x90,0x10,0x4E,0x9A,0xB6,0x21,0x81,0x23,0x3A,0x91,0x91,0xE8,0xFF,0x01}; -uint8_t spFOURTY[] PROGMEM = {0x04,0x18,0xB6,0x4C,0x00,0xC3,0x56,0x30,0xA0,0xE8,0xF4,0xA0,0x98,0x99,0x62,0x91,0xAE,0x83,0x6B,0x77,0x89,0x78,0x3B,0x09,0xAE,0xBD,0xA6,0x1E,0x63,0x3B,0x79,0x7E,0x71,0x5A,0x8F,0x95,0xE6,0xA5,0x4A,0x69,0xB9,0x4E,0x8A,0x5F,0x12,0x56,0xE4,0x58,0x69,0xE1,0x36,0xA1,0x69,0x2E,0x2B,0xF9,0x95,0x93,0x55,0x17,0xED,0xE4,0x37,0xC6,0xBA,0x93,0xB2,0x92,0xDF,0x19,0xD9,0x6E,0xC8,0x0A,0xFE,0x60,0xE8,0x37,0x21,0xC9,0xF9,0x8D,0x61,0x5F,0x32,0x13,0xE7,0x17,0x4C,0xD3,0xC6,0xB1,0x94,0x97,0x10,0x8F,0x8B,0xAD,0x11,0x7E,0xA1,0x9A,0x26,0x92,0xF6,0xFF,0x01}; -uint8_t spFIFTY[] PROGMEM = {0x08,0xE8,0x2E,0x84,0x00,0x23,0x84,0x13,0x60,0x38,0x95,0xA5,0x0F,0xCF,0xE2,0x79,0x8A,0x8F,0x37,0x02,0xB3,0xD5,0x2A,0x6E,0x5E,0x93,0x94,0x79,0x45,0xD9,0x05,0x5D,0x0A,0xB9,0x97,0x63,0x02,0x74,0xA7,0x82,0x80,0xEE,0xC3,0x10,0xD0,0x7D,0x28,0x03,0x6E,0x14,0x06,0x70,0xE6,0x0A,0xC9,0x9A,0x4E,0x37,0xD9,0x95,0x51,0xCE,0xBA,0xA2,0x14,0x0C,0x81,0x36,0x1B,0xB2,0x5C,0x30,0x38,0xFA,0x9C,0xC9,0x32,0x41,0xA7,0x18,0x3B,0xA2,0x48,0x04,0x05,0x51,0x4F,0x91,0x6D,0x12,0x04,0x20,0x9B,0x61,0x89,0xFF,0x1F}; -uint8_t spGOOD[] PROGMEM = {0x0A,0x28,0xCD,0x34,0x20,0xD9,0x1A,0x45,0x74,0xE4,0x66,0x24,0xAD,0xBA,0xB1,0x8C,0x9B,0x91,0xA5,0x64,0xE6,0x98,0x21,0x16,0x0B,0x96,0x9B,0x4C,0xE5,0xFF,0x01}; -uint8_t spMORNING[] PROGMEM = {0xCE,0x08,0x52,0x2A,0x35,0x5D,0x39,0x53,0x29,0x5B,0xB7,0x0A,0x15,0x0C,0xEE,0x2A,0x42,0x56,0x66,0xD2,0x55,0x2E,0x37,0x2F,0xD9,0x45,0xB3,0xD3,0xC5,0xCA,0x6D,0x27,0xD5,0xEE,0x50,0xF5,0x50,0x94,0x14,0x77,0x2D,0xD8,0x5D,0x49,0x92,0xFD,0xB1,0x64,0x2F,0xA9,0x49,0x0C,0x93,0x4B,0xAD,0x19,0x17,0x3E,0x66,0x1E,0xF1,0xA2,0x5B,0x84,0xE2,0x29,0x8F,0x8B,0x72,0x10,0xB5,0xB1,0x2E,0x4B,0xD4,0x45,0x89,0x4A,0xEC,0x5C,0x95,0x14,0x2B,0x8A,0x9C,0x34,0x52,0x5D,0xBC,0xCC,0xB5,0x3B,0x49,0x69,0x89,0x87,0xC1,0x98,0x56,0x3A,0x21,0x2B,0x82,0x67,0xCC,0x5C,0x85,0xB5,0x4A,0x8A,0xF6,0x64,0xA9,0x96,0xC4,0x69,0x3C,0x52,0x81,0x58,0x1C,0x97,0xF6,0x0E,0x1B,0xCC,0x0D,0x42,0x32,0xAA,0x65,0x12,0x67,0xD4,0x6A,0x61,0x52,0xFC,0xFF}; -uint8_t spAFTERNOON[] PROGMEM = {0xC7,0xCE,0xCE,0x3A,0xCB,0x58,0x1F,0x3B,0x07,0x9D,0x28,0x71,0xB4,0xAC,0x9C,0x74,0x5A,0x42,0x55,0x33,0xB2,0x93,0x0A,0x09,0xD4,0xC5,0x9A,0xD6,0x44,0x45,0xE3,0x38,0x60,0x9A,0x32,0x05,0xF4,0x18,0x01,0x09,0xD8,0xA9,0xC2,0x00,0x5E,0xCA,0x24,0xD5,0x5B,0x9D,0x4A,0x95,0xEA,0x34,0xEE,0x63,0x92,0x5C,0x4D,0xD0,0xA4,0xEE,0x58,0x0C,0xB9,0x4D,0xCD,0x42,0xA2,0x3A,0x24,0x37,0x25,0x8A,0xA8,0x8E,0xA0,0x53,0xE4,0x28,0x23,0x26,0x13,0x72,0x91,0xA2,0x76,0xBB,0x72,0x38,0x45,0x0A,0x46,0x63,0xCA,0x69,0x27,0x39,0x58,0xB1,0x8D,0x60,0x1C,0x34,0x1B,0x34,0xC3,0x55,0x8E,0x73,0x45,0x2D,0x4F,0x4A,0x3A,0x26,0x10,0xA1,0xCA,0x2D,0xE9,0x98,0x24,0x0A,0x1E,0x6D,0x97,0x29,0xD2,0xCC,0x71,0xA2,0xDC,0x86,0xC8,0x12,0xA7,0x8E,0x08,0x85,0x22,0x8D,0x9C,0x43,0xA7,0x12,0xB2,0x2E,0x50,0x09,0xEF,0x51,0xC5,0xBA,0x28,0x58,0xAD,0xDB,0xE1,0xFF,0x03}; -uint8_t spEVENING[] PROGMEM = {0xCD,0x6D,0x98,0x73,0x47,0x65,0x0D,0x6D,0x10,0xB2,0x5D,0x93,0x35,0x94,0xC1,0xD0,0x76,0x4D,0x66,0x93,0xA7,0x04,0xBD,0x71,0xD9,0x45,0xAE,0x92,0xD5,0xAC,0x53,0x07,0x6D,0xA5,0x76,0x63,0x51,0x92,0xD4,0xA1,0x83,0xD4,0xCB,0xB2,0x51,0x88,0xCD,0xF5,0x50,0x45,0xCE,0xA2,0x2E,0x27,0x28,0x54,0x15,0x37,0x0A,0xCF,0x75,0x61,0x5D,0xA2,0xC4,0xB5,0xC7,0x44,0x55,0x8A,0x0B,0xA3,0x6E,0x17,0x95,0x21,0xA9,0x0C,0x37,0xCD,0x15,0xBA,0xD4,0x2B,0x6F,0xB3,0x54,0xE4,0xD2,0xC8,0x64,0xBC,0x4C,0x91,0x49,0x12,0xE7,0xB2,0xB1,0xD0,0x22,0x0D,0x9C,0xDD,0xAB,0x62,0xA9,0x38,0x53,0x11,0xA9,0x74,0x2C,0xD2,0xCA,0x59,0x34,0xA3,0xE5,0xFF,0x03}; -uint8_t spPAUSE1[] PROGMEM = {0x00,0x00,0x00,0x00,0xFF,0x0F}; - -void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) ; - -void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) { - TTGO_PWR_ON - talkie = new AudioGeneratorTalkie(); - talkie->begin(nullptr, out); - - bool pm = (hour >= 12); - uint8_t *spHour[] = { spTWELVE, spONE, spTWO, spTHREE, spFOUR, spFIVE, spSIX, - spSEVEN, spEIGHT, spNINE, spTEN, spELEVEN }; - size_t spHourLen[] = { sizeof(spTWELVE), sizeof(spONE), sizeof(spTWO), - sizeof(spTHREE), sizeof(spFOUR), sizeof(spFIVE), - sizeof(spSIX), sizeof(spSEVEN), sizeof(spEIGHT), - sizeof(spNINE), sizeof(spTEN), sizeof(spELEVEN) }; - uint8_t *spMinDec[] = { spOH, spTEN, spTWENTY, spTHIRTY, spFOURTY, spFIFTY }; - size_t spMinDecLen[] = { sizeof(spOH), sizeof(spTEN), sizeof(spTWENTY), - sizeof(spTHIRTY), sizeof(spFOURTY), sizeof(spFIFTY) }; - uint8_t *spMinSpecial[] = { spELEVEN, spTWELVE, spTHIRTEEN, spFOURTEEN, - spFIFTEEN, spSIXTEEN, spSEVENTEEN, spEIGHTEEN, - spNINETEEN }; - size_t spMinSpecialLen[] = { sizeof(spELEVEN), sizeof(spTWELVE), - sizeof(spTHIRTEEN), sizeof(spFOURTEEN), - sizeof(spFIFTEEN), sizeof(spSIXTEEN), - sizeof(spSEVENTEEN), sizeof(spEIGHTEEN), - sizeof(spNINETEEN) }; - uint8_t *spMinLow[] = { spONE, spTWO, spTHREE, spFOUR, spFIVE, spSIX, - spSEVEN, spEIGHT, spNINE }; - size_t spMinLowLen[] = { sizeof(spONE), sizeof(spTWO), sizeof(spTHREE), - sizeof(spFOUR), sizeof(spFIVE), sizeof(spSIX), - sizeof(spSEVEN), sizeof(spEIGHT), sizeof(spNINE) }; - - talkie->say(spTHE, sizeof(spTHE)); - talkie->say(spTIME, sizeof(spTIME)); - talkie->say(spIS, sizeof(spIS)); - - hour = hour % 12; - talkie->say(spHour[hour], spHourLen[hour]); - if (minutes==0) { - talkie->say(spOCLOCK, sizeof(spOCLOCK)); - } else if (minutes<=10 || minutes >=20) { - talkie->say(spMinDec[minutes / 10], spMinDecLen[minutes /10]); - if (minutes % 10) { - talkie->say(spMinLow[(minutes % 10) - 1], spMinLowLen[(minutes % 10) - 1]); - } - } else { - talkie->say(spMinSpecial[minutes - 11], spMinSpecialLen[minutes - 11]); - } - if (pm) { - talkie->say(spP_M_, sizeof(spP_M_)); - } else { - talkie->say(spA_M_, sizeof(spA_M_)); - } - out->stop(); - delete talkie; - TTGO_PWR_OFF -} -#endif - - -uint8_t is2_volume; - -void I2S_Init(void) { - -#if EXTERNAL_DAC_PLAY - out = new AudioOutputI2S(); -#ifdef ESP32 - out->SetPinout(TWATCH_DAC_IIS_BCK, TWATCH_DAC_IIS_WS, TWATCH_DAC_IIS_DOUT); -#endif -#else - out = new AudioOutputI2S(0, 1); -#endif - - is2_volume=10; - out->SetGain(((float)is2_volume/100.0)*4.0); - out->stop(); - mp3ram = nullptr; - -#ifdef ESP32 - if (psramFound()) { - mp3ram = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - } - -#ifdef USE_WEBRADIO - if (psramFound()) { - preallocateBuffer = heap_caps_malloc(preallocateBufferSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - preallocateCodec = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - } else { - preallocateBuffer = malloc(preallocateBufferSize); - preallocateCodec = malloc(preallocateCodecSize); - } - if (!preallocateBuffer || !preallocateCodec) { - - } -#endif -#endif -} - -#ifdef ESP32 -TaskHandle_t mp3_task_h; - -void mp3_task(void *arg) { - while (1) { - while (mp3->isRunning()) { - if (!mp3->loop()) { - mp3->stop(); - mp3_delete(); - if (mp3_task_h) { - vTaskDelete(mp3_task_h); - mp3_task_h = 0; - } - - } - delay(1); - } - } -} -#endif - -#ifdef USE_WEBRADIO -void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str) { - const char *ptr = reinterpret_cast(cbData); - (void) isUnicode; - (void) ptr; - if (strstr_P(type, PSTR("Title"))) { - strncpy(wr_title, str, sizeof(wr_title)); - wr_title[sizeof(wr_title)-1] = 0; - - } else { - - } -} - -void StatusCallback(void *cbData, int code, const char *string) { - const char *ptr = reinterpret_cast(cbData); - (void) code; - (void) ptr; - - -} - -void Webradio(const char *url) { - if (decoder || mp3) return; - TTGO_PWR_ON - ifile = new AudioFileSourceICYStream(url); - ifile->RegisterMetadataCB(MDCallback, NULL); - buff = new AudioFileSourceBuffer(ifile, preallocateBuffer, preallocateBufferSize); - buff->RegisterStatusCB(StatusCallback, NULL); - decoder = new AudioGeneratorMP3(preallocateCodec, preallocateCodecSize); - decoder->RegisterStatusCB(StatusCallback, NULL); - decoder->begin(buff, out); - if (!decoder->isRunning()) { - - StopPlaying(); - - retryms = millis() + 2000; - } - - xTaskCreatePinnedToCore(mp3_task2, "MP3-2", I2SAUDIO_TASK_STACK_SIZE, NULL, 3, &mp3_task_h, 1); -} - -void mp3_task2(void *arg){ - while (1) { - if (decoder && decoder->isRunning()) { - if (!decoder->loop()) { - StopPlaying(); - - } - delay(1); - } - } -} - -void StopPlaying() { - - if (mp3_task_h) { - vTaskDelete(mp3_task_h); - mp3_task_h = nullptr; - } - - if (decoder) { - decoder->stop(); - delete decoder; - decoder = NULL; - } - if (buff) { - buff->close(); - delete buff; - buff = NULL; - } - if (ifile) { - ifile->close(); - delete ifile; - ifile = NULL; - } - TTGO_PWR_OFF -} - -void Cmd_WebRadio(void) { - if (decoder) { - StopPlaying(); - } - if (XdrvMailbox.data_len > 0) { - Webradio(XdrvMailbox.data); - ResponseCmndChar(XdrvMailbox.data); - } else { - ResponseCmndChar_P(PSTR("Stopped")); - } - -} - -const char HTTP_WEBRADIO[] PROGMEM = - "{s}" "I2S_WR-Title" "{m}%s{e}"; - -void I2S_WR_Show(void) { - if (decoder) { - WSContentSend_PD(HTTP_WEBRADIO,wr_title); - } -} - -#endif - -#ifdef ESP32 -void Play_mp3(const char *path) { -#if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS) - if (decoder || mp3) return; - - bool I2S_Task; - - TTGO_PWR_ON - if (*path=='+') { - I2S_Task = true; - path++; - } else { - I2S_Task = false; - } - - file = new AudioFileSourceFS(*fsp,path); - if (file->isOpen()) { - id3 = new AudioFileSourceID3(file); - - if (mp3ram) { - mp3 = new AudioGeneratorMP3(mp3ram, preallocateCodecSize); - } else { - mp3 = new AudioGeneratorMP3(); - } - mp3->begin(id3, out); - - if (I2S_Task) { - xTaskCreatePinnedToCore(mp3_task, "MP3", I2SAUDIO_TASK_STACK_SIZE, NULL, 3, &mp3_task_h, 1); - } else { - while (mp3->isRunning()) { - if (!mp3->loop()) { - mp3->stop(); - mp3_delete(); - break; - } - OsWatchLoop(); - } - } - } - -#endif -} - -void mp3_delete(void) { - delete file; - delete id3; - delete mp3; - mp3=nullptr; - TTGO_PWR_OFF -} -#endif - -void Say(char *text) { - - TTGO_PWR_ON - - out->begin(); - ESP8266SAM *sam = new ESP8266SAM; - sam->Say(out, text); - delete sam; - out->stop(); - - TTGO_PWR_OFF -} - - -const char kI2SAudio_Commands[] PROGMEM = "I2S|" - "Say|Gain|Time" -#ifdef ESP32 - "|Play" -#ifdef USE_WEBRADIO - "|WR" -#endif -#endif - ; - -void (* const I2SAudio_Command[])(void) PROGMEM = { - &Cmd_Say, &Cmd_Gain, &Cmd_Time -#ifdef ESP32 - ,&Cmd_Play -#ifdef USE_WEBRADIO - ,&Cmd_WebRadio -#endif -#endif -}; - - - -void Cmd_Play(void) { - if (XdrvMailbox.data_len > 0) { - Play_mp3(XdrvMailbox.data); - } - ResponseCmndChar(XdrvMailbox.data); -} - -void Cmd_Gain(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - if (out) { - is2_volume=XdrvMailbox.payload; - out->SetGain(((float)(is2_volume-2)/100.0)*4.0); - } - } - ResponseCmndNumber(is2_volume); -} - -void Cmd_Say(void) { - if (XdrvMailbox.data_len > 0) { - Say(XdrvMailbox.data); - } - ResponseCmndChar(XdrvMailbox.data); -} - -void Cmd_Time(void) { -#ifdef SAY_TIME - sayTime(RtcTime.hour, RtcTime.minute, talkie); -#endif - ResponseCmndDone(); -} - - - - - -bool Xdrv42(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kI2SAudio_Commands, I2SAudio_Command); - break; - case FUNC_INIT: - I2S_Init(); - break; -#ifdef USE_WEBSERVER -#ifdef USE_WEBRADIO - case FUNC_WEB_SENSOR: - I2S_WR_Show(); - break; -#endif -#endif - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_43_mlx90640.ino" -# 26 "/workspace/Tasmota/tasmota/xdrv_43_mlx90640.ino" -#ifdef USE_I2C -#ifdef USE_MLX90640 - -#define MLX90640_ADDRESS 0x33 -#define MLX90640_POI_NUM 6 - - - - - -#define XDRV_43 43 -#define XI2C_53 53 -#include - -const char MLX90640type[] PROGMEM = "MLX90640"; - -#ifdef USE_WEBSERVER -#define WEB_HANDLE_MLX90640 "mlx" -const char HTTP_BTN_MENU_MLX90640[] PROGMEM = "

"; -#endif - -struct { - uint32_t type:1; - uint32_t ready:1; - uint32_t dumpedEE:1; - uint32_t extractedParams:1; - paramsMLX90640 *params; - float Ta; - uint16_t Frame[834]; - float To[768]; - uint8_t pois[2*MLX90640_POI_NUM] = {2,1, 30,1, 10,12, 22,12, 2,23, 30,23}; -} MLX90640; - - - - - -#define D_CMND_MLX90640 "MLX" - -const char S_JSON_MLX90640_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\":%d}"; -const char S_JSON_MLX90640_COMMAND[] PROGMEM = "{\"" D_CMND_MLX90640 "%s\"}"; -const char kMLX90640_Commands[] PROGMEM = "POI"; - -enum MLX90640_Commands { - CMND_MLX90640_POI - }; - - - - -#ifdef USE_WEBSERVER - -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_MLX90640_1_SNS_SIZE = 389; -const char HTTP_MLX90640_1_SNS_COMPRESSED[] PROGMEM = "\x3D\x3C\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xDD\x33\x65\x1D\x86\xBB\x33\xB0\x41" - "\xA4\x7D\x9F\x81\xE7\x7A\x90\xDB\x18\x7C\x3B\xA6\x76\x10\xB6\x75\x1B\x0E\x43\xA8" - "\x8C\x8E\x43\xA8\x8D\x87\x28\xEA\x23\x23\x94\x77\x8F\x87\xE1\x02\x0D\x13\xAC\xD8" - "\x72\x1D\xE3\xD6\x77\x48\xC8\xE5\x1D\x64\x6C\x39\x47\x78\xEC\x3B\xA4\x64\x72\x1D" - "\x64\x6C\x39\x0E\xF1\xDB\x23\x61\xCA\x3C\x10\x20\xE3\x3A\x36\xC7\x9A\x3E\x2E\x63" - "\xE8\xB4\x6D\x8F\x33\xC1\x9D\xFD\x07\x7C\x67\x7E\x3A\x83\xA3\x61\xD4\x3D\xF1\x0F" - "\x06\x77\xF4\x3C\x43\x0D\x87\x50\xCC\xD3\xE1\xEF\x1E\xF9\xE0\xCE\xFE\xBE\x56\x7C" - "\x3D\xE3\xDF\x3C\x18\x17\xC1\xD6\xE7\x21\xE7\x44\x37\x05\xF9\x90\xCC\xF1\xDD\x04" - "\x2C\x65\x33\x3A\x3B\xC8\xF6\x82\x0E\x87\xF6\x1D\x23\xE0\x21\x66\x87\x41\xE7\x44" - "\x3B\x05\xF0\x9B\xC3\xC4\x18\x5A\xFA\x8B\xEC\x3A\x3B\xA7\x78\xF0\x67\x7F\x46\xC4" - "\x7C\x4C\xCE\x8E\x81\x85\xAF\xA8\x8D\x87\x5F\xD8\x74\x74\x09\x98\xA3\xC6\x98\x3B" - "\xA6\xC3\xF0\xE5\xD3\x3B\xC7\xB4\x8D\x87\xC3\x97\x11\xE0\xF7\x17\xDD\x0B\xFF\x23" - "\xDA\x6C\x3C\xD1\x0D\xBA\x14\x74\x30\x16\x67\xCE\xE8\xDB\x18\x77\x4D\x87\x51\xC6" - "\x75\x5D\x33\xA9\x9D\x57\x0E\x88\xEF\x1D\xE3\xA8\x8C\x81\x32\xF9\xDD\x04\x5D\x04" - "\x8C\x91\xD6\xBE\xC3\xA3\xA5\x60\xC3\xBC\x75\x1C\x67\x55\x63\x3A\x99\xD5\x56\x74" - "\x47\x78\xEF\x1E\xE3\xC1\xEE"; -#define HTTP_MLX90640_1_SNS Decompress(HTTP_MLX90640_1_SNS_COMPRESSED,HTTP_MLX90640_1_SNS_SIZE).c_str() -#else -const char HTTP_MLX90640_1_SNS[] PROGMEM = - "" -; -#endif -#ifdef USE_UNISHOX_COMPRESSION -const size_t HTTP_MLX90640_4b_SNS_SIZE = 418; -const char HTTP_MLX90640_4b_SNS_COMPRESSED[] PROGMEM = "\x3D\x07\x60\x86\x4B\x38\x2C\xB1\x0F\x87\xDF\x9D\x0B\x18\x77\x4E\xF1\xE0\xFB\x3F" - "\x0F\x40\xEF\x8C\xEF\xCB\x44\x3E\x1F\x63\x42\x36\x1F\x68\x7F\x44\xA1\x47\xC3\xEC" - "\xE5\xE3\x3E\xCE\xE1\x0A\x7A\x3C\x2A\x2B\x8F\x87\xD9\xCA\xC6\x7D\x9F\x87\xA1\xD8" - "\x40\x83\x83\x9F\x87\xA0\x9A\x66\x7E\x1E\x87\x60\x9A\x66\x7E\x1E\x9E\x61\x30\xE9" - "\x68\x87\xC3\xEC\x66\x69\x04\x7D\xAC\xE0\xC5\x5F\x0F\x33\xE1\xF6\x37\x3C\x77\x4E" - "\xF1\xF6\x7E\x1E\x98\x32\xB7\x39\x19\xD8\x42\xD9\xF0\xFB\x38\xCF\xB3\xF0\x88\x61" - "\x61\x69\xD6\x72\x1E\x87\x61\x02\x0D\x40\x4B\xB8\x72\x10\x20\xDC\x39\x44\x0A\x77" - "\x0E\x51\x02\x0D\xC3\x96\x40\xA7\x70\xE5\x90\x20\xDC\x39\x84\x0A\x77\x0E\x61\x02" - "\x0D\xC3\x9A\x40\xA7\x70\xE6\x90\x20\xDC\x39\xC4\x08\xB7\x0E\xC0\x41\xE1\x2A\x01" - "\xFC\x3D\x04\xD3\x30\x41\xE2\x0C\xE4\x3E\xC8\x10\xF8\x5B\x13\x4C\xCF\xC2\x18\x58" - "\x5A\x75\x9C\x67\x99\xDC\x3D\x0B\xC3\x2F\x96\x88\x7C\x3E\xEC\xE4\x3E\xCF\xC3\xD0" - "\xEC\x2F\x0C\xBE\x3F\x26\x3B\x32\xF2\x0D\x1D\xDF\x3E\xF6\x7C\xEF\x02\x2E\x1E\x08" - "\x39\x11\xCA\x20\x44\xC8\x8E\xC1\xD8\x21\x91\xF8"; -#define HTTP_MLX90640_4b_SNS Decompress(HTTP_MLX90640_4b_SNS_COMPRESSED,HTTP_MLX90640_4b_SNS_SIZE).c_str() -#else -const char HTTP_MLX90640_4b_SNS[] PROGMEM = - "" - "" - "
" - "" - "
" - "
POI-0: °C (sensor)
" - "
" - "" - ; -#endif -void MLX90640UpdateGUI(void){ - WSContentStart_P("mlx"); - WSContentSendStyle(); - WSContentSend_P(HTTP_MLX90640_1_SNS); - WSContentSend_P(HTTP_MLX90640_2a_SNS); - WSContentSend_P(HTTP_MLX90640_2b_SNS); - WSContentSend_P(HTTP_MLX90640_3a_SNS); - WSContentSend_P(HTTP_MLX90640_3b_SNS); - WSContentSend_P(HTTP_MLX90640_4a_SNS); - WSContentSend_P(HTTP_MLX90640_4b_SNS); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - -void MLX90640HandleWebGuiResponse(void){ - char tmp[(MLX90640_POI_NUM*2)+4]; - WebGetArg("ul", tmp, sizeof(tmp)); - if (strlen(tmp)) { - uint8_t _line = atoi(tmp); - - float _buf[65]; - if(_line==0){_buf[0]=1000+MLX90640.Ta;} - else{_buf[0]=(float)_line;} - memcpy((char*)&_buf[1],(char*)&MLX90640.To[_line*64],64*4); - Webserver->send(200,PSTR("application/octet-stream"),(const char*)&_buf,65*4); - return; - } - WebGetArg("up", tmp, sizeof(tmp)); - if (strlen(tmp)==1) { - Webserver->send(200,PSTR("application/octet-stream"),(const char*)&MLX90640.pois,MLX90640_POI_NUM*2); - return; - } - else if (strlen(tmp)>2) { - uint32_t _poi = atoi(tmp); - uint32_t _poiNum = (_poi-(_poi%10000))/10000; - MLX90640.pois[_poiNum*2] = (_poi%10000)/100; - MLX90640.pois[(_poiNum*2)+1] = _poi%100; - - for(int i = 0;i(MLX90640_POI_NUM-1)&&XdrvMailbox.index<1) return false; - _idx = (XdrvMailbox.index-1)*2; - if (XdrvMailbox.data_len > 0) { - uint32_t _coord = TextToInt(XdrvMailbox.data); - MLX90640.pois[_idx] = (_coord%10000)/100; - if(MLX90640.pois[_idx]>31) MLX90640.pois[_idx]=31; - MLX90640.pois[_idx+1] = _coord%100; - if(MLX90640.pois[_idx+1]>23) MLX90640.pois[_idx+1]=23; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("POI-%u = x:%u,y:%u"),XdrvMailbox.index,MLX90640.pois[_idx],MLX90640.pois[_idx+1]); - Response_P(S_JSON_MLX90640_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - -void MLX90640init() -{ - if (MLX90640.type || !I2cSetDevice(MLX90640_ADDRESS)) { return; } - - Wire.setClock(400000); - int status = -1; - if(!MLX90640.dumpedEE){ - status = MLX90640_DumpEE(MLX90640_ADDRESS, MLX90640.Frame); - if (status != 0){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("Failed to load system parameters")); - } - else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("MLX90640: started")); - MLX90640.type = true; - } - MLX90640.params = new paramsMLX90640; - } -} - - - - -void MLX90640every100msec(){ - static uint32_t _job = 0; - int status; - uint32_t _time; - - if(!MLX90640.extractedParams){ - static uint32_t _chunk = 0; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: will read chunk: %u"), _chunk); - _time = millis(); - status = MLX90640_ExtractParameters(MLX90640.Frame, MLX90640.params, _chunk); - if (status == 0){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: parameter received after: %u msec, status: %u"), TimePassedSince(_time), status); - } - if (_chunk == 5) MLX90640.extractedParams = true; - _chunk++; - return; - } - - switch(_job){ - case 0: - if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ - _job=-1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MLX90640: frame not ready")); - break; - } - - status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); - - break; - case 1: - MLX90640.Ta = MLX90640_GetTa(MLX90640.Frame, MLX90640.params); - break; - case 2: - - MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 0); - - break; - case 5: - if(MLX90640_SynchFrame(MLX90640_ADDRESS)!=0){ - _job=4; - break; - } - - status = MLX90640_GetFrameData(MLX90640_ADDRESS, MLX90640.Frame); - - break; - case 7: - - MLX90640_CalculateTo(MLX90640.Frame, MLX90640.params, 0.95f, MLX90640.Ta - 8, MLX90640.To, 1); - - break; - default: - break; - } - _job++; - if(_job>10) _job=0; -} - - - - - - -void MLX90640Show(uint8_t json) -{ - char amb_tstr[FLOATSZ]; - dtostrfd(MLX90640.Ta, Settings.flag2.temperature_resolution, amb_tstr); - if (json) { - ResponseAppend_P(PSTR(",\"MLX90640\":{\"" D_JSON_TEMPERATURE "\":[%s"), amb_tstr); - for(int i = 0;i - - -struct miel_hvac_header { - uint8_t start; -#define MIEL_HVAC_H_START 0xfc - uint8_t type; -#define MIEL_HVAC_H_TYPE_UPDATED 0x61 -#define MIEL_HVAC_H_TYPE_DATA 0x62 -#define MIEL_HVAC_H_TYPE_CONNECTED 0x7a - uint8_t middle1; -#define MIEL_HVAC_H_MIDDLE1 0x01 - uint8_t middle2; -#define MIEL_HVAC_H_MIDDLE2 0x30 - uint8_t len; -}; - -struct miel_hvac_data_settings { - uint8_t _pad1[2]; - uint8_t power; - uint8_t mode; -#define MIEL_HVAC_SETTINGS_MODE_MASK 0x7f - uint8_t temp; - uint8_t fan; - uint8_t vane; - uint8_t _pad2[2]; - uint8_t widevane; -#define MIEL_HVAC_SETTTINGS_WIDEVANE_MASK \ - 0x0f -}; - -struct miel_hvac_data_roomtemp { - uint8_t _pad1[2]; - uint8_t temp; -}; - -struct miel_hvac_data_status { - uint8_t _pad1[2]; - uint8_t compressor; - uint8_t operation; -}; - -struct miel_hvac_data { - uint8_t type; -#define MIEL_HVAC_DATA_T_SETTINGS 0x02 -#define MIEL_HVAC_DATA_T_ROOMTEMP 0x03 -#define MIEL_HVAC_DATA_T_TIMER 0x05 -#define MIEL_HVAC_DATA_T_STATUS 0x06 -#define MIEL_HVAC_DATA_T_STAGE 0x09 - - union { - struct miel_hvac_data_settings - settings; - struct miel_hvac_data_roomtemp - roomtemp; - struct miel_hvac_data_status - status; - - uint8_t bytes[15]; - } data; -}; - -CTASSERT(sizeof(struct miel_hvac_data) == 16); - -CTASSERT(offsetof(struct miel_hvac_data, data.settings.power) == 3); -CTASSERT(offsetof(struct miel_hvac_data, data.settings.mode) == 4); -CTASSERT(offsetof(struct miel_hvac_data, data.settings.temp) == 5); -CTASSERT(offsetof(struct miel_hvac_data, data.settings.fan) == 6); -CTASSERT(offsetof(struct miel_hvac_data, data.settings.vane) == 7); -CTASSERT(offsetof(struct miel_hvac_data, data.settings.widevane) == 10); - -CTASSERT(offsetof(struct miel_hvac_data, data.roomtemp.temp) == 3); - - - -#define MIEL_HVAC_H_TYPE_CONNECT 0x5a -static const uint8_t miel_hvac_msg_connect[] = { 0xca, 0x01 }; - -#define MIEL_HVAC_H_TYPE_REQUEST 0x42 - -struct miel_hvac_msg_request { - uint8_t type; -#define MIEL_HVAC_REQUEST_SETTINGS 0x02 -#define MIEL_HVAC_REQUEST_ROOMTEMP 0x03 -#define MIEL_HVAC_REQUEST_TIMERS 0x05 -#define MIEL_HVAC_REQUEST_STATUS 0x06 -#define MIEL_HVAC_REQUEST_STAGE 0x09 - uint8_t zero[15]; -}; - -#define MIEL_HVAC_H_TYPE_UPDATE 0x41 - -struct miel_hvac_msg_update { - uint8_t one; - uint16_t flags; -#define MIEL_HVAC_UPDATE_F_WIDEVANE (1 << 0) -#define MIEL_HVAC_UPDATE_F_POWER (1 << 8) -#define MIEL_HVAC_UPDATE_F_MODE (1 << 9) -#define MIEL_HVAC_UPDATE_F_TEMP (1 << 10) -#define MIEL_HVAC_UPDATE_F_FAN (1 << 11) -#define MIEL_HVAC_UPDATE_F_VANE (1 << 12) - uint8_t power; -#define MIEL_HVAC_UPDATE_POWER_OFF 0x00 -#define MIEL_HVAC_UPDATE_POWER_ON 0x01 - uint8_t mode; -#define MIEL_HVAC_UPDATE_MODE_HEAT 0x01 -#define MIEL_HVAC_UPDATE_MODE_DRY 0x02 -#define MIEL_HVAC_UPDATE_MODE_COOL 0x03 -#define MIEL_HVAC_UPDATE_MODE_FAN 0x07 -#define MIEL_HVAC_UPDATE_MODE_AUTO 0x08 - uint8_t temp; -#define MIEL_HVAC_UPDATE_TEMP_MIN 16 -#define MIEL_HVAC_UPDATE_TEMP_MAX 31 - uint8_t fan; -#define MIEL_HVAC_UPDATE_FAN_AUTO 0x00 -#define MIEL_HVAC_UPDATE_FAN_QUIET 0x01 -#define MIEL_HVAC_UPDATE_FAN_1 0x02 -#define MIEL_HVAC_UPDATE_FAN_2 0x03 -#define MIEL_HVAC_UPDATE_FAN_3 0x05 -#define MIEL_HVAC_UPDATE_FAN_4 0x06 - uint8_t vane; -#define MIEL_HVAC_UPDATE_VANE_AUTO 0x00 -#define MIEL_HVAC_UPDATE_VANE_1 0x01 -#define MIEL_HVAC_UPDATE_VANE_2 0x02 -#define MIEL_HVAC_UPDATE_VANE_3 0x03 -#define MIEL_HVAC_UPDATE_VANE_4 0x04 -#define MIEL_HVAC_UPDATE_VANE_5 0x05 -#define MIEL_HVAC_UPDATE_VANE_SWING 0x07 - uint8_t _pad1[5]; - uint8_t widevane; -#define MIEL_HVAC_UPDATE_WIDEVANE_MASK 0x0f -#define MIEL_HVAC_UPDATE_WIDEVANE_LL 0x01 -#define MIEL_HVAC_UPDATE_WIDEVANE_L 0x02 -#define MIEL_HVAC_UPDATE_WIDEVANE_LL 0x01 -#define MIEL_HVAC_UPDATE_WIDEVANE_L 0x02 -#define MIEL_HVAC_UPDATE_WIDEVANE_C 0x03 -#define MIEL_HVAC_UPDATE_WIDEVANE_R 0x04 -#define MIEL_HVAC_UPDATE_WIDEVANE_RR 0x05 -#define MIEL_HVAC_UPDATE_WIDEVANE_LR 0x08 -#define MIEL_HVAC_UPDATE_WIDEVANE_SWING 0x0c -#define MIEL_HVAC_UPDATE_WIDEVANE_ADJ 0x80 - uint8_t _pad2[2]; -} __packed; - -CTASSERT(sizeof(struct miel_hvac_msg_update) == 16); -#define MIEL_HVAC_OFFS(_v) ((_v) - sizeof(struct miel_hvac_header)) -CTASSERT(offsetof(struct miel_hvac_msg_update, flags) == MIEL_HVAC_OFFS(6)); -CTASSERT(offsetof(struct miel_hvac_msg_update, power) == MIEL_HVAC_OFFS(8)); -CTASSERT(offsetof(struct miel_hvac_msg_update, mode) == MIEL_HVAC_OFFS(9)); -CTASSERT(offsetof(struct miel_hvac_msg_update, temp) == MIEL_HVAC_OFFS(10)); -CTASSERT(offsetof(struct miel_hvac_msg_update, fan) == MIEL_HVAC_OFFS(11)); -CTASSERT(offsetof(struct miel_hvac_msg_update, vane) == MIEL_HVAC_OFFS(12)); -CTASSERT(offsetof(struct miel_hvac_msg_update, widevane) == MIEL_HVAC_OFFS(18)); - -static inline uint8_t -miel_hvac_deg2temp(uint8_t deg) -{ - return (31 - deg); -} - -static inline uint8_t -miel_hvac_temp2deg(uint8_t temp) -{ - return (31 - temp); -} - -static inline unsigned int -miel_hvac_roomtemp2deg(uint8_t roomtemp) -{ - return ((unsigned int)roomtemp + 10); -} - -struct miel_hvac_msg_remotetemp { - uint8_t seven; - uint8_t control; -#define MIEL_HVAC_REMOTETEMP_CLR 0x00 -#define MIEL_HVAC_REMOTETEMP_SET 0x01 - - uint8_t temp_old; -#define MIEL_HVAC_REMOTETEMP_OLD_MIN 8 -#define MIEL_HVAC_REMOTETEMP_OLD_MAX 38 -#define MIEL_HVAC_REMOTETEMP_OLD_FACTOR 2 - - uint8_t temp; -#define MIEL_HVAC_REMOTETEMP_MIN -63 -#define MIEL_HVAC_REMOTETEMP_MAX 63 -#define MIEL_HVAC_REMOTETEMP_OFFSET 64 -#define MIEL_HVAC_REMOTETEMP_FACTOR 2 - uint8_t _pad2[12]; -}; - -CTASSERT(sizeof(struct miel_hvac_msg_remotetemp) == 16); - -static inline uint8_t -miel_hvac_cksum_fini(uint8_t sum) -{ - return (0xfc - sum); -} - -struct miel_hvac_map { - uint8_t byte; - const char *name; -}; - -static const struct miel_hvac_map miel_hvac_mode_map[] = { - { MIEL_HVAC_UPDATE_MODE_HEAT, "heat" }, - { MIEL_HVAC_UPDATE_MODE_DRY, "dry" }, - { MIEL_HVAC_UPDATE_MODE_COOL, "cool" }, - { MIEL_HVAC_UPDATE_MODE_FAN, "fan_only" }, - { MIEL_HVAC_UPDATE_MODE_AUTO, "auto" }, -}; - -static const struct miel_hvac_map miel_hvac_fan_map[] = { - { MIEL_HVAC_UPDATE_FAN_AUTO, "auto" }, - { MIEL_HVAC_UPDATE_FAN_QUIET, "quiet" }, - { MIEL_HVAC_UPDATE_FAN_1, "1" }, - { MIEL_HVAC_UPDATE_FAN_2, "2" }, - { MIEL_HVAC_UPDATE_FAN_3, "3" }, - { MIEL_HVAC_UPDATE_FAN_4, "4" }, -}; - -static const struct miel_hvac_map miel_hvac_vane_map[] = { - { MIEL_HVAC_UPDATE_VANE_AUTO, "auto" }, - { MIEL_HVAC_UPDATE_VANE_1, "1" }, - { MIEL_HVAC_UPDATE_VANE_2, "2" }, - { MIEL_HVAC_UPDATE_VANE_3, "3" }, - { MIEL_HVAC_UPDATE_VANE_4, "4" }, - { MIEL_HVAC_UPDATE_VANE_5, "5" }, - { MIEL_HVAC_UPDATE_VANE_SWING, "swing" }, -}; - -static const struct miel_hvac_map miel_hvac_widevane_map[] = { - { MIEL_HVAC_UPDATE_WIDEVANE_LL, "LL" }, - { MIEL_HVAC_UPDATE_WIDEVANE_L, "L" }, - { MIEL_HVAC_UPDATE_WIDEVANE_C, "C" }, - { MIEL_HVAC_UPDATE_WIDEVANE_R, "R" }, - { MIEL_HVAC_UPDATE_WIDEVANE_RR, "RR" }, - { MIEL_HVAC_UPDATE_WIDEVANE_LR, "split" }, - { MIEL_HVAC_UPDATE_WIDEVANE_SWING, "swing" }, -}; - -enum miel_hvac_parser_state { - MIEL_HVAC_P_START, - MIEL_HVAC_P_TYPE, - MIEL_HVAC_P_MIDDLE1, - MIEL_HVAC_P_MIDDLE2, - MIEL_HVAC_P_LEN, - MIEL_HVAC_P_DATA, - MIEL_HVAC_P_CKSUM, - - MIEL_HVAC_P_SKIP, - MIEL_HVAC_P_SKIP_CKSUM, -}; - -#define MIEL_HVAC_DATABUFLEN 64 - -struct miel_hvac_parser { - enum miel_hvac_parser_state - p_state; - uint8_t p_type; - uint8_t p_sum; - uint8_t p_len; - uint8_t p_off; - uint8_t p_data[MIEL_HVAC_DATABUFLEN]; -}; - -struct miel_hvac_softc { - TasmotaSerial *sc_serial; - struct miel_hvac_parser sc_parser; - - unsigned int sc_device; - unsigned int sc_tick; - bool sc_settings_set; - bool sc_connected; - - struct miel_hvac_data sc_settings; - struct miel_hvac_data sc_temp; - struct miel_hvac_data sc_status; - struct miel_hvac_data sc_stage; - - struct miel_hvac_msg_update - sc_update; - struct miel_hvac_msg_remotetemp - sc_remotetemp; -}; - -static inline bool -miel_hvac_update_pending(struct miel_hvac_softc *sc) -{ - struct miel_hvac_msg_update *update = &sc->sc_update; - - return (update->flags != htons(0)); -} - -static struct miel_hvac_softc *miel_hvac_sc = nullptr; - -static void miel_hvac_input_connected(struct miel_hvac_softc *, - const void *, size_t); -static void miel_hvac_input_data(struct miel_hvac_softc *, - const void *, size_t); -static void miel_hvac_input_updated(struct miel_hvac_softc *, - const void *, size_t); - -static enum miel_hvac_parser_state -miel_hvac_parse(struct miel_hvac_softc *sc, uint8_t byte) -{ - struct miel_hvac_parser *p = &sc->sc_parser; - enum miel_hvac_parser_state nstate = p->p_state; - - switch (p->p_state) { - case MIEL_HVAC_P_START: - if (byte != MIEL_HVAC_H_START) - return (MIEL_HVAC_P_START); - - - p->p_sum = 0; - - nstate = MIEL_HVAC_P_TYPE; - break; - - case MIEL_HVAC_P_TYPE: - p->p_type = byte; - nstate = MIEL_HVAC_P_MIDDLE1; - break; - - case MIEL_HVAC_P_MIDDLE1: - if (byte != MIEL_HVAC_H_MIDDLE1) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": parse state MIDDLE1 expected %02x got %02x" - ", restarting"), MIEL_HVAC_H_MIDDLE1, byte); - return (MIEL_HVAC_P_START); - } - - nstate = MIEL_HVAC_P_MIDDLE2; - break; - - case MIEL_HVAC_P_MIDDLE2: - if (byte != MIEL_HVAC_H_MIDDLE2) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": parse state MIDDLE2 expected %02x got %02x" - ", restarting"), MIEL_HVAC_H_MIDDLE2, byte); - return (MIEL_HVAC_P_START); - } - - nstate = MIEL_HVAC_P_LEN; - break; - - case MIEL_HVAC_P_LEN: - if (byte == 0) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": skipping 0 byte message type 0x%02x"), - p->p_type); - return (MIEL_HVAC_P_SKIP_CKSUM); - } - - p->p_len = byte; - p->p_off = 0; - - switch (p->p_type) { - case MIEL_HVAC_H_TYPE_CONNECTED: - case MIEL_HVAC_H_TYPE_DATA: - case MIEL_HVAC_H_TYPE_UPDATED: - break; - default: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": skipping unknown message type 0x%02x"), - p->p_type); - return (MIEL_HVAC_P_SKIP); - } - - if (byte > sizeof(p->p_data)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": skipping %u data bytes of message type 0x%02x"), - p->p_len, p->p_type); - return (MIEL_HVAC_P_SKIP); - } - - nstate = MIEL_HVAC_P_DATA; - break; - - case MIEL_HVAC_P_DATA: - p->p_data[p->p_off++] = byte; - if (p->p_off >= p->p_len) - nstate = MIEL_HVAC_P_CKSUM; - break; - - case MIEL_HVAC_P_CKSUM: - if (miel_hvac_cksum_fini(p->p_sum) != byte) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": checksum failed, restarting")); - return (MIEL_HVAC_P_START); - } - - switch (p->p_type) { - case MIEL_HVAC_H_TYPE_CONNECTED: - miel_hvac_input_connected(sc, p->p_data, p->p_len); - break; - case MIEL_HVAC_H_TYPE_DATA: - miel_hvac_input_data(sc, p->p_data, p->p_len); - break; - case MIEL_HVAC_H_TYPE_UPDATED: - miel_hvac_input_updated(sc, p->p_data, p->p_len); - break; - } - - - return (MIEL_HVAC_P_START); - - case MIEL_HVAC_P_SKIP: - if (++p->p_off >= p->p_len) - return (MIEL_HVAC_P_SKIP_CKSUM); - return (nstate); - case MIEL_HVAC_P_SKIP_CKSUM: - return (MIEL_HVAC_P_START); - } - - p->p_sum += byte; - - return (nstate); -} - -static uint8_t -miel_hvac_write(struct miel_hvac_softc *sc, const uint8_t *bytes, size_t len) -{ - TasmotaSerial *serial = sc->sc_serial; - uint8_t cksum = 0; - size_t i; - - for (i = 0; i < len; i++) { - uint8_t b = bytes[i]; - serial->write(b); - cksum += b; - } - - return (cksum); -} - -static void -miel_hvac_send(struct miel_hvac_softc *sc, uint8_t type, - const void *data, size_t len) -{ - TasmotaSerial *serial = sc->sc_serial; - struct miel_hvac_header h = { - MIEL_HVAC_H_START, - type, - MIEL_HVAC_H_MIDDLE1, - MIEL_HVAC_H_MIDDLE2, - (uint8_t)len, - }; - uint8_t cksum = 0; - - cksum += miel_hvac_write(sc, (const uint8_t *)&h, sizeof(h)); - cksum += miel_hvac_write(sc, (const uint8_t *)data, len); - - char hex_h[(sizeof(h) + 1) * 2]; - char hex_d[(len + 1) * 2]; - AddLog_P2(LOG_LEVEL_DEBUG, - PSTR(MIEL_HVAC_LOGNAME ": sending %s %s %02x"), - ToHex_P((uint8_t *)&h, sizeof(h), hex_h, sizeof(hex_h)), - ToHex_P((uint8_t *)data, len, hex_d, sizeof(hex_d)), - miel_hvac_cksum_fini(cksum)); - - serial->write(miel_hvac_cksum_fini(cksum)); - serial->flush(); -} - -#define miel_hvac_send_connect(_sc) \ - miel_hvac_send((_sc), MIEL_HVAC_H_TYPE_CONNECT, \ - miel_hvac_msg_connect, sizeof(miel_hvac_msg_connect)) - -static const struct miel_hvac_map * -miel_hvac_map_byname(const char *name, - const struct miel_hvac_map *m, size_t n) -{ - const struct miel_hvac_map *e; - size_t i; - - for (i = 0; i < n; i++) { - e = &m[i]; - if (strcasecmp(e->name, name) == 0) - return (e); - } - - return (NULL); -} - -static const char * -miel_hvac_map_byval(uint8_t byte, - const struct miel_hvac_map *m, size_t n) -{ - const struct miel_hvac_map *e; - size_t i; - - for (i = 0; i < n; i++) { - e = &m[i]; - if (byte == e->byte) - return (e->name); - } - - return (NULL); -} - -static void -miel_hvac_request(struct miel_hvac_softc *sc, uint8_t type) -{ - struct miel_hvac_msg_request request = { type }; - - miel_hvac_send(sc, MIEL_HVAC_H_TYPE_REQUEST, - &request, sizeof(request)); -} - -static void -miel_hvac_init_update(struct miel_hvac_msg_update *update) -{ - memset(update, 0, sizeof(*update)); - update->one = 1; -} - -static inline void -miel_hvac_send_update(struct miel_hvac_softc *sc, - const struct miel_hvac_msg_update *update) -{ - miel_hvac_send(sc, MIEL_HVAC_H_TYPE_UPDATE, update, sizeof(*update)); -} - -static inline void -miel_hvac_send_remotetemp(struct miel_hvac_softc *sc, - const struct miel_hvac_msg_remotetemp *remotetemp) -{ - miel_hvac_send(sc, MIEL_HVAC_H_TYPE_UPDATE, - remotetemp, sizeof(*remotetemp)); -} - -static bool -miel_hvac_set_power(struct miel_hvac_softc *sc) -{ - struct miel_hvac_msg_update *update = &sc->sc_update; - uint16_t source = XdrvMailbox.payload; - - if (source == SRC_SWITCH) - return (false); - - update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER); - update->power = (XdrvMailbox.index & (1 << sc->sc_device)) ? - MIEL_HVAC_UPDATE_POWER_ON : MIEL_HVAC_UPDATE_POWER_OFF; - - return (true); -} - -static void -miel_hvac_respond_unsupported(void) -{ - ResponseCmndChar_P(PSTR("Unsupported")); -} - -static void -miel_hvac_cmnd_setfanspeed(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - const struct miel_hvac_map *e; - - if (XdrvMailbox.data_len == 0) - return; - - e = miel_hvac_map_byname(XdrvMailbox.data, - miel_hvac_fan_map, nitems(miel_hvac_fan_map)); - if (e == NULL) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_FAN); - update->fan = e->byte; - - ResponseCmndChar_P(e->name); -} - -static void -miel_hvac_cmnd_setmode(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - const struct miel_hvac_map *e; - - if (XdrvMailbox.data_len == 0) - return; - - e = miel_hvac_map_byname(XdrvMailbox.data, - miel_hvac_mode_map, nitems(miel_hvac_mode_map)); - if (e == NULL) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_MODE); - update->mode = e->byte; - - ResponseCmndChar_P(e->name); -} - -static void -miel_hvac_cmnd_sethamode(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - const struct miel_hvac_map *e; - - if (XdrvMailbox.data_len == 0) - return; - - if (strcasecmp(XdrvMailbox.data, "off") == 0) { - update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER); - update->power = MIEL_HVAC_UPDATE_POWER_OFF; - ResponseCmndChar_P(PSTR("off")); - return; - } - - - - - - - e = miel_hvac_map_byname(XdrvMailbox.data, - miel_hvac_mode_map, nitems(miel_hvac_mode_map)); - if (e == NULL) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_POWER) | - htons(MIEL_HVAC_UPDATE_F_MODE); - update->power = MIEL_HVAC_UPDATE_POWER_ON; - update->mode = e->byte; - - ResponseCmndChar_P(e->name); -} - -static void -miel_hvac_cmnd_settemp(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - unsigned long degc; - - if (XdrvMailbox.data_len == 0) - return; - - degc = strtoul(XdrvMailbox.data, nullptr, 0); - if (degc < MIEL_HVAC_UPDATE_TEMP_MIN || - degc > MIEL_HVAC_UPDATE_TEMP_MAX) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_TEMP); - update->temp = miel_hvac_deg2temp(degc); - - ResponseCmndNumber(degc); -} - -static void -miel_hvac_cmnd_setvane(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - const struct miel_hvac_map *e; - - if (XdrvMailbox.data_len == 0) - return; - - e = miel_hvac_map_byname(XdrvMailbox.data, - miel_hvac_vane_map, nitems(miel_hvac_vane_map)); - if (e == NULL) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_VANE); - update->vane = e->byte; - - ResponseCmndChar_P(e->name); -} - -static void -miel_hvac_cmnd_setwidevane(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_update *update = &sc->sc_update; - const struct miel_hvac_map *e; - - if (XdrvMailbox.data_len == 0) - return; - - e = miel_hvac_map_byname(XdrvMailbox.data, - miel_hvac_widevane_map, nitems(miel_hvac_widevane_map)); - if (e == NULL) { - miel_hvac_respond_unsupported(); - return; - } - - update->flags |= htons(MIEL_HVAC_UPDATE_F_WIDEVANE); - update->widevane = e->byte; - - ResponseCmndChar_P(e->name); -} - -static inline uint8_t -miel_hvac_remotetemp_degc2old(long degc) -{ -# 760 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" - if (degc < MIEL_HVAC_REMOTETEMP_OLD_MIN) - degc = MIEL_HVAC_REMOTETEMP_OLD_MIN; - else if (degc > MIEL_HVAC_REMOTETEMP_OLD_MAX) - degc = MIEL_HVAC_REMOTETEMP_OLD_MIN; - - return ((degc - MIEL_HVAC_REMOTETEMP_OLD_MIN) * - MIEL_HVAC_REMOTETEMP_OLD_FACTOR); -} - -static void -miel_hvac_cmnd_remotetemp(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - struct miel_hvac_msg_remotetemp *rt = &sc->sc_remotetemp; - uint8_t control = MIEL_HVAC_REMOTETEMP_SET; - long degc; - - if (XdrvMailbox.data_len == 0) - return; - - if (strcasecmp(XdrvMailbox.data, "clear") == 0) { - control = MIEL_HVAC_REMOTETEMP_CLR; - degc = 0; - - ResponseCmndChar_P("clear"); - } else { - degc = strtol(XdrvMailbox.data, nullptr, 0); - - - if (degc < MIEL_HVAC_REMOTETEMP_MIN) - degc = MIEL_HVAC_REMOTETEMP_MIN; - else if (degc > MIEL_HVAC_REMOTETEMP_MAX) - degc = MIEL_HVAC_REMOTETEMP_MAX; - - ResponseCmndNumber(degc); - } - - memset(rt, 0, sizeof(*rt)); - rt->seven = 0x7; - rt->control = control; -# 808 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" - rt->temp_old = miel_hvac_remotetemp_degc2old(degc); - rt->temp = (degc + MIEL_HVAC_REMOTETEMP_OFFSET) * - MIEL_HVAC_REMOTETEMP_OLD_FACTOR; -} - -#ifdef MIEL_HVAC_DEBUG -static void -miel_hvac_cmnd_request(void) -{ - struct miel_hvac_softc *sc = miel_hvac_sc; - uint8_t type = MIEL_HVAC_REQUEST_ROOMTEMP; - - if (XdrvMailbox.data_len > 0) - type = strtoul(XdrvMailbox.data, nullptr, 0); - - miel_hvac_request(sc, type); - - ResponseCmndDone(); -} -#endif - - - - - -static void -miel_hvac_log_bytes(struct miel_hvac_softc *sc, const char *name, - const void *buf, size_t len) -{ - char hex[(MIEL_HVAC_DATABUFLEN + 1) * 2]; - const unsigned char *b = (const unsigned char *)buf; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": response %s %s"), name, ToHex_P(b, len, hex, sizeof(hex))); -} - -static void -miel_hvac_input_connected(struct miel_hvac_softc *sc, - const void *buf, size_t len) -{ - AddLog_P2(LOG_LEVEL_INFO, - PSTR(MIEL_HVAC_LOGNAME ": connected to Mitsubishi Electric HVAC")); - sc->sc_connected = 1; -} - -static void -miel_hvac_publish_settings(struct miel_hvac_softc *sc) -{ - const struct miel_hvac_data_settings *set = - &sc->sc_settings.data.settings; - char hex[(sizeof(sc->sc_settings) + 1) * 2]; - char temp[33]; - const char *name; - - Response_P(PSTR("{\"" D_JSON_IRHVAC_POWER "\":\"%s\""), - set->power ? "ON" : "OFF"); - - name = miel_hvac_map_byval( set->mode & - MIEL_HVAC_SETTINGS_MODE_MASK, - miel_hvac_mode_map, nitems(miel_hvac_mode_map)); - if (name != NULL) { - ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_MODE "\":\"%s\""), - name); - ResponseAppend_P(PSTR(",\"HA" D_JSON_IRHVAC_MODE "\":\"%s\""), - set->power ? name : "off"); - } - - dtostrfd(ConvertTemp(miel_hvac_temp2deg(set->temp)), - Settings.flag2.temperature_resolution, temp); - ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_TEMP "\":%s"), temp); - - name = miel_hvac_map_byval(set->fan, - miel_hvac_fan_map, nitems(miel_hvac_fan_map)); - if (name != NULL) { - ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_FANSPEED "\":\"%s\""), - name); - } - - name = miel_hvac_map_byval(set->vane, - miel_hvac_vane_map, nitems(miel_hvac_vane_map)); - if (name != NULL) { - ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_SWINGV "\":\"%s\""), - name); - } - - name = miel_hvac_map_byval(set->widevane & - MIEL_HVAC_SETTTINGS_WIDEVANE_MASK, - miel_hvac_widevane_map, nitems(miel_hvac_widevane_map)); - if (name != NULL) { - ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_SWINGH "\":\"%s\""), - name); - } - - ResponseAppend_P(PSTR(",\"Bytes\":\"%s\""), - ToHex_P((uint8_t *)&sc->sc_settings, sizeof(sc->sc_settings), - hex, sizeof(hex))); - - ResponseAppend_P(PSTR("}")); - - MqttPublishPrefixTopic_P(TELE, PSTR("HVACSettings")); - - XdrvRulesProcess(); -} - -static void -miel_hvac_input_settings(struct miel_hvac_softc *sc, - const struct miel_hvac_data *d) -{ - const struct miel_hvac_data_settings *set = &d->data.settings; - uint32_t state = set->power ? 1 : 0; - bool publish; - - if (miel_hvac_update_pending(sc)) { - - - - - sc->sc_settings_set = 0; - return; - } - - if (bitRead(power, sc->sc_device) != !!state) - ExecuteCommandPower(sc->sc_device, state, SRC_SWITCH); - - publish = (sc->sc_settings_set == 0) || - (memcmp(d, &sc->sc_settings, sizeof(sc->sc_settings)) != 0); - sc->sc_settings_set = 1; - sc->sc_settings = *d; - - if (publish) - miel_hvac_publish_settings(sc); -} - -static void -miel_hvac_data_response(struct miel_hvac_softc *sc, - const struct miel_hvac_data *d) -{ - char hex[(sizeof(*d) + 1) * 2]; - - Response_P(PSTR("{\"Bytes\":\"%s\"}"), - ToHex_P((uint8_t *)d, sizeof(*d), hex, sizeof(hex))); - - MqttPublishPrefixTopic_P(TELE, PSTR("HVACData")); - XdrvRulesProcess(); -} - -static void -miel_hvac_input_sensor(struct miel_hvac_softc *sc, struct miel_hvac_data *dst, - const struct miel_hvac_data *src) -{ - bool publish; - - publish = (memcmp(dst, src, sizeof(*dst)) != 0); - *dst = *src; - - if (publish) - MqttPublishSensor(); - -} - -static void -miel_hvac_input_data(struct miel_hvac_softc *sc, - const void *buf, size_t len) -{ - const struct miel_hvac_data *d; - - miel_hvac_log_bytes(sc, "data", buf, len); - if (len < sizeof(*d)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME - ": short data response (%zu < %zu)"), len, sizeof(*d)); - return; - } - - d = (const struct miel_hvac_data *)buf; - - switch (d->type) { - case MIEL_HVAC_DATA_T_SETTINGS: - miel_hvac_input_settings(sc, d); - break; - case MIEL_HVAC_DATA_T_ROOMTEMP: - miel_hvac_input_sensor(sc, &sc->sc_temp, d); - break; - case MIEL_HVAC_DATA_T_STATUS: - miel_hvac_input_sensor(sc, &sc->sc_status, d); - break; - case MIEL_HVAC_DATA_T_STAGE: - miel_hvac_input_sensor(sc, &sc->sc_stage, d); - break; - default: - miel_hvac_data_response(sc, d); - break; - } -} - -static void -miel_hvac_input_updated(struct miel_hvac_softc *sc, - const void *buf, size_t len) -{ - miel_hvac_log_bytes(sc, "updated", buf, len); -} - - - - - -static void -miel_hvac_pre_init(void) -{ - struct miel_hvac_softc *sc; - int baudrate = 2400; - - if (!PinUsed(GPIO_MIEL_HVAC_TX) || !PinUsed(GPIO_MIEL_HVAC_RX)) - return; - - sc = (struct miel_hvac_softc *)malloc(sizeof(*sc)); - if (sc == NULL) { - AddLog_P(LOG_LEVEL_ERROR, - PSTR(MIEL_HVAC_LOGNAME ": unable to allocate state")); - return; - } - - memset(sc, 0, sizeof(*sc)); - miel_hvac_init_update(&sc->sc_update); - - sc->sc_serial = new TasmotaSerial(Pin(GPIO_MIEL_HVAC_RX), - Pin(GPIO_MIEL_HVAC_TX), 2); - - if (!sc->sc_serial->begin(baudrate, 2)) { - AddLog_P2(LOG_LEVEL_ERROR, - PSTR(MIEL_HVAC_LOGNAME ": unable to begin serial " - "(baudrate %d)"), baudrate); - goto del; - } - - if (sc->sc_serial->hardwareSerial()) { - ClaimSerial(); - SetSerial(baudrate, TS_SERIAL_8E1); - } - - sc->sc_device = devices_present++; - - miel_hvac_sc = sc; - return; -del: - delete sc->sc_serial; -free: - free(sc); -} - -static void -miel_hvac_loop(struct miel_hvac_softc *sc) -{ - TasmotaSerial *serial = sc->sc_serial; - - while (serial->available()) { - yield(); - - sc->sc_parser.p_state = miel_hvac_parse(sc, serial->read()); - } -} - -static void -miel_hvac_sensor(struct miel_hvac_softc *sc) -{ - char hex[(sizeof(sc->sc_status) + 1) * 2]; - const char *sep = ""; - - ResponseAppend_P(PSTR("," "\"MiElHVAC\":{")); - - if (sc->sc_temp.type != 0) { - const struct miel_hvac_data_roomtemp *rt = - &sc->sc_temp.data.roomtemp; - unsigned int temp = miel_hvac_roomtemp2deg(rt->temp); - char room_temp[33]; - - dtostrfd(ConvertTemp(temp), - Settings.flag2.temperature_resolution, room_temp); - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), - room_temp); - - sep = ","; - } - - if (sc->sc_status.type != 0) { - const struct miel_hvac_data_status *s = - &sc->sc_status.data.status; - - ResponseAppend_P(PSTR("%s" "\"Operation\":\"%s\"" "," - "\"Compressor\":\"%s\""), sep, - s->operation ? "ON" : "OFF", - s->compressor ? "ON" : "OFF"); - - sep = ","; - } - - if (sc->sc_temp.type != 0) { - ResponseAppend_P(PSTR("%s" "\"roomtemp\":\"%s\""), sep, - ToHex_P((uint8_t *)&sc->sc_temp, sizeof(sc->sc_temp), - hex, sizeof(hex))); - - sep = ","; - } - - if (sc->sc_status.type != 0) { - ResponseAppend_P(PSTR("%s" "\"status\":\"%s\""), sep, - ToHex_P((uint8_t *)&sc->sc_status, sizeof(sc->sc_status), - hex, sizeof(hex))); - - sep = ","; - } - - if (sc->sc_stage.type != 0) { - ResponseAppend_P(PSTR("%s" "\"stage\":\"%s\""), sep, - ToHex_P((uint8_t *)&sc->sc_stage, sizeof(sc->sc_stage), - hex, sizeof(hex))); - } - - ResponseAppend_P(PSTR("}")); -} -# 1136 "/workspace/Tasmota/tasmota/xdrv_44_miel_hvac.ino" -enum miel_hvac_connect_states { - MIEL_HVAC_CONNECT_S_2400_MSG, - MIEL_HVAC_CONNECT_S_9600, - MIEL_HVAC_CONNECT_S_9600_MSG, - MIEL_HVAC_CONNECT_S_2400, - - MIEL_HVAC_CONNECT_S_COUNT, -}; - -static void -miel_hvac_connect(struct miel_hvac_softc *sc) -{ - TasmotaSerial *serial = sc->sc_serial; - uint32_t baudrate; - unsigned int state; - - state = (sc->sc_tick++ % MIEL_HVAC_CONNECT_S_COUNT); - - switch (state) { - case MIEL_HVAC_CONNECT_S_2400: - baudrate = 2400; - break; - case MIEL_HVAC_CONNECT_S_9600: - baudrate = 9600; - break; - default: - miel_hvac_send_connect(sc); - return; - } - - serial->begin(baudrate, 2); - if (serial->hardwareSerial()) - SetSerial(baudrate, TS_SERIAL_8E1); -} - -static void -miel_hvac_tick(struct miel_hvac_softc *sc) -{ - static const uint8_t updates[] = { - MIEL_HVAC_REQUEST_SETTINGS, - MIEL_HVAC_REQUEST_STATUS, - MIEL_HVAC_REQUEST_SETTINGS, - MIEL_HVAC_REQUEST_ROOMTEMP, - - MIEL_HVAC_REQUEST_SETTINGS, - - MIEL_HVAC_REQUEST_STAGE, - }; - - unsigned int i; - - if (miel_hvac_update_pending(sc)) { - struct miel_hvac_msg_update *update = &sc->sc_update; - - miel_hvac_send_update(sc, update); - - miel_hvac_init_update(update); - - - sc->sc_tick = 0; - return; - } - - if (sc->sc_remotetemp.seven) { - struct miel_hvac_msg_remotetemp *remotetemp = - &sc->sc_remotetemp; - - miel_hvac_send_remotetemp(sc, remotetemp); - memset(remotetemp, 0, sizeof(*remotetemp)); - return; - } - - i = (sc->sc_tick++ % nitems(updates)); - - miel_hvac_request(sc, updates[i]); -} - - - - - -static const char miel_hvac_cmnd_names[] PROGMEM = - - "|" D_CMND_MIEL_HVAC_SETFANSPEED - "|" D_CMND_MIEL_HVAC_SETMODE - "|" D_CMND_MIEL_HVAC_SETHAMODE - "|" D_CMND_MIEL_HVAC_SETTEMP - "|" D_CMND_MIEL_HVAC_SETSWINGV - "|" D_CMND_MIEL_HVAC_SETSWINGH - "|" D_CMND_MIEL_HVAC_REMOTETEMP -#ifdef MIEL_HVAC_DEBUG - "|" "HVACRequest" -#endif - ; - -static void (*const miel_hvac_cmnds[])(void) PROGMEM = { - &miel_hvac_cmnd_setfanspeed, - &miel_hvac_cmnd_setmode, - &miel_hvac_cmnd_sethamode, - &miel_hvac_cmnd_settemp, - &miel_hvac_cmnd_setvane, - &miel_hvac_cmnd_setwidevane, - &miel_hvac_cmnd_remotetemp, -#ifdef MIEL_HVAC_DEBUG - &miel_hvac_cmnd_request, -#endif -}; - -bool Xdrv44(uint8_t function) { - bool result = false; - struct miel_hvac_softc *sc = miel_hvac_sc; - - switch (function) { - case FUNC_PRE_INIT: - miel_hvac_pre_init(); - return (false); - } - - if (sc == NULL) - return (false); - - switch (function) { - case FUNC_LOOP: - miel_hvac_loop(sc); - break; - - case FUNC_SET_DEVICE_POWER: - result = miel_hvac_set_power(sc); - break; - - case FUNC_EVERY_250_MSECOND: - if (sc->sc_connected) - miel_hvac_tick(sc); - else - miel_hvac_connect(sc); - break; - - case FUNC_EVERY_50_MSECOND: - case FUNC_EVERY_100_MSECOND: - case FUNC_EVERY_200_MSECOND: - case FUNC_EVERY_SECOND: - break; - - case FUNC_JSON_APPEND: - miel_hvac_sensor(sc); - break; - case FUNC_AFTER_TELEPERIOD: - if (sc->sc_settings_set) - miel_hvac_publish_settings(sc); - break; - - case FUNC_COMMAND: - result = DecodeCommand(miel_hvac_cmnd_names, miel_hvac_cmnds); - break; - } - - return (result); -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" -#ifdef ESP32 -#ifdef USE_WEBCAM -# 61 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" -#define XDRV_81 81 - -#include "esp_camera.h" -#include "sensor.h" -#include "fb_gfx.h" -#include "fd_forward.h" -#include "fr_forward.h" - -bool HttpCheckPriviledgedAccess(bool); -extern ESP8266WebServer *Webserver; - -ESP8266WebServer *CamServer; -#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e" - -WiFiClient client; - - - -#define PWDN_GPIO_NUM 32 -#define RESET_GPIO_NUM -1 -#define XCLK_GPIO_NUM 0 -#define SIOD_GPIO_NUM 26 -#define SIOC_GPIO_NUM 27 - -#define Y9_GPIO_NUM 35 -#define Y8_GPIO_NUM 34 -#define Y7_GPIO_NUM 39 -#define Y6_GPIO_NUM 36 -#define Y5_GPIO_NUM 21 -#define Y4_GPIO_NUM 19 -#define Y3_GPIO_NUM 18 -#define Y2_GPIO_NUM 5 -#define VSYNC_GPIO_NUM 25 -#define HREF_GPIO_NUM 23 -#define PCLK_GPIO_NUM 22 - -struct { - uint8_t up; - uint16_t width; - uint16_t height; - uint8_t stream_active; -#ifdef USE_FACE_DETECT - uint8_t faces; - uint16_t face_detect_time; -#endif -} Wc; - -#ifdef ENABLE_RTSPSERVER -#include -#include -#include -#include -WiFiServer rtspServer(8554); -CStreamer *rtsp_streamer; -CRtspSession *rtsp_session; -WiFiClient rtsp_client; -uint8_t rtsp_start; -OV2640 cam; -#endif - - - -bool WcPinUsed(void) { - bool pin_used = true; - for (uint32_t i = 0; i < MAX_WEBCAM_DATA; i++) { - if (!PinUsed(GPIO_WEBCAM_DATA, i)) { - pin_used = false; - } - - - - - - } - if (!PinUsed(GPIO_WEBCAM_XCLK) || !PinUsed(GPIO_WEBCAM_PCLK) || - !PinUsed(GPIO_WEBCAM_VSYNC) || !PinUsed(GPIO_WEBCAM_HREF) || - !PinUsed(GPIO_WEBCAM_SIOD) || !PinUsed(GPIO_WEBCAM_SIOC)) { - pin_used = false; - } - return pin_used; -} - -uint32_t WcSetup(int32_t fsiz) { - if (fsiz > 10) { fsiz = 10; } - - Wc.stream_active = 0; - - if (fsiz < 0) { - esp_camera_deinit(); - Wc.up = 0; - return 0; - } - - if (Wc.up) { - esp_camera_deinit(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Deinit")); - - } - Wc.up = 0; - - - - camera_config_t config; - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.xclk_freq_hz = 20000000; - config.pixel_format = PIXFORMAT_JPEG; - - - - if (WcPinUsed()) { - config.pin_d0 = Pin(GPIO_WEBCAM_DATA); - config.pin_d1 = Pin(GPIO_WEBCAM_DATA, 1); - config.pin_d2 = Pin(GPIO_WEBCAM_DATA, 2); - config.pin_d3 = Pin(GPIO_WEBCAM_DATA, 3); - config.pin_d4 = Pin(GPIO_WEBCAM_DATA, 4); - config.pin_d5 = Pin(GPIO_WEBCAM_DATA, 5); - config.pin_d6 = Pin(GPIO_WEBCAM_DATA, 6); - config.pin_d7 = Pin(GPIO_WEBCAM_DATA, 7); - config.pin_xclk = Pin(GPIO_WEBCAM_XCLK); - config.pin_pclk = Pin(GPIO_WEBCAM_PCLK); - config.pin_vsync = Pin(GPIO_WEBCAM_VSYNC); - config.pin_href = Pin(GPIO_WEBCAM_HREF); - config.pin_sscb_sda = Pin(GPIO_WEBCAM_SIOD); - config.pin_sscb_scl = Pin(GPIO_WEBCAM_SIOC); - config.pin_pwdn = (PinUsed(GPIO_WEBCAM_PWDN)) ? Pin(GPIO_WEBCAM_PWDN) : -1; - config.pin_reset = (PinUsed(GPIO_WEBCAM_RESET)) ? Pin(GPIO_WEBCAM_RESET) : -1; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: User template")); - } else { - - config.pin_d0 = Y2_GPIO_NUM; - config.pin_d1 = Y3_GPIO_NUM; - config.pin_d2 = Y4_GPIO_NUM; - config.pin_d3 = Y5_GPIO_NUM; - config.pin_d4 = Y6_GPIO_NUM; - config.pin_d5 = Y7_GPIO_NUM; - config.pin_d6 = Y8_GPIO_NUM; - config.pin_d7 = Y9_GPIO_NUM; - config.pin_xclk = XCLK_GPIO_NUM; - config.pin_pclk = PCLK_GPIO_NUM; - config.pin_vsync = VSYNC_GPIO_NUM; - config.pin_href = HREF_GPIO_NUM; - config.pin_sscb_sda = SIOD_GPIO_NUM; - config.pin_sscb_scl = SIOC_GPIO_NUM; - config.pin_pwdn = PWDN_GPIO_NUM; - config.pin_reset = RESET_GPIO_NUM; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Default template")); - } -# 218 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" - bool psram = psramFound(); - if (psram) { - config.frame_size = FRAMESIZE_UXGA; - config.jpeg_quality = 10; - config.fb_count = 2; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM found")); - } else { - config.frame_size = FRAMESIZE_VGA; - config.jpeg_quality = 12; - config.fb_count = 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM not found")); - } - - - - - - - - void *x = 0; - esp_err_t err = esp_camera_init(&config); - if (x) { free(x); } - - if (err != ESP_OK) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Init failed with error 0x%x"), err); - return 0; - } - - - - sensor_t * wc_s = esp_camera_sensor_get(); - - wc_s->set_vflip(wc_s, Settings.webcam_config.flip); - wc_s->set_hmirror(wc_s, Settings.webcam_config.mirror); - wc_s->set_brightness(wc_s, Settings.webcam_config.brightness -2); - wc_s->set_saturation(wc_s, Settings.webcam_config.saturation -2); - wc_s->set_contrast(wc_s, Settings.webcam_config.contrast -2); - - - wc_s->set_framesize(wc_s, (framesize_t)fsiz); - - camera_fb_t *wc_fb = esp_camera_fb_get(); - if (!wc_fb) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Init failed to get the frame on time")); - return 0; - } - Wc.width = wc_fb->width; - Wc.height = wc_fb->height; - esp_camera_fb_return(wc_fb); - -#ifdef USE_FACE_DETECT - fd_init(); -#endif - - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: Initialized")); - - Wc.up = 1; - if (psram) { Wc.up = 2; } - - return Wc.up; -} - - - -int32_t WcSetOptions(uint32_t sel, int32_t value) { - int32_t res = 0; - sensor_t *s = esp_camera_sensor_get(); - if (!s) { return -99; } - - switch (sel) { - case 0: - if (value >= 0) { s->set_framesize(s, (framesize_t)value); } - res = s->status.framesize; - break; - case 1: - if (value >= 0) { s->set_special_effect(s, value); } - res = s->status.special_effect; - break; - case 2: - if (value >= 0) { s->set_vflip(s, value); } - res = s->status.vflip; - break; - case 3: - if (value >= 0) { s->set_hmirror(s, value); } - res = s->status.hmirror; - break; - case 4: - if (value >= -4) { s->set_contrast(s, value); } - res = s->status.contrast; - break; - case 5: - if (value >= -4) { s->set_brightness(s, value); } - res = s->status.brightness; - break; - case 6: - if (value >= -4) { s->set_saturation(s,value); } - res = s->status.saturation; - break; - } - - return res; -} - -uint32_t WcGetWidth(void) { - camera_fb_t *wc_fb = esp_camera_fb_get(); - if (!wc_fb) { return 0; } - Wc.width = wc_fb->width; - esp_camera_fb_return(wc_fb); - return Wc.width; -} - -uint32_t WcGetHeight(void) { - camera_fb_t *wc_fb = esp_camera_fb_get(); - if (!wc_fb) { return 0; } - Wc.height = wc_fb->height; - esp_camera_fb_return(wc_fb); - return Wc.height; -} - - - -uint16_t motion_detect; -uint32_t motion_ltime; -uint32_t motion_trigger; -uint32_t motion_brightness; -uint8_t *last_motion_buffer; - -uint32_t WcSetMotionDetect(int32_t value) { - if (value >= 0) { motion_detect = value; } - if (-1 == value) { - return motion_trigger; - } else { - return motion_brightness; - } -} - - -void WcDetectMotion(void) { - camera_fb_t *wc_fb; - uint8_t *out_buf = 0; - - if ((millis()-motion_ltime) > motion_detect) { - motion_ltime = millis(); - wc_fb = esp_camera_fb_get(); - if (!wc_fb) { return; } - - if (!last_motion_buffer) { - last_motion_buffer=(uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - } - if (last_motion_buffer) { - if (PIXFORMAT_JPEG == wc_fb->format) { - out_buf = (uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (out_buf) { - fmt2rgb888(wc_fb->buf, wc_fb->len, wc_fb->format, out_buf); - uint32_t x, y; - uint8_t *pxi = out_buf; - uint8_t *pxr = last_motion_buffer; - - uint64_t accu = 0; - uint64_t bright = 0; - for (y = 0; y < wc_fb->height; y++) { - for (x = 0; x < wc_fb->width; x++) { - int32_t gray = (pxi[0] + pxi[1] + pxi[2]) / 3; - int32_t lgray = pxr[0]; - pxr[0] = gray; - pxi += 3; - pxr++; - accu += abs(gray - lgray); - bright += gray; - } - } - motion_trigger = accu / ((wc_fb->height * wc_fb->width) / 100); - motion_brightness = bright / ((wc_fb->height * wc_fb->width) / 100); - free(out_buf); - } - } - } - esp_camera_fb_return(wc_fb); - } -} - - - -#ifdef USE_FACE_DETECT - -static mtmn_config_t mtmn_config = {0}; - -void fd_init(void) { - mtmn_config.type = FAST; - mtmn_config.min_face = 80; - mtmn_config.pyramid = 0.707; - mtmn_config.pyramid_times = 4; - mtmn_config.p_threshold.score = 0.6; - mtmn_config.p_threshold.nms = 0.7; - mtmn_config.p_threshold.candidate_number = 20; - mtmn_config.r_threshold.score = 0.7; - mtmn_config.r_threshold.nms = 0.7; - mtmn_config.r_threshold.candidate_number = 10; - mtmn_config.o_threshold.score = 0.7; - mtmn_config.o_threshold.nms = 0.7; - mtmn_config.o_threshold.candidate_number = 1; -} - -#define FACE_COLOR_WHITE 0x00FFFFFF -#define FACE_COLOR_BLACK 0x00000000 -#define FACE_COLOR_RED 0x000000FF -#define FACE_COLOR_GREEN 0x0000FF00 -#define FACE_COLOR_BLUE 0x00FF0000 -#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN) -#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN) -#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED) -void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id); -# 469 "/workspace/Tasmota/tasmota/xdrv_81_webcam.ino" -#define DL_SPIRAM_SUPPORT - -uint32_t WcSetFaceDetect(int32_t value) { - if (value >= 0) { Wc.face_detect_time = value; } - return Wc.faces; -} - -uint32_t face_ltime; - -uint32_t WcDetectFace(void); - -uint32_t WcDetectFace(void) { - dl_matrix3du_t *image_matrix; - size_t out_len, out_width, out_height; - uint8_t * out_buf; - bool s; - bool detected = false; - int face_id = 0; - camera_fb_t *fb; - - if ((millis() - face_ltime) > Wc.face_detect_time) { - face_ltime = millis(); - fb = esp_camera_fb_get(); - if (!fb) { return ESP_FAIL; } - - image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3); - if (!image_matrix) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: dl_matrix3du_alloc failed")); - esp_camera_fb_return(fb); - return ESP_FAIL; - } - - out_buf = image_matrix->item; - - - - - s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); - esp_camera_fb_return(fb); - if (!s){ - dl_matrix3du_free(image_matrix); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: to rgb888 failed")); - return ESP_FAIL; - } - - box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config); - if (net_boxes){ - detected = true; - Wc.faces = net_boxes->len; - - - - - free(net_boxes->score); - free(net_boxes->box); - free(net_boxes->landmark); - free(net_boxes); - } else { - Wc.faces = 0; - } - dl_matrix3du_free(image_matrix); - - - } -} -#endif - - - -#ifndef MAX_PICSTORE -#define MAX_PICSTORE 4 -#endif -struct PICSTORE { - uint8_t *buff; - uint32_t len; -}; - -struct PICSTORE picstore[MAX_PICSTORE]; - -#ifdef COPYFRAME -struct PICSTORE tmp_picstore; -#endif - -uint32_t WcGetPicstore(int32_t num, uint8_t **buff) { - if (num<0) { return MAX_PICSTORE; } - *buff = picstore[num].buff; - return picstore[num].len; -} - -uint32_t WcGetFrame(int32_t bnum) { - size_t _jpg_buf_len = 0; - uint8_t * _jpg_buf = NULL; - camera_fb_t *wc_fb = 0; - bool jpeg_converted = false; - - if (bnum < 0) { - if (bnum < -MAX_PICSTORE) { bnum=-1; } - bnum = -bnum; - bnum--; - if (picstore[bnum].buff) { free(picstore[bnum].buff); } - picstore[bnum].len = 0; - return 0; - } - -#ifdef COPYFRAME - if (bnum & 0x10) { - bnum &= 0xf; - _jpg_buf = tmp_picstore.buff; - _jpg_buf_len = tmp_picstore.len; - if (!_jpg_buf_len) { return 0; } - goto pcopy; - } -#endif - - wc_fb = esp_camera_fb_get(); - if (!wc_fb) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't get frame")); - return 0; - } - if (!bnum) { - Wc.width = wc_fb->width; - Wc.height = wc_fb->height; - esp_camera_fb_return(wc_fb); - return 0; - } - - if (wc_fb->format != PIXFORMAT_JPEG) { - jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); - if (!jpeg_converted){ - - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - } else { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - -pcopy: - if ((bnum < 1) || (bnum > MAX_PICSTORE)) { bnum = 1; } - bnum--; - if (picstore[bnum].buff) { free(picstore[bnum].buff); } - picstore[bnum].buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (picstore[bnum].buff) { - memcpy(picstore[bnum].buff, _jpg_buf, _jpg_buf_len); - picstore[bnum].len = _jpg_buf_len; - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't allocate picstore")); - picstore[bnum].len = 0; - } - if (wc_fb) { esp_camera_fb_return(wc_fb); } - if (jpeg_converted) { free(_jpg_buf); } - if (!picstore[bnum].buff) { return 0; } - - return _jpg_buf_len; -} - -void HandleImage(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - uint32_t bnum = Webserver->arg(F("p")).toInt(); - if ((bnum < 0) || (bnum > MAX_PICSTORE)) { bnum= 1; } - WiFiClient client = Webserver->client(); - String response = "HTTP/1.1 200 OK\r\n"; - response += "Content-disposition: inline; filename=cap.jpg\r\n"; - response += "Content-type: image/jpeg\r\n\r\n"; - Webserver->sendContent(response); - - if (!bnum) { - size_t _jpg_buf_len = 0; - uint8_t * _jpg_buf = NULL; - camera_fb_t *wc_fb = 0; - wc_fb = esp_camera_fb_get(); - if (!wc_fb) { return; } - if (wc_fb->format != PIXFORMAT_JPEG) { - bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); - if (!jpeg_converted) { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - } else { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - if (_jpg_buf_len) { - client.write((char *)_jpg_buf, _jpg_buf_len); - } - if (wc_fb) { esp_camera_fb_return(wc_fb); } - } else { - bnum--; - if (!picstore[bnum].len) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: No image #: %d"), bnum); - return; - } - client.write((char *)picstore[bnum].buff, picstore[bnum].len); - } - client.stop(); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("CAM: Sending image #: %d"), bnum+1); -} - -void HandleImageBasic(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP "Capture image")); - - if (Settings.webcam_config.stream) { - if (!CamServer) { - WcStreamControl(); - } - } - - camera_fb_t *wc_fb; - wc_fb = esp_camera_fb_get(); - if (!wc_fb) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame buffer could not be acquired")); - return; - } - - size_t _jpg_buf_len = 0; - uint8_t * _jpg_buf = NULL; - if (wc_fb->format != PIXFORMAT_JPEG) { - bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); - if (!jpeg_converted) { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - } else { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - - if (_jpg_buf_len) { - Webserver->client().flush(); - WSHeaderSend(); - Webserver->sendHeader(F("Content-disposition"), F("inline; filename=snapshot.jpg")); - Webserver->send_P(200, "image/jpeg", (char *)_jpg_buf, _jpg_buf_len); - Webserver->client().stop(); - } - - esp_camera_fb_return(wc_fb); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("CAM: Image sent")); -} - -void HandleWebcamMjpeg(void) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Handle camserver")); - - - Wc.stream_active = 1; - client = CamServer->client(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Create client")); - -} - -void HandleWebcamMjpegTask(void) { - camera_fb_t *wc_fb; - size_t _jpg_buf_len = 0; - uint8_t * _jpg_buf = NULL; - - - uint32_t tlen; - bool jpeg_converted = false; - - if (!client.connected()) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Client fail")); - Wc.stream_active = 0; - } - if (1 == Wc.stream_active) { - client.flush(); - client.setTimeout(3); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Start stream")); - client.print("HTTP/1.1 200 OK\r\n" - "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" - "\r\n"); - Wc.stream_active = 2; - } - if (2 == Wc.stream_active) { - wc_fb = esp_camera_fb_get(); - if (!wc_fb) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame fail")); - Wc.stream_active = 0; - } - } - if (2 == Wc.stream_active) { - if (wc_fb->format != PIXFORMAT_JPEG) { - jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); - if (!jpeg_converted){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: JPEG compression failed")); - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - } else { - _jpg_buf_len = wc_fb->len; - _jpg_buf = wc_fb->buf; - } - - client.printf("Content-Type: image/jpeg\r\n" - "Content-Length: %d\r\n" - "\r\n", static_cast(_jpg_buf_len)); - tlen = client.write(_jpg_buf, _jpg_buf_len); - - - - - - - client.print("\r\n--" BOUNDARY "\r\n"); - -#ifdef COPYFRAME - if (tmp_picstore.buff) { free(tmp_picstore.buff); } - tmp_picstore.buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (tmp_picstore.buff) { - memcpy(tmp_picstore.buff, _jpg_buf, _jpg_buf_len); - tmp_picstore.len = _jpg_buf_len; - } else { - tmp_picstore.len = 0; - } -#endif - - if (jpeg_converted) { free(_jpg_buf); } - esp_camera_fb_return(wc_fb); - - } - if (0 == Wc.stream_active) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit")); - client.flush(); - client.stop(); - } -} - -void HandleWebcamRoot(void) { - - CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg"); - CamServer->send(302, "", ""); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Root called")); -} - - - -uint32_t WcSetStreamserver(uint32_t flag) { - if (global_state.network_down) { return 0; } - - Wc.stream_active = 0; - - if (flag) { - if (!CamServer) { - CamServer = new ESP8266WebServer(81); - CamServer->on("/", HandleWebcamRoot); - CamServer->on("/cam.mjpeg", HandleWebcamMjpeg); - CamServer->on("/cam.jpg", HandleWebcamMjpeg); - CamServer->on("/stream", HandleWebcamMjpeg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream init")); - CamServer->begin(); - } - } else { - if (CamServer) { - CamServer->stop(); - delete CamServer; - CamServer = NULL; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit")); - } - } - return 0; -} - -void WcStreamControl() { - WcSetStreamserver(Settings.webcam_config.stream); - WcSetup(Settings.webcam_config.resolution); -} - - -#ifdef ENABLE_RTSPSERVER -static uint32_t rtsp_lastframe_time; -#ifndef RTSP_FRAME_TIME -#define RTSP_FRAME_TIME 100 -#endif -#endif - -void WcLoop(void) { - if (CamServer) { - CamServer->handleClient(); - if (Wc.stream_active) { HandleWebcamMjpegTask(); } - } - if (motion_detect) { WcDetectMotion(); } -#ifdef USE_FACE_DETECT - if (Wc.face_detect_time) { WcDetectFace(); } -#endif - -#ifdef ENABLE_RTSPSERVER - - if (!rtsp_start && !global_state.wifi_down && Wc.up) { - rtspServer.begin(); - rtsp_start = 1; - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP init")); - rtsp_lastframe_time = millis(); - } - - - if (rtsp_session) { - rtsp_session->handleRequests(0); - - - uint32_t now = millis(); - if ((now-rtsp_lastframe_time) > RTSP_FRAME_TIME) { - rtsp_session->broadcastCurrentFrame(now); - rtsp_lastframe_time = now; - - } - - if (rtsp_session->m_stopped) { - delete rtsp_session; - delete rtsp_streamer; - rtsp_session = NULL; - rtsp_streamer = NULL; - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stopped")); - } - } - else { - rtsp_client = rtspServer.accept(); - if (rtsp_client) { - rtsp_streamer = new OV2640Streamer(&rtsp_client, cam); - rtsp_session = new CRtspSession(&rtsp_client, rtsp_streamer); - AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stream created")); - } - } -#endif -} - -void WcPicSetup(void) { - WebServer_on(PSTR("/wc.jpg"), HandleImage); - WebServer_on(PSTR("/wc.mjpeg"), HandleImage); - WebServer_on(PSTR("/snapshot.jpg"), HandleImage); -} - -void WcShowStream(void) { - if (Settings.webcam_config.stream) { - - if (!CamServer) { - WcStreamControl(); - delay(50); - } - if (CamServer && Wc.up) { - WSContentSend_P(PSTR("

Webcam stream

"), - WiFi.localIP().toString().c_str()); - } - } -} - -void WcInit(void) { - if (!Settings.webcam_config.data) { - Settings.webcam_config.stream = 1; - Settings.webcam_config.resolution = 5; - Settings.webcam_config.flip = 0; - Settings.webcam_config.mirror = 0; - Settings.webcam_config.saturation = 0; - Settings.webcam_config.brightness = 3; - Settings.webcam_config.contrast = 2; - } -} - - - - - -#define D_PRFX_WEBCAM "WC" -#define D_CMND_WC_STREAM "Stream" -#define D_CMND_WC_RESOLUTION "Resolution" -#define D_CMND_WC_MIRROR "Mirror" -#define D_CMND_WC_FLIP "Flip" -#define D_CMND_WC_SATURATION "Saturation" -#define D_CMND_WC_BRIGHTNESS "Brightness" -#define D_CMND_WC_CONTRAST "Contrast" -#define D_CMND_WC_INIT "Init" - -const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" - "|" D_CMND_WC_STREAM "|" D_CMND_WC_RESOLUTION "|" D_CMND_WC_MIRROR "|" D_CMND_WC_FLIP "|" - D_CMND_WC_SATURATION "|" D_CMND_WC_BRIGHTNESS "|" D_CMND_WC_CONTRAST "|" D_CMND_WC_INIT - ; - -void (* const WCCommand[])(void) PROGMEM = { - &CmndWebcam, &CmndWebcamStream, &CmndWebcamResolution, &CmndWebcamMirror, &CmndWebcamFlip, - &CmndWebcamSaturation, &CmndWebcamBrightness, &CmndWebcamContrast, &CmndWebcamInit - }; - -void CmndWebcam(void) { - Response_P(PSTR("{\"" D_PRFX_WEBCAM "\":{\"" D_CMND_WC_STREAM "\":%d,\"" D_CMND_WC_RESOLUTION "\":%d,\"" D_CMND_WC_MIRROR "\":%d,\"" - D_CMND_WC_FLIP "\":%d,\"" - D_CMND_WC_SATURATION "\":%d,\"" D_CMND_WC_BRIGHTNESS "\":%d,\"" D_CMND_WC_CONTRAST "\":%d}}"), - Settings.webcam_config.stream, Settings.webcam_config.resolution, Settings.webcam_config.mirror, - Settings.webcam_config.flip, - Settings.webcam_config.saturation -2, Settings.webcam_config.brightness -2, Settings.webcam_config.contrast -2); -} - -void CmndWebcamStream(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.webcam_config.stream = XdrvMailbox.payload; - if (!Settings.webcam_config.stream) { WcStreamControl(); } - } - ResponseCmndStateText(Settings.webcam_config.stream); -} - -void CmndWebcamResolution(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) { - Settings.webcam_config.resolution = XdrvMailbox.payload; - WcSetOptions(0, Settings.webcam_config.resolution); - } - ResponseCmndNumber(Settings.webcam_config.resolution); -} - -void CmndWebcamMirror(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.webcam_config.mirror = XdrvMailbox.payload; - WcSetOptions(3, Settings.webcam_config.mirror); - } - ResponseCmndStateText(Settings.webcam_config.mirror); -} - -void CmndWebcamFlip(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.webcam_config.flip = XdrvMailbox.payload; - WcSetOptions(2, Settings.webcam_config.flip); - } - ResponseCmndStateText(Settings.webcam_config.flip); -} - -void CmndWebcamSaturation(void) { - if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { - Settings.webcam_config.saturation = XdrvMailbox.payload +2; - WcSetOptions(6, Settings.webcam_config.saturation -2); - } - ResponseCmndNumber(Settings.webcam_config.saturation -2); -} - -void CmndWebcamBrightness(void) { - if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { - Settings.webcam_config.brightness = XdrvMailbox.payload +2; - WcSetOptions(5, Settings.webcam_config.brightness -2); - } - ResponseCmndNumber(Settings.webcam_config.brightness -2); -} - -void CmndWebcamContrast(void) { - if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) { - Settings.webcam_config.contrast = XdrvMailbox.payload +2; - WcSetOptions(4, Settings.webcam_config.contrast -2); - } - ResponseCmndNumber(Settings.webcam_config.contrast -2); -} - -void CmndWebcamInit(void) { - WcStreamControl(); - ResponseCmndDone(); -} - - - - - -bool Xdrv81(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_LOOP: - WcLoop(); - break; - case FUNC_WEB_ADD_HANDLER: - WcPicSetup(); - break; - case FUNC_WEB_ADD_MAIN_BUTTON: - WcShowStream(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kWCCommands, WCCommand); - break; - case FUNC_PRE_INIT: - WcInit(); - break; - - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" -#ifdef ESP32 -#ifdef USE_ETHERNET -# 59 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" -#define XDRV_82 82 -# 81 "/workspace/Tasmota/tasmota/xdrv_82_ethernet.ino" -#include - -char eth_hostname[sizeof(my_hostname)]; - -void EthernetEvent(WiFiEvent_t event) { - switch (event) { - case SYSTEM_EVENT_ETH_START: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION)); - ETH.setHostname(eth_hostname); - break; - case SYSTEM_EVENT_ETH_CONNECTED: - AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED " at %dMbps%s"), - ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : ""); - break; - case SYSTEM_EVENT_ETH_GOT_IP: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %s, Hostname %s"), - ETH.macAddress().c_str(), ETH.localIP().toString().c_str(), eth_hostname); - Settings.ip_address[1] = (uint32_t)ETH.gatewayIP(); - Settings.ip_address[2] = (uint32_t)ETH.subnetMask(); - Settings.ip_address[3] = (uint32_t)ETH.dnsIP(); - global_state.eth_down = 0; - break; - case SYSTEM_EVENT_ETH_DISCONNECTED: - AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: Disconnected")); - global_state.eth_down = 1; - break; - case SYSTEM_EVENT_ETH_STOP: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped")); - global_state.eth_down = 1; - break; - default: - break; - } -} - -void EthernetInit(void) { - if (!Settings.flag4.network_ethernet) { return; } - if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: No ETH MDC and/or ETH MDIO GPIO defined")); - return; - } - - - strlcpy(eth_hostname, my_hostname, sizeof(eth_hostname) -5); - strcat(eth_hostname, "_eth"); - - WiFi.onEvent(EthernetEvent); - - int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : -1; - int eth_mdc = Pin(GPIO_ETH_PHY_MDC); - int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); - if (!ETH.begin(Settings.eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings.eth_type, (eth_clock_mode_t)Settings.eth_clk_mode)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error")); - }; -} - -IPAddress EthernetLocalIP(void) { - return ETH.localIP(); -} - -char* EthernetHostname(void) { - return eth_hostname; -} - -String EthernetMacAddress(void) { - return ETH.macAddress(); -} - - - - - -#define D_CMND_ETHADDRESS "EthAddress" -#define D_CMND_ETHTYPE "EthType" -#define D_CMND_ETHCLOCKMODE "EthClockMode" - -const char kEthernetCommands[] PROGMEM = "|" - D_CMND_ETHERNET "|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE; - -void (* const EthernetCommand[])(void) PROGMEM = { - &CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode }; - -void CmndEthernet(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag4.network_ethernet = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndStateText(Settings.flag4.network_ethernet); -} - -void CmndEthAddress(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) { - Settings.eth_address = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndNumber(Settings.eth_address); -} - -void CmndEthType(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - Settings.eth_type = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndNumber(Settings.eth_type); -} - -void CmndEthClockMode(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.eth_clk_mode = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndNumber(Settings.eth_clk_mode); -} - - - - - -bool Xdrv82(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kEthernetCommands, EthernetCommand); - break; - case FUNC_INIT: - EthernetInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_83_esp32watch.ino" -# 20 "/workspace/Tasmota/tasmota/xdrv_83_esp32watch.ino" -#ifdef ESP32 -#ifdef USE_TTGO_WATCH - -#include -#include -#include -#include - -#define XDRV_83 83 - -#define AXP202_INT 35 - -struct TTGO_ADC { - float vbus_v; - float vbus_c; - float batt_v; - float batt_c; - float temp; - uint16_t per; -} ttgo_adc; - -enum { - Q_EVENT_WIFI_SCAN_DONE, - Q_EVENT_WIFI_CONNECT, - Q_EVENT_BMA_INT, - Q_EVENT_AXP_INT, -} ; - -#define BMA423_INT1 39 -#define BMA423_INT2 0 - -#define WATCH_FLAG_SLEEP_MODE _BV(1) -#define WATCH_FLAG_SLEEP_EXIT _BV(2) -#define WATCH_FLAG_BMA_IRQ _BV(3) -#define WATCH_FLAG_AXP_IRQ _BV(4) - -struct TTGO_globs { - AXP20X_Class *ttgo_power = nullptr; - I2CBus *i2c = nullptr; - BMA *bma = nullptr; - QueueHandle_t g_event_queue_handle = NULL; - - EventGroupHandle_t isr_group = NULL; - bool lenergy = false; - bool bma_double_click = false; - bool bma_click = false; - bool bma_button = false; - bool power_ok = false; -} ttgo_globs; - - -void TTGO_Init(void) { - ttgo_globs.ttgo_power = new AXP20X_Class(); - ttgo_globs.i2c = new I2CBus(); - initPower(); - -#ifdef USE_BMA423 - ttgo_globs.bma = new BMA(*ttgo_globs.i2c); - if (ttgo_globs.bma->begin()) { - I2cSetActiveFound(BMA4_I2C_ADDR_SECONDARY, "BMA423"); - } else { - return; - } - - ttgo_globs.bma->attachInterrupt(); - pinMode(BMA423_INT1, INPUT); - attachInterrupt(BMA423_INT1, [] { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group); - if (bits & WATCH_FLAG_SLEEP_MODE) - { - - xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_BMA_IRQ, &xHigherPriorityTaskWoken); - } else - { - - uint8_t data = Q_EVENT_BMA_INT; - xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken); - } - - if (xHigherPriorityTaskWoken) - { - portYIELD_FROM_ISR (); - } - }, RISING); - struct bma423_axes_remap remap_data; - - remap_data.x_axis = 0; - remap_data.x_axis_sign = 1; - remap_data.y_axis = 1; - remap_data.y_axis_sign = 0; - remap_data.z_axis = 2; - remap_data.z_axis_sign = 1; - - ttgo_globs.bma->set_remap_axes(&remap_data); - - ttgo_globs.bma->enableWakeupInterrupt(true); - ttgo_globs.bma->enableAnyNoMotionInterrupt(true); - ttgo_globs.bma->enableAccel(); -#endif -} - -void initPower(void) { - int ret = ttgo_globs.ttgo_power->begin(axpReadBytes, axpWriteBytes); - if (ret == AXP_FAIL) { - - - } else { - I2cSetActiveFound(AXP202_SLAVE_ADDRESS, "AXP202"); - ttgo_globs.power_ok = true; - - - - ttgo_globs.ttgo_power->setShutdownTime(AXP_POWER_OFF_TIME_4S); - - ttgo_globs.ttgo_power->setChgLEDMode(AXP20X_LED_OFF); - - ttgo_globs.ttgo_power->setPowerOutPut(AXP202_EXTEN, false); - - ttgo_globs.ttgo_power->setChargeControlCur(300); - - ttgo_globs.ttgo_power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true); - - ttgo_globs.ttgo_power->adc2Enable(AXP202_TEMP_MONITORING_ADC2, true); - - ttgo_globs.ttgo_power->enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ, AXP202_ON); - ttgo_globs.ttgo_power->clearIRQ(); - - ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO2, AXP202_ON); - - ttgo_globs.isr_group = xEventGroupCreate(); - ttgo_globs.g_event_queue_handle = xQueueCreate(20, sizeof(uint8_t)); - - - pinMode(AXP202_INT, INPUT); - attachInterrupt(AXP202_INT, [] { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group); - if (bits & WATCH_FLAG_SLEEP_MODE) { - - xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_AXP_IRQ, &xHigherPriorityTaskWoken); - } else { - - uint8_t data = Q_EVENT_AXP_INT; - xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken); - } - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR (); - } - }, FALLING); - - } - -} - -static uint8_t axpWriteBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) { - ttgo_globs.i2c->writeBytes(devAddress, regAddress, data, len); - return 0; -} - -static uint8_t axpReadBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) { - ttgo_globs.i2c->readBytes(devAddress, regAddress, data, len); - return 0; -} - - -void TTGO_GetADC(void) { - ttgo_adc.vbus_v = ttgo_globs.ttgo_power->getVbusVoltage(); - ttgo_adc.vbus_c = ttgo_globs.ttgo_power->getVbusCurrent(); - ttgo_adc.batt_v = ttgo_globs.ttgo_power->getBattVoltage(); - ttgo_adc.per = ttgo_globs.ttgo_power->getBattPercentage(); - ttgo_adc.batt_c = ttgo_globs.ttgo_power->getBattDischargeCurrent(); - ttgo_adc.temp = ttgo_globs.ttgo_power->getTemp(); -} - -#ifdef USE_WEBSERVER -const char HTTP_TTGO[] PROGMEM = - "{s}TTGO " "VBUS Voltage" "{m}%s mV" "{e}" - "{s}TTGO " "VBUS Current" "{m}%s mA" "{e}" - "{s}TTGO " "BATT Voltage" "{m}%s mV" "{e}" - "{s}TTGO " "BATT Current" "{m}%s mA" "{e}" - "{s}TTGO " "BATT Percentage" "{m}%d %%" "{e}" - "{s}TTGO " "Temperature" "{m}%s C" "{e}"; -#ifdef USE_BMA423 -const char HTTP_TTGO_BMA[] PROGMEM = - "{s}TTGO " "BMA x" "{m}%d mg" "{e}" - "{s}TTGO " "BMA y" "{m}%d mg" "{e}" - "{s}TTGO " "BMA z" "{m}%d mg" "{e}"; -#endif -#endif - - -void TTGO_WebShow(uint32_t json) { - - if (ttgo_globs.power_ok == false) return; - - TTGO_GetADC(); - - char vstring[32]; - char cstring[32]; - char bvstring[32]; - char bcstring[32]; - char tstring[32]; - dtostrfd(ttgo_adc.vbus_v,2,vstring); - dtostrfd(ttgo_adc.vbus_c,2,cstring); - dtostrfd(ttgo_adc.batt_v,2,bvstring); - dtostrfd(ttgo_adc.batt_c,2,bcstring); - dtostrfd(ttgo_adc.temp,2,tstring); - -#ifdef USE_BMA423 - Accel acc; - bool res = ttgo_globs.bma->getAccel(acc); -#endif - - if (json) { - ResponseAppend_P(PSTR(",\"TTGO_WATCH\":{\"VBV\":%s,\"VBC\":%s,\"BV\":%s,\"BC\":%s,\"BP\":%d,\"CT\":%s"), - vstring, cstring, bvstring, bcstring, ttgo_adc.per, tstring); -#ifdef USE_BMA423 - ResponseAppend_P(PSTR(",\"BMAX\":%d,\"BMAY\":%d,\"BMAZ\":%d"),acc.x,acc.y,acc.z); -#endif - ResponseJsonEnd(); - } else { - WSContentSend_PD(HTTP_TTGO,vstring,cstring,bvstring,bcstring,ttgo_adc.per,tstring); -#ifdef USE_BMA423 - WSContentSend_PD(HTTP_TTGO_BMA,acc.x,acc.y,acc.z); -#endif - } -} - - -void enableLDO3(bool en = true) { - if (!ttgo_globs.ttgo_power) return; - ttgo_globs.ttgo_power->setLDO3Mode(1); - ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO3, en); -} - -void TTGO_audio_power(bool power) { - enableLDO3(power); -} - -const char TTGO_Commands[] PROGMEM = "TTGO|" - "LSLP"; - -void (* const TTTGO_Command[])(void) PROGMEM = { - &TTGO_LightSleep}; - -void TTGO_LightSleep(void) { -int32_t ttgo_sleeptime; - - - if ((abs(XdrvMailbox.payload) >= 10) && (abs(XdrvMailbox.payload) <= 3600*24)) { - ttgo_sleeptime = XdrvMailbox.payload; - } else { - ttgo_sleeptime = 0; - } - - ResponseCmndNumber(ttgo_sleeptime); - - TTGO_Sleep(ttgo_sleeptime); - -} - -void TTGO_Sleep(int32_t stime) { -int32_t ttgo_sleeptime; - - ttgo_sleeptime = stime; - -#ifdef USE_DISPLAY - DisplayOnOff(0); -#endif - if (ttgo_sleeptime>=0) { - - WifiShutdown(); - SettingsSaveAll(); - RtcSettingsSave(); - ttgo_globs.lenergy = true; - rtc_clk_cpu_freq_set(RTC_CPU_FREQ_2M); - xEventGroupSetBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE); - gpio_wakeup_enable ((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL); - gpio_wakeup_enable ((gpio_num_t)BMA423_INT1, GPIO_INTR_HIGH_LEVEL); - esp_sleep_enable_gpio_wakeup(); - if (ttgo_sleeptime) { - esp_sleep_enable_timer_wakeup(ttgo_sleeptime * 1000000); - } - esp_light_sleep_start(); - } else { - ttgo_globs.ttgo_power->setPowerOutPut(0xFF, false); - Settings.deepsleep = -ttgo_sleeptime; -#ifdef USE_DEEPSLEEP - RtcSettings.nextwakeup = 0; - deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; - if (deepsleep_flag) { - if (!Settings.tele_period) { - Settings.tele_period = TELE_PERIOD; - } - } -#endif - return; - } - - if (ttgo_sleeptime) { - ttgo_globs.lenergy = false; - rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); -#ifdef USE_DISPLAY - DisplayOnOff(1); -#endif - } else { - while (ttgo_globs.lenergy == true) { - TTGO_loop(0); - OsWatchLoop(); - } - } -} - - -void TTGO_loop(uint32_t flg) { -bool rlst; -uint8_t data; - - if (!flg) { - - EventBits_t bits = xEventGroupGetBits(ttgo_globs.isr_group); - if (bits & WATCH_FLAG_SLEEP_EXIT) { - if (ttgo_globs.lenergy) { - ttgo_globs.lenergy = false; - rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); -#ifdef USE_DISPLAY - DisplayOnOff(1); -#endif - } - -#ifdef USE_BMA423 - if (bits & WATCH_FLAG_BMA_IRQ) { - do { - rlst = ttgo_globs.bma->readInterrupt(); - } while (!rlst); - xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_BMA_IRQ); - } -#endif - - if (bits & WATCH_FLAG_AXP_IRQ) { - ttgo_globs.ttgo_power->readIRQ(); - ttgo_globs.ttgo_power->clearIRQ(); - xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_AXP_IRQ); - } - xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT); - xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE); - } - } else { - - if (xQueueReceive(ttgo_globs.g_event_queue_handle, &data, 5 / portTICK_RATE_MS) == pdPASS) { - switch (data) { -#ifdef USE_BMA423 - case Q_EVENT_BMA_INT: - - do { - rlst = ttgo_globs.bma->readInterrupt(); - } while (!rlst); - - if (ttgo_globs.bma->isDoubleClick()) { - ttgo_globs.bma_double_click = true; - - } - if (ttgo_globs.bma->isAnyNoMotion()) { - ttgo_globs.bma_click = true; - - } - - - if (ttgo_globs.bma->isStepCounter()) { - - } - break; -#endif - case Q_EVENT_AXP_INT: - - ttgo_globs.ttgo_power->readIRQ(); - if (ttgo_globs.ttgo_power->isVbusPlugInIRQ()) { - - - } - if (ttgo_globs.ttgo_power->isVbusRemoveIRQ()) { - - - } - if (ttgo_globs.ttgo_power->isChargingDoneIRQ()) { - - - } - if (ttgo_globs.ttgo_power->isPEKShortPressIRQ()) { - ttgo_globs.bma_button = true; - - } - ttgo_globs.ttgo_power->clearIRQ(); - break; - default: - break; - } - } - } -} - -bool TTGO_doubleclick(void) { - bool retval = ttgo_globs.bma_double_click; - ttgo_globs.bma_double_click = false; - return retval; -} - -bool TTGO_button(void) { - bool retval = ttgo_globs.bma_button; - ttgo_globs.bma_button = false; - return retval; -} - - - - - -bool Xdrv83(uint8_t function) { - bool result = false; - - switch (function) { - - case FUNC_WEB_SENSOR: -#ifdef USE_WEBSERVER - TTGO_WebShow(0); -#endif - break; - case FUNC_JSON_APPEND: - TTGO_WebShow(1); - break; - case FUNC_COMMAND: - result = DecodeCommand(TTGO_Commands, TTTGO_Command); - break; - case FUNC_INIT: - TTGO_Init(); - break; - case FUNC_LOOP: - TTGO_loop(1); - break; - - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdrv_99_debug.ino" -# 22 "/workspace/Tasmota/tasmota/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_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" -#define D_CMND_I2CWRITE "I2CWrite" -#define D_CMND_I2CREAD "I2CRead" -#define D_CMND_I2CSTRETCH "I2CStretch" -#define D_CMND_I2CCLOCK "I2CClock" -#define D_CMND_SERBUFF "SerBufSize" - -const char kDebugCommands[] PROGMEM = "|" - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" -#ifdef USE_WEBSERVER - D_CMND_CFGXOR "|" -#endif - D_CMND_CPUCHECK "|" D_CMND_SERBUFF "|" -#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 "|" -#ifdef USE_I2C - D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK -#endif - ; - -void (* const DebugCommand[])(void) PROGMEM = { - &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, -#ifdef USE_WEBSERVER - &CmndCfgXor, -#endif - &CmndCpuCheck, &CmndSerBufSize, -#ifdef DEBUG_THEO - &CmndException, -#endif - &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, -#ifdef USE_I2C - &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock -#endif - }; - -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) -{ -# 145 "/workspace/Tasmota/tasmota/xdrv_99_debug.ino" - if (1 == type) { - char svalue[10]; - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); - } -# 159 "/workspace/Tasmota/tasmota/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*ssleep)) / (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*ssleep)) / (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; - } - } -} - - - -#ifdef ESP8266 - - - - -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); -} - -#else - -void DebugFreeMem(void) -{ - register uint8_t *sp asm("a1"); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL), XdrvMailbox.data); -} - -#endif - - - -void DebugRtcDump(char* parms) -{ -#ifdef ESP8266 - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; -# 239 "/workspace/Tasmota/tasmota/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); - } -#endif -} - - - -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(Settings)+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(Settings)) address = sizeof(Settings) -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(Settings)) address = sizeof(Settings) -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); -} - -void SetFlashMode(uint8_t mode) -{ -#ifdef ESP8266 - 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; -#endif -} - - - - - -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_WEBSERVER -void CmndCfgXor(void) -{ - if (XdrvMailbox.data_len > 0) { - Web.config_xor_on_set = XdrvMailbox.payload; - } - char temp[10]; - snprintf_P(temp, sizeof(temp), PSTR("0x%02X"), Web.config_xor_on_set); - ResponseCmndChar(temp); -} -#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 CmndSerBufSize(void) -{ - if (XdrvMailbox.data_len > 0) { - Serial.setRxBufferSize(XdrvMailbox.payload); - } -#ifdef ESP8266 - ResponseCmndNumber(Serial.getRxBufferSize()); -#else - ResponseCmndDone(); -#endif -} - -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) -{ -#ifdef ESP8266 - - - - 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(); -#endif -} - -#ifdef USE_I2C -void CmndI2cWrite(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 1) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - - Wire.beginTransmission(buffer[0]); - for (uint32_t i = 1; i < index; i++) { - Wire.write(buffer[i]); - } - int result = Wire.endTransmission(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); - } - } - ResponseCmndDone(); -} - -void CmndI2cRead(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 0) { - uint8_t size = 1; - if (index > 1) { - size = buffer[1]; - } - Wire.requestFrom(buffer[0], size); - index = 0; - while (Wire.available() && index < sizeof(buffer)) { - buffer[index++] = Wire.read(); - } - if (index > 0) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - } - } - } - ResponseCmndDone(); -} - -void CmndI2cStretch(void) -{ -#ifdef ESP8266 - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClockStretchLimit(XdrvMailbox.payload); - } - ResponseCmndDone(); -#endif -} - -void CmndI2cClock(void) -{ - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClock(XdrvMailbox.payload); - } - ResponseCmndDone(); -} -#endif - - - - - -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 "/workspace/Tasmota/tasmota/xdrv_interface.ino" -# 20 "/workspace/Tasmota/tasmota/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 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; - - DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); - - 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 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_LCD - -#define XDSP_01 1 -#define XI2C_03 3 - -#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 (I2cSetDevice(LCD_ADDRESS1)) { - Settings.display_address[0] = LCD_ADDRESS1; - Settings.display_model = XDSP_01; - } - else if (I2cSetDevice(LCD_ADDRESS2)) { - Settings.display_address[0] = LCD_ADDRESS2; - Settings.display_model = XDSP_01; - } - } - - if (XDSP_01 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "LCD"); - - 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) -{ - if (dsp_flag) { - dsp_x--; - dsp_y--; - } - lcd->setCursor(dsp_x, dsp_y); - lcd->print(dsp_str); -} - -void LcdDisplayOnOff() -{ - if (disp_power) { - 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) -{ - if (!I2cEnabled(XI2C_03)) { return false; } - - bool result = false; - - 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(); - break; - case FUNC_DISPLAY_CLEAR: - lcd->clear(); - break; -# 238 "/workspace/Tasmota/tasmota/xdsp_01_lcd.ino" - case FUNC_DISPLAY_DRAW_STRING: - LcdDrawStringAt(); - break; - - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - LcdRefresh(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdsp_02_ssd1306.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_02_ssd1306.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1306 - -#define XDSP_02 2 -#define XI2C_04 4 - -#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(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_02; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_02; - } - } - - if (XDSP_02 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SSD1306"); - - if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { - Settings.display_width = 128; - } - if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { - Settings.display_height = 64; - } - - uint8_t reset_pin = -1; - if (PinUsed(GPIO_OLED_RESET)) { - 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], reset_pin >= 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); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - 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) -{ - if (!I2cEnabled(XI2C_04)) { return false; } - - bool result = false; - - 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 "/workspace/Tasmota/tasmota/xdsp_03_matrix.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_03_matrix.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_MATRIX - -#define XDSP_03 3 -#define XI2C_05 5 - -#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 (I2cSetDevice(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]) { - I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); - 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) -{ - if (!I2cEnabled(XI2C_05)) { return false; } - - bool result = false; - - 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 "/workspace/Tasmota/tasmota/xdsp_04_ili9341.ino" -# 20 "/workspace/Tasmota/tasmota/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_top = TFT_TOP; -uint16_t tft_bottom = TFT_BOTTOM; -uint16_t tft_scroll = TFT_TOP; -uint16_t tft_cols = 0; - - - -bool Ili9341Header(void) { - if (Settings.display_cols[0] != tft_cols) { - tft_cols = Settings.display_cols[0]; - if (tft_cols > 17) { - tft_top = TFT_TOP; - tft_bottom = TFT_BOTTOM; - } else { - tft_top = 0; - tft_bottom = 0; - } - tft_scroll = tft_top; - tft->setScrollMargins(tft_top, tft_bottom); - } - return (tft_cols > 17); -} - -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 { - Ili9341Header(); - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); - tft->setTextSize(2); - - - } -} - -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(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR("DSP: ILI9341")); - } -} - -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() -{ - - - if (PinUsed(GPIO_BACKLIGHT)) { - pinMode(Pin(GPIO_BACKLIGHT), OUTPUT); - digitalWrite(Pin(GPIO_BACKLIGHT), 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 = (tft_top) ? theight : 0; - 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) { - - - - if (Ili9341Header()) { - char tftdt[Settings.display_cols[0] +1]; - char date4[11]; - uint8_t time_size = (Settings.display_cols[0] >= 20) ? 9 : 6; - char spaces[Settings.display_cols[0] - (8 + time_size)]; - char time[time_size]; - - tft->setTextSize(Settings.display_size); - 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(spaces, 0x20, sizeof(spaces)); - spaces[sizeof(spaces) -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, spaces, time); - - tft->print(tftdt); - } else { - tft->setCursor(0, 0); - } - - 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: - Ili9341DisplayOnOff(); - 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_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 "/workspace/Tasmota/tasmota/xdsp_05_epaper_29.ino" -# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_CLK) && PinUsed(GPIO_SPI_MOSI)) { - 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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_MOSI)) { - 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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xdsp_06_epaper_42.ino" -# 21 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) { - epd42->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); - } else { - free(buffer); - return; - } - #else - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { - 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 "/workspace/Tasmota/tasmota/xdsp_07_sh1106.ino" -# 20 "/workspace/Tasmota/tasmota/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 XI2C_06 6 - -#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 (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_07; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_07; - } - } - - if (XDSP_07 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SH1106"); - - 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); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - 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) -{ - if (!I2cEnabled(XI2C_06)) { return false; } - - bool result = false; - - 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 "/workspace/Tasmota/tasmota/xdsp_08_ILI9488.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_08_ILI9488.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488 - -#define XDSP_08 8 -#define XI2C_38 38 - -#define COLORED 1 -#define UNCOLORED 0 - - - -#define USE_TINY_FONT - - -#include -uint8_t ili9488_ctouch_counter = 0; - - -#define BACKPLANE_PIN 2 - -extern uint8_t *buffer; -extern uint8_t color_type; -ILI9488 *ili9488; -extern const uint16_t picture[]; - - - -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 (PinUsed(GPIO_BACKLIGHT)) { - bppin=Pin(GPIO_BACKLIGHT); - } - -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_MISO -#define HW_SPI_MISO 19 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#else -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_MISO -#define HW_SPI_MISO 12 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif - - - if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { - ili9488 = new ILI9488(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK),bppin); - } else { - if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { - ili9488 = new ILI9488(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK),bppin); - } else { - return; - } - } - - 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; - -#ifdef USE_FT5206 - Touch_Init(Wire); -#endif - } -} - -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - -void ILI9488_RotConvert(int16_t *x, int16_t *y) { -int16_t temp; - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - temp=*y; - *y=renderer->height()-*x; - *x=temp; - break; - case 1: - break; - case 2: - break; - case 3: - temp=*y; - *y=*x; - *x=renderer->width()-temp; - break; - } - } -} - - -void ILI9488_CheckTouch(void) { - ili9488_ctouch_counter++; - if (2 == ili9488_ctouch_counter) { - - ili9488_ctouch_counter = 0; - Touch_Check(ILI9488_RotConvert); - } -} -#endif -#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 (FT5206_found) { - ILI9488_CheckTouch(); - } -#endif - break; - } - } - - return result; -} - -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdsp_09_SSD1351.ino" -# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)){ - ssd1351 = new SSD1351(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); - } else { - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { - ssd1351 = new SSD1351(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK)); - } else { - return; - } - } - - delay(100); - 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); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - 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 "/workspace/Tasmota/tasmota/xdsp_10_RA8876.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_10_RA8876.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_RA8876 - -#define XDSP_10 10 -#define XI2C_39 39 - -#define COLORED 1 -#define UNCOLORED 0 - - - -#define USE_TINY_FONT - -#include - -uint8_t ra8876_ctouch_counter = 0; -extern uint8_t *buffer; -extern uint8_t color_type; -RA8876 *ra8876; - - -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; - -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_MISO -#define HW_SPI_MISO 19 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#else -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_MISO -#define HW_SPI_MISO 12 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif - - - if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { - ra8876 = new RA8876(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_MISO),Pin(GPIO_SSPI_SCLK),Pin(GPIO_BACKLIGHT)); - } else { - if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { - 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; - -#ifdef USE_FT5206 - Touch_Init(Wire); -#endif - - } -} - - -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - - -void RA8876_RotConvert(int16_t *x, int16_t *y) { -int16_t temp; - if (renderer) { - *x=*x*renderer->width()/800; - *y=*y*renderer->height()/480; - - *x = renderer->width() - *x; - *y = renderer->height() - *y; - } -} - - -void RA8876_CheckTouch(void) { - ra8876_ctouch_counter++; - if (2 == ra8876_ctouch_counter) { - - ra8876_ctouch_counter = 0; - Touch_Check(RA8876_RotConvert); - } -} -#endif -#endif -# 324 "/workspace/Tasmota/tasmota/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_FT5206 - if (FT5206_found) RA8876_CheckTouch(); -#endif - break; - } - } - return result; -} -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SEVENSEG - -#define XDSP_11 11 -#define XI2C_47 47 - -#include -#include -#include - -Adafruit_7segment *sevenseg[8]; -uint8_t sevensegs = 0; -uint8_t sevenseg_state = 0; - - - -void SevensegWrite(void) -{ - for (uint32_t i = 0; i < sevensegs; i++) { - sevenseg[i]->writeDisplay(); - } -} - -void SevensegClear(void) -{ - for (uint32_t i = 0; i < sevensegs; i++) { - sevenseg[i]->clear(); - } - SevensegWrite(); -} - - - - -void SevensegInitMode(void) -{ - for (uint32_t i = 0; i < sevensegs; i++) { - sevenseg[i]->setBrightness(Settings.display_dimmer); - sevenseg[i]->blinkRate(0); - } - SevensegClear(); -} - -void SevensegInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - SevensegInitMode(); - break; - } -} - -void SevensegInitDriver(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(Settings.display_address[0])) { - Settings.display_model = XDSP_11; - } - } - - if (XDSP_11 == Settings.display_model) { - sevenseg_state = 1; - for (sevensegs = 0; sevensegs < 8; sevensegs++) { - if (Settings.display_address[sevensegs]) { - I2cSetActiveFound(Settings.display_address[sevensegs], "SevenSeg"); - sevenseg[sevensegs] = new Adafruit_7segment(); - sevenseg[sevensegs]->begin(Settings.display_address[sevensegs]); - } else { - break; - } - } - - Settings.display_width = 4; - Settings.display_height = sevensegs; - - SevensegInitMode(); - } -} - -void SevensegOnOff(void) -{ - if (!disp_power) { SevensegClear(); } -} - -void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - enum OutNumType {DECIMAL, HEXADECIMAL, FLOAT, SEGMENTS}; - int16_t number = 0; - double numberf = 0; - boolean hasnumber= false; - uint8_t dots= 0; - OutNumType outnumtype= DECIMAL; - uint8 fds = 0; - boolean done= false; - boolean s= false; - uint8_t unit= y; - char *buf; - - if ((unit>=sevensegs) || (unit<0)) { - unit=0; - } - - for (int i=0; (str[i]!='\0') && (!done); i++) { -# 155 "/workspace/Tasmota/tasmota/xdsp_11_sevenseg.ino" - switch (str[i]) { - case 'x': - - outnumtype = HEXADECIMAL; - break; - case 'f': - - outnumtype = FLOAT; - break; - case ':': - dots |= 0x02; - break; - case '^': - dots |= 0x08; - break; - case 'v': - dots |= 0x04; - break; - case '.': - dots |= 0x10; - break; - case 's': - s = true; - break; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - hasnumber= true; - if (outnumtype == FLOAT) { - - numberf = atof(str+i); - - buf= str+i; - char *cp= strchr(buf, '.'); - if (cp == NULL) { - fds= 0; - } else { - fds= buf+strlen(buf) - 1 - cp; - } - } else { - - number = atoi(str+i); - } - done = true; - break; - case 'z': - hasnumber=false; - dots=0; - s=false; - sevenseg[unit]->clear(); - break; - case 'r': - outnumtype= SEGMENTS; - break; - default: - break; - } - } - - - if (hasnumber) { - if (s) { - - int hour = number/60/60; - int minute = (number/60)%60; - - if (hour) { - - number = hour*100 + minute; - } else { - - number = minute*100 + number%60; - } - } - - if (outnumtype == HEXADECIMAL) { - - sevenseg[unit]->print(number, HEX); - } else if (outnumtype == FLOAT) { - - sevenseg[unit]->printFloat(numberf, fds, 10); - } else if (outnumtype == SEGMENTS) { - - sevenseg[unit]->writeDigitRaw(x, number); - } else { - - sevenseg[unit]->print(number, DEC); - } - } - - if (dots) { - sevenseg[unit]->writeDigitRaw(2, dots); - } - - sevenseg[unit]->writeDisplay(); -} - - - -#ifdef USE_DISPLAY_MODES1TO5 -void SevensegTime(boolean time_24) -{ - - uint hours = RtcTime.hour; - uint minutes = RtcTime.minute; - uint second = RtcTime.second; - uint16_t displayValue = hours * 100 + minutes; - uint16_t dots = 0; - - - if (!time_24) { - - if (hours > 12) { - displayValue -= 1200; - } - - else if (hours == 0) { - displayValue += 1200; - } - } - - - - sevenseg[0]->print(displayValue, DEC); - - - - - if (time_24) { - if (hours == 0) { - - sevenseg[0]->writeDigitNum(1, 0); - - if (minutes < 10) { - sevenseg[0]->writeDigitNum(3, 0); - } - } - if (hours < 10) { - - sevenseg[0]->writeDigitNum(0, 0); - } - } else { - - if (hours >= 12) { - dots |= 0x10; - } - } - - sevenseg[0]->writeDigitRaw(2, dots |= ((second%2) << 1)); - sevenseg[0]->writeDisplay(); -} - -void SevensegRefresh(void) -{ - if (disp_power) { - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SevensegTime(false); - break; - case 2: - SevensegTime(true); - break; - case 4: - case 3: - case 5: { - break; - } - } - } - } -} - -#endif - - - - - -bool Xdsp11(uint8_t function) -{ - if (!I2cEnabled(XI2C_47)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SevensegInitDriver(); - } - else if (XDSP_11 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - SevensegInit(dsp_init); - break; - case FUNC_DISPLAY_CLEAR: - SevensegClear(); - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SevensegRefresh(); - break; -#endif - case FUNC_DISPLAY_POWER: - SevensegOnOff(); - break; - case FUNC_DISPLAY_DRAW_STRING: - SevensegDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdsp_12_ST7789.ino" -# 21 "/workspace/Tasmota/tasmota/xdsp_12_ST7789.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ST7789 - -#define XDSP_12 12 -#define XI2C_38 38 - -#undef COLORED -#define COLORED 1 -#undef UNCOLORED -#define UNCOLORED 0 - - -#undef FT5206_address -#define FT5206_address 0x38 - - - -#undef USE_TINY_FONT -#define USE_TINY_FONT - - -#include -#include - - -#define BACKPLANE_PIN 2 - -extern uint8_t *buffer; -extern uint8_t color_type; -Arduino_ST7789 *st7789; - -#ifdef USE_FT5206 -uint8_t st7789_ctouch_counter = 0; -#endif - - - -void ST7789_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_12; - } - - if (XDSP_12 == Settings.display_model) { - - if (Settings.display_width != ST7789_TFTWIDTH) { - Settings.display_width = ST7789_TFTWIDTH; - } - if (Settings.display_height != ST7789_TFTHEIGHT) { - Settings.display_height = ST7789_TFTHEIGHT; - } - - - buffer=NULL; - - - fg_color = ST7789_WHITE; - bg_color = ST7789_BLACK; - - int8_t bppin=BACKPLANE_PIN; - if (PinUsed(GPIO_BACKLIGHT)) { - bppin=Pin(GPIO_BACKLIGHT); - } - - int8_t reset = -1; - if (PinUsed(GPIO_OLED_RESET)) { - reset=Pin(GPIO_OLED_RESET); - } - - int8_t cs = -1; - if (PinUsed(GPIO_SSPI_CS)) { - cs=Pin(GPIO_SSPI_CS); - } else if (PinUsed(GPIO_SPI_CS)) { - cs=Pin(GPIO_SPI_CS); - } - -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#else -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif - - - - if ((Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) { - st7789 = new Arduino_ST7789(Pin(GPIO_SPI_DC), reset, cs, bppin); - } else { - if ((PinUsed(GPIO_SSPI_CS) || PinUsed(GPIO_OLED_RESET)) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) { - st7789 = new Arduino_ST7789(Pin(GPIO_SSPI_DC), reset, Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), cs, bppin); - } else { - return; - } - } - st7789->init(Settings.display_width,Settings.display_height); - renderer = st7789; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(ST7789_WHITE,ST7789_BLACK); - renderer->DrawStringAt(30, 100, "ST7789 TFT!", ST7789_WHITE,0); - delay(1000); -#endif - - color_type = COLOR_COLOR; - -#ifdef ESP32 -#ifdef USE_FT5206 - - #define SDA_2 23 - #define SCL_2 32 - Wire1.begin(SDA_2, SCL_2, 400000); - Touch_Init(Wire1); -#endif -#endif - - } -} - -#ifdef ESP32 -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - -void ST7789_RotConvert(int16_t *x, int16_t *y) { -int16_t temp; - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - break; - case 1: - temp=*y; - *y=renderer->height()-*x; - *x=temp; - break; - case 2: - *x=renderer->width()-*x; - *y=renderer->height()-*y; - break; - case 3: - temp=*y; - *y=*x; - *x=renderer->width()-temp; - break; - } - } -} - - -void ST7789_CheckTouch() { -st7789_ctouch_counter++; - if (2 == st7789_ctouch_counter) { - - st7789_ctouch_counter = 0; - Touch_Check(ST7789_RotConvert); - } -} -#endif -#endif -#endif - - - - - -bool Xdsp12(uint8_t function) -{ - bool result = false; - - - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ST7789_InitDriver(); - } - else if (XDSP_12 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - if (FT5206_found) { - ST7789_CheckTouch(); - } -#endif -#endif - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xdsp_interface.ino" -# 20 "/workspace/Tasmota/tasmota/xdsp_interface.ino" -#if defined(USE_I2C) || defined(USE_SPI) -#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 "/workspace/Tasmota/tasmota/xdsp_interface.ino" -uint8_t XdspPresent(void) -{ - return xdsp_present; -} - -bool XdspCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); - - 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 -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" -#ifdef USE_LIGHT -#ifdef USE_WS2812 -# 38 "/workspace/Tasmota/tasmota/xlgt_01_ws2812.ino" -#define XLGT_01 1 - -const uint8_t WS2812_SCHEMES = 8; - -const char kWs2812Commands[] PROGMEM = "|" - D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; - -void (* const Ws2812Command[])(void) PROGMEM = { - &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; - -#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 - -#ifdef USE_WS2812_INVERTED - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaInvertedWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaInvertedSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaInvertedApa106Method selectedNeoSpeedType; -#else - typedef NeoEsp8266DmaInverted800KbpsMethod selectedNeoSpeedType; -#endif - -#else - -#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 - -#endif - -#else - -#ifdef USE_WS2812_INVERTED - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xInvertedMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812InvertedMethod selectedNeoSpeedType; -#else - typedef NeoEsp8266BitBang400KbpsInvertedMethod 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 - -#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 -1] = { - 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 }; - -struct WS2812 { - uint8_t show_next = 1; - uint8_t scheme_offset = 0; - bool suspend_update = false; -} Ws2812; - - - -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 Ws2812Clear(void) -{ - strip->ClearTo(0); - strip->Show(); - Ws2812.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 (!Ws2812.suspend_update) { - strip->Show(); - Ws2812.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 Ws2812ForceSuspend (void) -{ - Ws2812.suspend_update = true; -} - -void Ws2812ForceUpdate (void) -{ - Ws2812.suspend_update = false; - strip->Show(); - Ws2812.show_next = 1; -} - - - -bool Ws2812SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); - - return true; -} - -void Ws2812ShowScheme(void) -{ - uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; - - switch (scheme) { - case 0: - if ((1 == state_250mS) || (Ws2812.show_next)) { - Ws2812Clock(); - Ws2812.show_next = 0; - } - break; - default: - if (1 == Settings.light_fade) { - Ws2812Gradient(scheme -1); - } else { - Ws2812Bars(scheme -1); - } - Ws2812.show_next = 1; - break; - } -} - -void Ws2812ModuleSelected(void) -{ - if (PinUsed(GPIO_WS2812)) { - - - strip = new NeoPixelBus(WS2812_MAX_LEDS, Pin(GPIO_WS2812)); - strip->Begin(); - - Ws2812Clear(); - - Ws2812.scheme_offset = Light.max_scheme +1; - Light.max_scheme += WS2812_SCHEMES; - -#if (USE_WS2812_CTYPE > NEO_3LED) - light_type = LT_RGBW; -#else - light_type = LT_RGB; -#endif - light_flg = XLGT_01; - } -} - - - -void CmndLed(void) -{ - if ((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 ((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 ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { - Settings.light_rotation = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_rotation); -} - -void CmndWidth(void) -{ - if ((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]); - } - } -} - - - - - -bool Xlgt01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Ws2812SetChannels(); - break; - case FUNC_SET_SCHEME: - Ws2812ShowScheme(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kWs2812Commands, Ws2812Command); - break; - case FUNC_MODULE_INIT: - Ws2812ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_02_my92x1.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_02_my92x1.ino" -#ifdef USE_LIGHT -#ifdef USE_MY92X1 - - - - -#define XLGT_02 2 - -struct MY92X1 { - uint8_t pdi_pin = 0; - uint8_t pdcki_pin = 0; - uint8_t model = 0; -} My92x1; - -extern "C" { - void os_delay_us(unsigned int); -} - -void LightDiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdi_pin, HIGH); - digitalWrite(My92x1.pdi_pin, LOW); - } -} - -void LightDckiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdcki_pin, HIGH); - digitalWrite(My92x1.pdcki_pin, LOW); - } -} - -void LightMy92x1Write(uint8_t data) -{ - for (uint32_t i = 0; i < 4; i++) { - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, HIGH); - data = data << 1; - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, LOW); - data = data << 1; - } -} - -void LightMy92x1Init(void) -{ - uint8_t chips[3] = { 1, 2, 2 }; - - LightDckiPulse(chips[My92x1.model] * 32); - os_delay_us(12); - - - LightDiPulse(12); - os_delay_us(12); - for (uint32_t n = 0; n < chips[My92x1.model]; 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[3] = { 4, 6, 6 }; - - uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, - { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, - { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; - - os_delay_us(12); - for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { - LightMy92x1Write(duty[My92x1.model][channel]); - } - os_delay_us(12); - LightDiPulse(8); - os_delay_us(12); -} - - - -bool My92x1SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - - return true; -} - -void My92x1ModuleSelected(void) -{ - if (PinUsed(GPIO_DCKI) && PinUsed(GPIO_DI)) { - My92x1.pdi_pin = Pin(GPIO_DI); - My92x1.pdcki_pin = Pin(GPIO_DCKI); - - pinMode(My92x1.pdi_pin, OUTPUT); - pinMode(My92x1.pdcki_pin, OUTPUT); - digitalWrite(My92x1.pdi_pin, LOW); - digitalWrite(My92x1.pdcki_pin, LOW); - - My92x1.model = 2; - light_type = LT_RGBW; - if (AILIGHT == my_module_type) { - My92x1.model = 0; - - } - else if (SONOFF_B1 == my_module_type) { - My92x1.model = 1; - light_type = LT_RGBWC; - } - - LightMy92x1Init(); - - light_flg = XLGT_02; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); - } -} - - - - - -bool Xlgt02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = My92x1SetChannels(); - break; - case FUNC_MODULE_INIT: - My92x1ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" -#ifdef USE_LIGHT -#ifdef USE_SM16716 - - - - - - - -#define XLGT_03 3 - -#define D_LOG_SM16716 "SM16716: " - -struct SM16716 { - uint8_t pin_clk = 0; - uint8_t pin_dat = 0; - uint8_t pin_sel = 0; - bool enabled = false; -} Sm16716; - -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) { - bool should_enable = (duty_r | duty_g | duty_b); - if (!Sm16716.enabled && should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); - Sm16716.enabled = true; - digitalWrite(Sm16716.pin_sel, HIGH); - - - delayMicroseconds(1000); - SM16716_Init(); - } - else if (Sm16716.enabled && !should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); - Sm16716.enabled = false; - 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); -} -# 111 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" -void SM16716_Init(void) -{ - for (uint32_t t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } -} - - - -bool Sm16716SetChannels(void) -{ -# 132 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); - - return true; -} - -void Sm16716ModuleSelected(void) -{ - if (PinUsed(GPIO_SM16716_CLK) && PinUsed(GPIO_SM16716_DAT)) { - Sm16716.pin_clk = Pin(GPIO_SM16716_CLK); - Sm16716.pin_dat = Pin(GPIO_SM16716_DAT); - Sm16716.pin_sel = Pin(GPIO_SM16716_SEL); -# 161 "/workspace/Tasmota/tasmota/xlgt_03_sm16716.ino" - 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(); - } - - LightPwmOffset(LST_RGB); - light_type += LST_RGB; - light_flg = XLGT_03; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); - } -} - - - - - -bool Xlgt03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm16716SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm16716ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" -#ifdef USE_LIGHT -#ifdef USE_SM2135 -# 31 "/workspace/Tasmota/tasmota/xlgt_04_sm2135.ino" -#define XLGT_04 4 - -#define SM2135_ADDR_MC 0xC0 -#define SM2135_ADDR_CH 0xC1 -#define SM2135_ADDR_R 0xC2 -#define SM2135_ADDR_G 0xC3 -#define SM2135_ADDR_B 0xC4 -#define SM2135_ADDR_C 0xC5 -#define SM2135_ADDR_W 0xC6 - -#define SM2135_RGB 0x00 -#define SM2135_CW 0x80 - -#define SM2135_10MA 0x00 -#define SM2135_15MA 0x01 -#define SM2135_20MA 0x02 -#define SM2135_25MA 0x03 -#define SM2135_30MA 0x04 -#define SM2135_35MA 0x05 -#define SM2135_40MA 0x06 -#define SM2135_45MA 0x07 -#define SM2135_50MA 0x08 -#define SM2135_55MA 0x09 -#define SM2135_60MA 0x0A - -enum Sm2135Color { SM2135_WCGRB, SM2135_WCBGR }; - - -const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; - -struct SM2135 { - uint8_t clk = 0; - uint8_t data = 0; - uint8_t model = SM2135_WCGRB; -} Sm2135; - - - - - -const uint8_t SM2135_DELAY = 4; - -void Sm2135SetLow(uint8_t pin) { - noInterrupts(); - digitalWrite(pin, LOW); - pinMode(pin, OUTPUT); - interrupts(); -} - -void Sm2135SetHigh(uint8_t pin) { - noInterrupts(); - pinMode(pin, INPUT_PULLUP); - interrupts(); -} - -bool Sm2135Init(void) { - digitalWrite(Sm2135.data, LOW); - digitalWrite(Sm2135.clk, LOW); - Sm2135SetHigh(Sm2135.data); - Sm2135SetHigh(Sm2135.clk); - return (!((digitalRead(Sm2135.data) == LOW || digitalRead(Sm2135.clk) == LOW))); -} - -bool Sm2135Write(uint8_t value) { - for (uint8_t curr = 0X80; curr != 0; curr >>= 1) { - if (curr & value) { - Sm2135SetHigh(Sm2135.data); - } else { - Sm2135SetLow(Sm2135.data); - } - Sm2135SetHigh(Sm2135.clk); - delayMicroseconds(SM2135_DELAY); - Sm2135SetLow(Sm2135.clk); - } - - Sm2135SetHigh(Sm2135.data); - Sm2135SetHigh(Sm2135.clk); - delayMicroseconds(SM2135_DELAY / 2); - uint8_t ack = digitalRead(Sm2135.data); - Sm2135SetLow(Sm2135.clk); - delayMicroseconds(SM2135_DELAY / 2); - Sm2135SetLow(Sm2135.data); - return (0 == ack); -} - -bool Sm2135Start(uint8_t addr) { - Sm2135SetLow(Sm2135.data); - delayMicroseconds(SM2135_DELAY); - Sm2135SetLow(Sm2135.clk); - return Sm2135Write(addr); -} - -void Sm2135Stop(void) { - Sm2135SetLow(Sm2135.data); - delayMicroseconds(SM2135_DELAY); - Sm2135SetHigh(Sm2135.clk); - delayMicroseconds(SM2135_DELAY); - Sm2135SetHigh(Sm2135.data); - delayMicroseconds(SM2135_DELAY); -} - - - -bool Sm2135SetChannels(void) { - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - uint8_t data[6]; - - Sm2135Start(SM2135_ADDR_MC); - Sm2135Write(SM2135_CURRENT); - if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { - Sm2135Write(SM2135_CW); - Sm2135Stop(); - delay(1); - Sm2135Start(SM2135_ADDR_C); - Sm2135Write(cur_col[4]); - Sm2135Write(cur_col[3]); - } else { - Sm2135Write(SM2135_RGB); - if (SM2135_WCBGR == Sm2135.model) { - Sm2135Write(cur_col[2]); - Sm2135Write(cur_col[1]); - Sm2135Write(cur_col[0]); - } else { - Sm2135Write(cur_col[1]); - Sm2135Write(cur_col[0]); - Sm2135Write(cur_col[2]); - } - } - Sm2135Stop(); - - return true; -} - -void Sm2135ModuleSelected(void) -{ - if (PinUsed(GPIO_SM2135_CLK) && PinUsed(GPIO_SM2135_DAT)) { - Sm2135.clk = Pin(GPIO_SM2135_CLK); - Sm2135.data = Pin(GPIO_SM2135_DAT); - - Sm2135.model = SM2135_WCGRB; - if (PinUsed(GPIO_SWT1)) { - Sm2135.model = SM2135_WCBGR; - pinMode(Pin(GPIO_SWT1), INPUT); - SetPin(Pin(GPIO_SWT1), AGPIO(GPIO_NONE)); - } - - Sm2135Init(); - - light_type = LT_RGBWC; - light_flg = XLGT_04; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 (%s) Found"), (SM2135_WCBGR == Sm2135.model) ? PSTR("BGR") : PSTR("GRB")); - } -} - - - - - -bool Xlgt04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm2135SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm2135ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -#ifdef USE_LIGHT -#ifdef USE_SONOFF_L1 - - - - -#define XLGT_05 5 - -#define SONOFF_L1_BUFFER_SIZE 140 - -#define SONOFF_L1_MODE_COLORFUL 1 -#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 -#define SONOFF_L1_MODE_COLORFUL_BREATH 3 -#define SONOFF_L1_MODE_DIY_GRADIENT 4 -#define SONOFF_L1_MODE_DIY_PULSE 5 -#define SONOFF_L1_MODE_DIY_BREATH 6 -#define SONOFF_L1_MODE_DIY_STROBE 7 -#define SONOFF_L1_MODE_RGB_GRADIENT 8 -#define SONOFF_L1_MODE_RGB_PULSE 9 -#define SONOFF_L1_MODE_RGB_BREATH 10 -#define SONOFF_L1_MODE_RGB_STROBE 11 -#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 - -struct SNFL1 { - uint32_t unlock = 0; - bool receive_ready = true; -} Snfl1; - - - -void SnfL1Send(const char *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))) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - } else { - serial_in_buffer[serial_in_byte_counter++] = 0x00; - - - - - - - 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)) { - - - - token = nullptr; - } - - else if (!strncmp(token2, "\"switch\"", 8)) { - switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - 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) { - - - - - - 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); - - - - 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) { - 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) { - if (Settings.light_fade) { - 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; - Snfl1.receive_ready = false; - } - return true; -} - -void SnfL1ModuleSelected(void) -{ - if (SONOFF_L1 == my_module_type) { - if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) { - SetSerial(19200, TS_SERIAL_8N1); - - light_type = LT_RGB; - light_flg = XLGT_05; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); - } - } -} - - - - - -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 -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" -#ifdef USE_LIGHT -#ifdef USE_ELECTRIQ_MOODL -# 31 "/workspace/Tasmota/tasmota/xlgt_06_electriq_moodl.ino" -#define XLGT_06 6 - - - -bool ElectriqMoodLSetChannels(void) -{ - uint8_t *col = (uint8_t*)XdrvMailbox.data; - uint8_t checksum = (uint8_t)(0x65 + 0xAA + 0x01 + 0x0A); - - Serial.write(0x65); - Serial.write(0xAA); - Serial.write(0x00); - Serial.write(0x01); - Serial.write(0x0A); - - uint8_t payload[5]; - payload[0] = col[0]; - payload[1] = col[1]; - payload[2] = col[2]; - payload[3] = col[3]; - payload[4] = 0x0; - - - for (uint32_t i = 0; i < 5; i++) { - Serial.write(payload[i]); - checksum += payload[i]; - } - - - for (uint32_t i = 0; i < 5; i++) { - Serial.write(payload[i]); - checksum += payload[i]; - } - - Serial.write(checksum); - Serial.flush(); - - return true; -} - -void ElectriqMoodLModuleSelected(void) -{ - if (PinUsed(GPIO_ELECTRIQ_MOODL_TX)) { - SetSerial(9600, TS_SERIAL_8N1); - light_type = LT_RGBW; - light_flg = XLGT_06; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: ElectriQ Mood Lamp Found")); - } -} - - - - - -bool Xlgt06(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = ElectriqMoodLSetChannels(); - break; - case FUNC_MODULE_INIT: - ElectriqMoodLModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xlgt_interface.ino" -# 20 "/workspace/Tasmota/tasmota/xlgt_interface.ino" -#ifdef USE_LIGHT - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xlgt_func_ptr[])(uint8_t) = { -#endif - -#ifdef XLGT_01 - &Xlgt01, -#endif - -#ifdef XLGT_02 - &Xlgt02, -#endif - -#ifdef XLGT_03 - &Xlgt03, -#endif - -#ifdef XLGT_04 - &Xlgt04, -#endif - -#ifdef XLGT_05 - &Xlgt05, -#endif - -#ifdef XLGT_06 - &Xlgt06, -#endif - -#ifdef XLGT_07 - &Xlgt07, -#endif - -#ifdef XLGT_08 - &Xlgt08, -#endif - -#ifdef XLGT_09 - &Xlgt09, -#endif - -#ifdef XLGT_10 - &Xlgt10, -#endif - -#ifdef XLGT_11 - &Xlgt11, -#endif - -#ifdef XLGT_12 - &Xlgt12, -#endif - -#ifdef XLGT_13 - &Xlgt13, -#endif - -#ifdef XLGT_14 - &Xlgt14, -#endif - -#ifdef XLGT_15 - &Xlgt15, -#endif - -#ifdef XLGT_16 - &Xlgt16 -#endif -}; - -const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); - -uint8_t xlgt_active = 0; - -bool XlgtCall(uint8_t function) -{ - DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); - - if (FUNC_MODULE_INIT == function) { - for (uint32_t x = 0; x < xlgt_present; x++) { - xlgt_func_ptr[x](function); - if (light_flg) { - xlgt_active = x; - return true; - } - } - } - else if (light_flg) { - return xlgt_func_ptr[xlgt_active](function); - } - return false; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_01_hlw8012.ino" -# 20 "/workspace/Tasmota/tasmota/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 - uint32_t debug[HLW_SAMPLE_COUNT]; -#endif - volatile uint32_t cf_pulse_length = 0; - volatile uint32_t cf_pulse_last_time = 0; - uint32_t cf_power_pulse_length = 0; - - volatile uint32_t cf1_pulse_length = 0; - volatile uint32_t cf1_pulse_last_time = 0; - volatile uint32_t cf1_summed_pulse_length = 0; - volatile uint32_t cf1_pulse_counter = 0; - uint32_t cf1_voltage_pulse_length = 0; - uint32_t cf1_current_pulse_length = 0; - - volatile uint32_t energy_period_counter = 0; - - uint32_t power_ratio = 0; - uint32_t voltage_ratio = 0; - uint32_t current_ratio = 0; - - uint8_t model_type = 0; - volatile uint8_t cf1_timer = 0; - uint8_t power_retry = 0; - bool select_ui_flag = false; - bool ui_flag = true; - volatile 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) -{ - uint32_t 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) -{ - uint32_t 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) -{ - uint32_t cf1_pulse_length = 0; - uint32_t hlw_w = 0; - uint32_t hlw_u = 0; - uint32_t 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 (PinUsed(GPIO_NRG_CF1)) { - Hlw.cf1_timer++; - if (Hlw.cf1_timer >= 8) { - Hlw.cf1_timer = 0; - Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; - DigitalWrite(GPIO_NRG_SEL, 0, 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]); - } - } - } - uint32_t 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 { - uint32_t hlw_len; - - if (Hlw.energy_period_counter) { - hlw_len = 10000 * 100 / Hlw.energy_period_counter; - Hlw.energy_period_counter = 0; - if (hlw_len) { - Energy.kWhtoday_delta += (((Hlw.power_ratio * Settings.energy_power_calibration) / 36) * 100) / hlw_len; - 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 (PinUsed(GPIO_NRG_SEL)) { - pinMode(Pin(GPIO_NRG_SEL), OUTPUT); - digitalWrite(Pin(GPIO_NRG_SEL), Hlw.select_ui_flag); - } - if (PinUsed(GPIO_NRG_CF1)) { - 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 (PinUsed(GPIO_HJL_CF)) { - SetPin(Pin(GPIO_HJL_CF), AGPIO(GPIO_HLW_CF)); - Hlw.model_type = 1; - } - - if (PinUsed(GPIO_HLW_CF)) { - - Hlw.ui_flag = true; - if (PinUsed(GPIO_NRG_SEL_INV)) { - SetPin(Pin(GPIO_NRG_SEL_INV), AGPIO(GPIO_NRG_SEL)); - Hlw.ui_flag = false; - } - - if (PinUsed(GPIO_NRG_CF1)) { - if (!PinUsed(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 = ((uint32_t)(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 = ((uint32_t)(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 = ((uint32_t)(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 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_CSE7766 -# 31 "/workspace/Tasmota/tasmota/xnrg_02_cse7766.ino" -#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 - -#define CSE_BUFFER_SIZE 25 - -#include - -TasmotaSerial *CseSerial = nullptr; - -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; - - int byte_counter = 0; - uint8_t *rx_buffer = nullptr; - uint8_t power_invalid = 0; - bool received = false; -} Cse; - -void CseReceived(void) { - - - - - - - uint8_t header = Cse.rx_buffer[0]; - if ((header & 0xFC) == 0xFC) { - AddLog_P2(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 = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_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 = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_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 = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; - } - Settings.energy_power_calibration = power_coefficient / CSE_PREF; - } - - uint8_t adjustement = Cse.rx_buffer[20]; - Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; - Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; - Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; - Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_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; - } -} - -void CseSerialInput(void) { - while (CseSerial->available()) { - yield(); - uint8_t serial_in_byte = CseSerial->read(); - - if (Cse.received) { - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - if (24 == Cse.byte_counter) { - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); - - uint8_t checksum = 0; - for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } - if (checksum == Cse.rx_buffer[23]) { - Energy.data_valid[0] = 0; - CseReceived(); - Cse.received = false; - return; - } else { - do { - memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); - Cse.byte_counter--; - } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); - if (0x5A != Cse.rx_buffer[1]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - Cse.received = false; - Cse.byte_counter = 0; - } - } - } - } else { - if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { - Cse.received = true; - } else { - Cse.byte_counter = 0; - } - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - } - } -} - - - -void CseEverySecond(void) { - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Cse.voltage_cycle = 0; - Cse.current_cycle = 0; - Cse.power_cycle = 0; - } else { - if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - } else { - uint32_t cf_pulses = 0; - if (Cse.cf_pulses < Cse.cf_pulses_last_time) { - cf_pulses = (0x10000 - Cse.cf_pulses_last_time) + Cse.cf_pulses; - } else { - cf_pulses = Cse.cf_pulses - Cse.cf_pulses_last_time; - } - if (cf_pulses && Energy.active_power[0]) { - uint32_t delta = (cf_pulses * Settings.energy_power_calibration) / 36; - - - if (delta <= (4000 * 1000 / 36)) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - Energy.kWhtoday_delta += delta; - } - else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CSE: Overload")); - Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - } - EnergyUpdateToday(); - } - } - } -} - -void CseSnsInit(void) { - - - CseSerial = new TasmotaSerial(Pin(GPIO_CSE7766_RX), -1, 1); - if (CseSerial->begin(4800, 2)) { - if (CseSerial->hardwareSerial()) { - SetSerial(4800, TS_SERIAL_8E1); - ClaimSerial(); - } - 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]; - } else { - energy_flg = ENERGY_NONE; - } -} - -void CseDrvInit(void) { - - if (PinUsed(GPIO_CSE7766_RX)) { - Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); - if (Cse.rx_buffer != nullptr) { - 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_LOOP: - if (CseSerial) { CseSerialInput(); } - break; - case FUNC_EVERY_SECOND: - CseEverySecond(); - break; - case FUNC_COMMAND: - result = CseCommand(); - break; - case FUNC_INIT: - CseSnsInit(); - break; - case FUNC_PRE_INIT: - CseDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM004T -# 31 "/workspace/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#define XNRG_03 3 - -const uint32_t PZEM_STABILIZE = 30; - -#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; - float last_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] = 192; - pzem.addr[1] = 168; - pzem.addr[2] = 1; - 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) -{ -# 124 "/workspace/Tasmota/tasmota/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 (!len && ((c & 0xF8) != 0xA0)) { - 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 PzemEvery250ms(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) { - if (Pzem.energy > Pzem.last_energy) { - if (uptime > PZEM_STABILIZE) { - EnergyUpdateTotal(Pzem.energy, false); - } - Pzem.last_energy = Pzem.energy; - } - Pzem.energy = 0; - } - break; - } - Pzem.read_state++; - if (5 == Pzem.read_state) { - Pzem.read_state = 1; - } - - - } - } - - if (0 == Pzem.send_retry || data_ready) { - if (1 == Pzem.read_state) { - if (0 == Pzem.phase) { - Pzem.phase = Energy.phase_count -1; - } else { - Pzem.phase--; - } - - - } - - 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 < PZEM_STABILIZE)) { - 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 = 0; - Pzem.read_state = 1; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDrvInit(void) -{ - if (PinUsed(GPIO_PZEM004_RX) && PinUsed(GPIO_PZEM0XX_TX)) { - energy_flg = XNRG_03; - } -} - -bool PzemCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Pzem.address = XdrvMailbox.payload; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } - break; - case FUNC_COMMAND: - result = PzemCommand(); - break; - case FUNC_INIT: - PzemSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_04_mcp39f501.ino" -# 20 "/workspace/Tasmota/tasmota/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)); - } - DigitalWrite(GPIO_MCP39F5_RST, 0, 1); - } else { - energy_flg = ENERGY_NONE; - } -} - -void McpDrvInit(void) -{ - if (PinUsed(GPIO_MCP39F5_RX) && PinUsed(GPIO_MCP39F5_TX)) { - if (PinUsed(GPIO_MCP39F5_RST)) { - 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 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_AC -# 33 "/workspace/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#define XNRG_05 5 - -const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_AC_STABILIZE = 30; - -#include -TasmotaModbus *PzemAcModbus; - -struct PZEMAC { - float energy = 0; - float last_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) { - if (PzemAc.energy > PzemAc.last_energy) { - if (uptime > PZEM_AC_STABILIZE) { - EnergyUpdateTotal(PzemAc.energy, false); - } - PzemAc.last_energy = PzemAc.energy; - } - PzemAc.energy = 0; - } - - } - } - } - - if (0 == PzemAc.send_retry || data_ready) { - if (0 == PzemAc.phase) { - PzemAc.phase = Energy.phase_count -1; - } else { - PzemAc.phase--; - } - 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 < PZEM_AC_STABILIZE)) { - 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 = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemAcDrvInit(void) -{ - if (PinUsed(GPIO_PZEM016_RX) && PinUsed(GPIO_PZEM0XX_TX)) { - 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 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_DC -# 32 "/workspace/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#define XNRG_06 6 - -const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_DC_STABILIZE = 30; - -#include -TasmotaModbus *PzemDcModbus; - -struct PZEMDC { - float energy = 0; - float last_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) { - if (PzemDc.energy > PzemDc.last_energy) { - if (uptime > PZEM_DC_STABILIZE) { - EnergyUpdateTotal(PzemDc.energy, false); - } - PzemDc.last_energy = PzemDc.energy; - } - PzemDc.energy = 0; - } - } - } - } - - if (0 == PzemDc.send_retry || data_ready) { - if (0 == PzemDc.channel) { - PzemDc.channel = Energy.phase_count -1; - } else { - PzemDc.channel--; - } - 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 < PZEM_DC_STABILIZE)) { - 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 = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDcDrvInit(void) -{ - if (PinUsed(GPIO_PZEM017_RX) && PinUsed(GPIO_PZEM0XX_TX)) { - 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 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" -#ifdef USE_I2C -#ifdef USE_ENERGY_SENSOR -#ifdef USE_ADE7953 -# 31 "/workspace/Tasmota/tasmota/xnrg_07_ade7953.ino" -#define XNRG_07 7 -#define XI2C_07 7 - -#define ADE7953_PREF 1540 -#define ADE7953_UREF 26000 -#define ADE7953_IREF 10000 - -#define ADE7953_ADDR 0x38 - -const uint16_t Ade7953Registers[] { - 0x31B, - 0x313, - 0x311, - 0x315, - 0x31A, - 0x312, - 0x310, - 0x314, - 0x31C, - 0x10E -}; - -struct Ade7953 { - uint32_t voltage_rms = 0; - uint32_t period = 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)/sizeof(uint16_t); i++) { - int32_t value = Ade7953Read(Ade7953Registers[i]); - if (8 == i) { - Ade7953.voltage_rms = value; - } else if (9 == i) { - Ade7953.period = 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, %d]"), - Ade7953.voltage_rms, Ade7953.period, - 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, C %d, I %d + %d = %d, P %d + %d = %d"), - Ade7953.voltage_rms, Ade7953.period, - 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; - Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); - - 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(void) -{ - if (Ade7953.init_step) { - if (1 == Ade7953.init_step) { - Ade7953Init(); - } - Ade7953.init_step--; - } else { - Ade7953GetData(); - } -} - -void Ade7953DrvInit(void) -{ - if (PinUsed(GPIO_ADE7953_IRQ)) { - pinMode(Pin(GPIO_ADE7953_IRQ), INPUT); - delay(100); - if (I2cSetDevice(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; - } - I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); - Ade7953.init_step = 2; - Energy.phase_count = 2; - Energy.voltage_common = true; - Energy.frequency_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) -{ - if (!I2cEnabled(XI2C_07)) { return false; } - - 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 "/workspace/Tasmota/tasmota/xnrg_08_sdm120.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_08_sdm120.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM120 - - - - - - -#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[0] = 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 (PinUsed(GPIO_SDM120_RX) && PinUsed(GPIO_SDM120_TX)) { - 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 "/workspace/Tasmota/tasmota/xnrg_09_dds2382.ino" -# 20 "/workspace/Tasmota/tasmota/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; -# 67 "/workspace/Tasmota/tasmota/xnrg_09_dds2382.ino" - 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; - uint8_t offset = 11; - if (Settings.flag3.dds2382_model) { - offset = 19; - } - Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; - float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; - - EnergyUpdateTotal(import_active, true); - } - } - - 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 (PinUsed(GPIO_DDS2382_RX) && PinUsed(GPIO_DDS2382_TX)) { - 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 "/workspace/Tasmota/tasmota/xnrg_10_sdm630.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_10_sdm630.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM630 - - - - - - -#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, - 0x0046, - 0x0160, - 0x0162, - 0x0164, -#ifdef SDM630_IMPORT - 0x015A, - 0x015C, - 0x015E, -#endif - 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: - Energy.frequency[0] = value; - break; - - case 16: - Energy.export_active[0] = value; - break; - - case 17: - Energy.export_active[1] = value; - break; - - case 18: - Energy.export_active[2] = value; - break; - - case 19: -#ifdef SDM630_IMPORT - Energy.import_active[0] = value; - break; - - case 20: - Energy.import_active[1] = value; - break; - - case 21: - Energy.import_active[2] = value; - break; - - case 22: -#endif - 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; - Energy.frequency_common = true; - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm630DrvInit(void) -{ - if (PinUsed(GPIO_SDM630_RX) && PinUsed(GPIO_SDM630_TX)) { - 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 "/workspace/Tasmota/tasmota/xnrg_11_ddsu666.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_11_ddsu666.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDSU666 - - - - -#define XNRG_11 11 - - -#ifndef DDSU666_SPEED - #define DDSU666_SPEED 9600 -#endif - -#ifndef DDSU666_ADDR - #define DDSU666_ADDR 1 -#endif - -#include -TasmotaModbus *Ddsu666Modbus; - -const uint16_t Ddsu666_start_addresses[] { - 0x2000, - 0x2002, - 0x2004, - 0x2006, - 0x200A, - 0x200E, - 0X4000, - 0X400A, -}; - -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]; - - 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; - - - - - 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(Ddsu666.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value * 1000; - break; - - case 3: - Energy.reactive_power[0] = value * 1000; - break; - - case 4: - Energy.power_factor[0] = value; - break; - - case 5: - Energy.frequency[0] = value; - break; - - case 6: - Ddsu666.import_active = value; - break; - - case 7: - Energy.export_active[0] = value; - break; - } - - Ddsu666.read_state++; - - if (Ddsu666.read_state == 8) { - Ddsu666.read_state = 0; - EnergyUpdateTotal(Ddsu666.import_active, true); - } - } - } - - 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 (PinUsed(GPIO_DDSU666_RX) && PinUsed(GPIO_DDSU666_TX)) { - energy_flg = XNRG_11; - } -} - - - - - -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 -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_12_solaxX1.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_12_solaxX1.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SOLAX_X1 - - - - -#define XNRG_12 12 - -#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; - -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; - uint8_t freeBit6:1; - uint8_t freeBit5:1; - uint8_t queryOffline:1; - uint8_t queryOfflineSend:1; - uint8_t hasAddress:1; - uint8_t inverterAddressSend:1; - uint8_t inverterSnReceived:1; - }; -} 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); - - while (solaxX1Serial->available() > 0) - { - 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); - - 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_SendInverterAddress(void) -{ - source[0] = 0x00; - destination[0] = 0x00; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x01; - dataLength[0] = 0x0F; - data[14] = INVERTER_ADDRESS; - solaxX1_RS485Send(24); -} - -void solaxX1_QueryLiveData(void) -{ - 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; - return 0; -} - - - -uint8_t solaxX1_send_retry = 0; -uint8_t solaxX1_nodata_count = 0; - -void solaxX1250MSecond(void) -{ - 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]); - solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; - solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; - solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; - solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; - solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; - Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; - Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; - Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; - Energy.active_power[0] = (float)((value[27] << 8) | value[28]); - - solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; - solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); - solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); - - - - - - - - solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); - - 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); - } - } - - if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { - solaxX1_send_retry = 12; - solaxX1_QueryLiveData(); - } - - - - if (255 == solaxX1_nodata_count) { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; - } - } - 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) - { - solaxX1_nodata_count++; - } - else if (255 != solaxX1_nodata_count) - { - - solaxX1_nodata_count = 255; - solaxX1_send_retry = 12; - protocolStatus.status = 0b00001000; - 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; - - } - } - - if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - - 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; - } - } - } - - - if (protocolStatus.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 && protocolStatus.inverterSnReceived == false) - { - for (uint8_t i = 9; i <= 22; i++) - { - data[i - 9] = value[i]; - } - solaxX1_SendInverterAddress(); - protocolStatus.status = 0b1100000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); - } - } - } - } - - if (solaxX1_send_retry == 0) - { - if (protocolStatus.queryOfflineSend) - { - protocolStatus.status = 0b00001000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); - } - solaxX1_send_retry = 12; - } - - - if (protocolStatus.queryOffline) - { - - source[0] = 0x01; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x00; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); - protocolStatus.status = 0b00010000; - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); - } - } - - 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; - - 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 (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { - 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 - -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 - } -} - - - - - -bool Xnrg12(uint8_t function) -{ - bool result = false; - - 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; -#endif - case FUNC_INIT: - solaxX1SnsInit(); - break; - case FUNC_PRE_INIT: - solaxX1DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_LE01MR -# 71 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#define XNRG_13 13 - - -#ifndef LE01MR_SPEED - #define LE01MR_SPEED 2400 -#endif - -#ifndef LE01MR_ADDR - #define LE01MR_ADDR 1 -#endif - -#include -TasmotaModbus *FifLEModbus; - -const uint8_t le01mr_table_sz = 9; - -const uint16_t le01mr_register_addresses[] { - - 0x0130, - 0x0131, - 0x0158, - 0x0139, - 0x0140, - 0x0148, - 0x0150, - 0xA000, - 0xA01E -}; - -struct LE01MR { - float total_active = 0; - float total_reactive = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = le01mr_table_sz; -} Le01mr; - - - -void FifLEEvery250ms(void) -{ - bool data_ready = FifLEModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - uint8_t reg_count = 2; - if (Le01mr.read_state < 3) { - reg_count=1; - } - - uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); - } else { - Energy.data_valid[0] = 0; -# 146 "/workspace/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" - uint32_t value_buff = 0; - - if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { - value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; - } else { - value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; - } - - switch(Le01mr.read_state) { - case 0: - Energy.frequency[0] = value_buff * 0.01f; - break; - - case 1: - Energy.voltage[0] = value_buff * 0.01f; - break; - - case 2: - Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; - break; - - case 3: - Energy.current[0] = value_buff * 0.001f; - break; - - case 4: - Energy.active_power[0] = value_buff * 1.0f; - break; - - case 5: - Energy.reactive_power[0] = value_buff * 1.0f; - break; - - case 6: - Energy.apparent_power[0] = value_buff * 1.0f; - break; - - case 7: - Le01mr.total_active = value_buff * 0.01f; - break; - - case 8: - Le01mr.total_reactive = value_buff * 0.01f; - break; - } - - Le01mr.read_state++; - if (Le01mr.read_state == Le01mr.start_address_count) { - Le01mr.read_state = 0; - - EnergyUpdateTotal(Le01mr.total_active, true); - } - } - } - - if (0 == Le01mr.send_retry || data_ready) { - uint8_t reg_count = 2; - - Le01mr.send_retry = 5; - - if (Le01mr.read_state < 3) reg_count=1; - - FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); - } else { - Le01mr.send_retry--; - } -} - -void FifLESnsInit(void) -{ - FifLEModbus = new TasmotaModbus(Pin(GPIO_LE01MR_RX), Pin(GPIO_LE01MR_TX)); - uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void FifLEDrvInit(void) -{ - if (PinUsed(GPIO_LE01MR_RX) && PinUsed(GPIO_LE01MR_TX)) { - energy_flg = XNRG_13; - } -} - -void FifLEReset(void) -{ - Le01mr.total_active = 0; - Le01mr.total_reactive = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_LE01MR[] PROGMEM = - "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - ; -#endif - -void FifLEShow(bool json) -{ - char total_reactive_chr[FLOATSZ]; - dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); - char total_active_chr[FLOATSZ]; - dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), - total_active_chr, total_reactive_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); -#endif - } -} - - - - - -bool Xnrg13(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { - FifLEEvery250ms(); - } - break; - case FUNC_JSON_APPEND: - FifLEShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - FifLEShow(0); - break; -#endif - case FUNC_ENERGY_RESET: - FifLEReset(); - break; - case FUNC_INIT: - FifLESnsInit(); - break; - case FUNC_PRE_INIT: - FifLEDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_BL0940 -# 30 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" -#define XNRG_14 14 - -#define BL0940_PREF 1430 -#define BL0940_UREF 33000 -#define BL0940_IREF 2750 - -#define BL0940_PULSES_NOT_INITIALIZED -1 - -#define BL0940_BUFFER_SIZE 36 - -#define BL0940_WRITE_COMMAND 0xA0 -#define BL0940_REG_I_FAST_RMS_CTRL 0x10 -#define BL0940_REG_MODE 0x18 -#define BL0940_REG_SOFT_RESET 0x19 -#define BL0940_REG_USR_WRPROT 0x1A -#define BL0940_REG_TPS_CTRL 0x1B - -#define BL0940_READ_COMMAND 0x50 -#define BL0940_FULL_PACKET 0xAA - -#define BL0940_PACKET_HEADER 0x55 - -#include - -TasmotaSerial *Bl0940Serial = nullptr; - -struct BL0940 { - long voltage = 0; - long current = 0; - long power = 0; - long power_cycle_first = 0; - long cf_pulses = 0; - long cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; - float temperature; - - int byte_counter = 0; - uint16_t tps1 = 0; - uint8_t *rx_buffer = nullptr; - bool received = false; -} Bl0940; - -const uint8_t bl0940_init[5][6] = { - { BL0940_WRITE_COMMAND, BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38 }, - { BL0940_WRITE_COMMAND, BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0 }, - { BL0940_WRITE_COMMAND, BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37 }, - { BL0940_WRITE_COMMAND, BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE }, - { BL0940_WRITE_COMMAND, BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B }}; - -void Bl0940Received(void) { - - - - - - - uint16_t tps1 = Bl0940.rx_buffer[29] << 8 | Bl0940.rx_buffer[28]; - if ((Bl0940.rx_buffer[0] != BL0940_PACKET_HEADER) || - (Bl0940.tps1 && ((tps1 < (Bl0940.tps1 -10)) || (tps1 > (Bl0940.tps1 +10)))) - ) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: Invalid data")); - return; - } - - Bl0940.tps1 = tps1; - float t = ((170.0f/448.0f)*(((float)Bl0940.tps1/2.0f)-32.0f))-45.0f; - Bl0940.temperature = ConvertTemp(t); - - Bl0940.voltage = Bl0940.rx_buffer[12] << 16 | Bl0940.rx_buffer[11] << 8 | Bl0940.rx_buffer[10]; - Bl0940.current = Bl0940.rx_buffer[6] << 16 | Bl0940.rx_buffer[5] << 8 | Bl0940.rx_buffer[4]; - int32_t power = Bl0940.rx_buffer[18] << 24 | Bl0940.rx_buffer[17] << 16 | Bl0940.rx_buffer[16] << 8; - Bl0940.power = abs(power) >> 8; - int32_t cf_cnt = Bl0940.rx_buffer[24] << 24 | Bl0940.rx_buffer[23] << 16 | Bl0940.rx_buffer[22] << 8; - Bl0940.cf_pulses = abs(cf_cnt) >> 8; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: U %d, I %d, P %d, C %d, T %d"), - Bl0940.voltage, Bl0940.current, Bl0940.power, Bl0940.cf_pulses, Bl0940.tps1); - - if (Energy.power_on) { - Energy.voltage[0] = (float)Bl0940.voltage / Settings.energy_voltage_calibration; - if (power && (Bl0940.power > Settings.energy_power_calibration)) { - Energy.active_power[0] = (float)Bl0940.power / Settings.energy_power_calibration; - Energy.current[0] = (float)Bl0940.current / (Settings.energy_current_calibration * 100); - } else { - Energy.active_power[0] = 0; - Energy.current[0] = 0; - } - } else { - - Energy.voltage[0] = 0; - Energy.active_power[0] = 0; - Energy.current[0] = 0; - } -} - -void Bl0940SerialInput(void) { - while (Bl0940Serial->available()) { - yield(); - uint8_t serial_in_byte = Bl0940Serial->read(); - if (!Bl0940.received && (BL0940_PACKET_HEADER == serial_in_byte)) { - Bl0940.received = true; - Bl0940.byte_counter = 0; - } - if (Bl0940.received) { - Bl0940.rx_buffer[Bl0940.byte_counter++] = serial_in_byte; - if (BL0940_BUFFER_SIZE == Bl0940.byte_counter) { - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Bl0940.rx_buffer, BL0940_BUFFER_SIZE -1); - - uint8_t checksum = BL0940_READ_COMMAND; - for (uint32_t i = 0; i < BL0940_BUFFER_SIZE -2; i++) { checksum += Bl0940.rx_buffer[i]; } - checksum ^= 0xFF; - if (checksum == Bl0940.rx_buffer[34]) { - Energy.data_valid[0] = 0; - Bl0940Received(); - Bl0940.received = false; - return; - } else { - do { - memmove(Bl0940.rx_buffer, Bl0940.rx_buffer +1, BL0940_BUFFER_SIZE -1); - Bl0940.byte_counter--; - } while ((Bl0940.byte_counter > 1) && (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0])); - if (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: " D_CHECKSUM_FAILURE)); - Bl0940.received = false; - Bl0940.byte_counter = 0; - } - } - } - } - } -} - - - -void Bl0940EverySecond(void) { - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Bl0940.voltage = 0; - Bl0940.current = 0; - Bl0940.power = 0; - } else { -# 178 "/workspace/Tasmota/tasmota/xnrg_14_bl0940.ino" - if (BL0940_PULSES_NOT_INITIALIZED == Bl0940.cf_pulses_last_time) { - Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; - } else { - uint32_t cf_pulses = 0; - if (Bl0940.cf_pulses < Bl0940.cf_pulses_last_time) { - cf_pulses = (0x1000000 - Bl0940.cf_pulses_last_time) + Bl0940.cf_pulses; - } else { - cf_pulses = Bl0940.cf_pulses - Bl0940.cf_pulses_last_time; - } - if (cf_pulses && Energy.active_power[0]) { - uint32_t watt256 = (1638400 * 256) / Settings.energy_power_calibration; - uint32_t delta = (cf_pulses * watt256) / 36; - if (delta <= (4000 * 1000 / 36)) { - Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; - Energy.kWhtoday_delta += delta; - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BL9: Overload")); - Bl0940.cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; - } - EnergyUpdateToday(); - } - } - - } - - - - Bl0940Serial->flush(); - Bl0940Serial->write(BL0940_READ_COMMAND); - Bl0940Serial->write(BL0940_FULL_PACKET); -} - -void Bl0940SnsInit(void) { - - Bl0940Serial = new TasmotaSerial(Pin(GPIO_BL0940_RX), Pin(GPIO_TXD), 1); - if (Bl0940Serial->begin(4800, 1)) { - if (Bl0940Serial->hardwareSerial()) { - ClaimSerial(); - } - if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { - Settings.energy_voltage_calibration = BL0940_UREF; - Settings.energy_current_calibration = BL0940_IREF; - Settings.energy_power_calibration = BL0940_PREF; - } - - for (uint32_t i = 0; i < 5; i++) { - for (uint32_t j = 0; j < 6; j++) { - Bl0940Serial->write(bl0940_init[i][j]); - - } - delay(1); - } - - } else { - energy_flg = ENERGY_NONE; - } -} - -void Bl0940DrvInit(void) { - if (PinUsed(GPIO_BL0940_RX) && PinUsed(GPIO_TXD)) { - Bl0940.rx_buffer = (uint8_t*)(malloc(BL0940_BUFFER_SIZE)); - if (Bl0940.rx_buffer != nullptr) { - energy_flg = XNRG_14; - } - } -} - -bool Bl0940Command(void) { - bool serviced = true; - - uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Bl0940.power) { - Settings.energy_power_calibration = (Bl0940.power * 100) / value; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Bl0940.voltage) { - Settings.energy_voltage_calibration = (Bl0940.voltage * 100) / value; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Bl0940.current) { - Settings.energy_current_calibration = Bl0940.current / value; - } - } - else serviced = false; - - return serviced; -} - -void Bl0940Show(bool json) { - char temperature[33]; - dtostrfd(Bl0940.temperature, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, "BL0940", temperature); - if (0 == tele_period) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, Bl0940.temperature); -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xnrg14(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (Bl0940Serial) { Bl0940SerialInput(); } - break; - case FUNC_EVERY_SECOND: - Bl0940EverySecond(); - break; - case FUNC_JSON_APPEND: - Bl0940Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bl0940Show(0); - break; -#endif - case FUNC_COMMAND: - result = Bl0940Command(); - break; - case FUNC_INIT: - Bl0940SnsInit(); - break; - case FUNC_PRE_INIT: - Bl0940DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_TELEINFO -# 34 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -#define XNRG_15 15 - -#include "LibTeleinfo.h" -#include - -#define TINFO_READ_TIMEOUT 400 - - -enum TInfoContrat{ - CONTRAT_BAS = 1, - CONTRAT_HC, - CONTRAT_EJP, - CONTRAT_BBR, - CONTRAT_END -}; - - -const char kContratName[] PROGMEM = - "|Base|Heures Creuses|EJP|Bleu Blanc Rouge" - ; - - -const char kContratValue[] PROGMEM = - "|BASE|HC..|EJP.|BBR" - ; - - -enum TInfoTarif{ - TARIF_TH = 1, - TARIF_HC, TARIF_HP, - TARIF_HN, TARIF_PM, - TARIF_CB, TARIF_CW, TARIF_CR, - TARIF_PB, TARIF_PW, TARIF_PR, - TARIF_END -}; - - - -const char kTarifValue[] PROGMEM = - "|TH..|HC..|HP.." - "|HN..|PM.." - "|HCJB|HCJW|HCJR" - "|HPJB|HPJW|HPJR" - ; - - -const char kTarifName[] PROGMEM = - "|Toutes|Creuses|Pleines" - "|Normales|Pointe Mobile" - "|Creuses Bleu|Creuses Blanc|Creuse Rouges" - "|Pleines Bleu|Pleines Blanc|Pleines Rouges" - ; - - -enum TInfoLabel{ - LABEL_BASE = 1, - LABEL_ADCO, LABEL_ADSC, - LABEL_HCHC, LABEL_HCHP, LABEL_EAST, LABEL_EASF01, LABEL_EASF02, - LABEL_OPTARIF, LABEL_NGTF, LABEL_ISOUSC, LABEL_PREF, LABEL_PTEC, LABEL_LTARF, LABEL_NTARF, - LABEL_PAPP, LABEL_SINSTS, LABEL_IINST, LABEL_IRMS1, LABEL_TENSION, LABEL_URMS1, - LABEL_IMAX, LABEL_PMAX, LABEL_SMAXSN, - LABEL_DEMAIN, - LABEL_END -}; - -const char kLabel[] PROGMEM = - "|BASE|ADCO|ADSC" - "|HCHC|HCHP|EAST|EASF01|EASF02" - "|OPTARIF|NGTF|ISOUSC|PREF|PTEC|LTARF|NTARF" - "|PAPP|SINSTS|IINST|IRMS1|TENSION|URMS1" - "|IMAX|PMAX|SMAXSN" - "|DEMAIN" - ; - -TInfo tinfo; -TasmotaSerial *TInfoSerial = nullptr; -_Mode_e tinfo_mode = TINFO_MODE_HISTORIQUE; -char serialNumber[13] = ""; -bool tinfo_found = false; -int contrat; -int tarif; -int isousc; -# 126 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -char * getValueFromLabelIndex(int labelIndex, char * value) -{ - char labelName[16]; - - GetTextIndexed(labelName, sizeof(labelName), labelIndex, kLabel); - - return tinfo.valueGet(labelName, value) ; -} -# 147 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void ADPSCallback(uint8_t phase) -{ - - if (phase == 0){ - phase = 1; - } - - Response_P(PSTR("{")); - ResponseAppend_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), serialNumber, phase ); - ResponseJsonEnd(); - - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ADPS on phase %d"), phase); -} -# 172 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void DataCallback(struct _ValueList * me, uint8_t flags) -{ - char c = ' '; - int ilabel ; - - - if (flags & (TINFO_FLAGS_ADDED | TINFO_FLAGS_UPDATED) ) { - char labelName[16]; - - for ( ilabel = 1 ; ilabel < LABEL_END ; ilabel++) { - GetTextIndexed(labelName, sizeof(labelName), ilabel, kLabel); - if (!strcmp(labelName, me->name)) { - break; - } - } - - if (flags & TINFO_FLAGS_ADDED) { c = '#'; } - if (flags & TINFO_FLAGS_UPDATED) { c = '*'; } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: [%d]%c %s=%s"), ilabel, c , me->name, me->value); - - if (ilabelvalue)) { - break; - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); - } - - - else if (ilabel == LABEL_LTARF) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif name changed, now '%s'"), me->value); - } - - else if (ilabel == LABEL_NTARF) - { - tarif = atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif index changed, now '%d'"), tarif); - } - - - - else if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1) - { - Energy.voltage_available = true; - Energy.voltage[0] = (float) atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s, now %d"), me->value, (int) Energy.voltage[0]); - } - - - else if (ilabel == LABEL_IINST || ilabel == LABEL_IRMS1) - { - Energy.current[0] = (float) atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s, now %d"), me->value, (int) Energy.current[0]); - } - - - else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS) - { - Energy.active_power[0] = (float) atoi(me->value);; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]); - } - - - else if ( ilabel == LABEL_HCHC || ilabel == LABEL_HCHP || ilabel == LABEL_BASE) - { - char value[32]; - uint32_t hc = 0; - uint32_t hp = 0; - uint32_t total = 0; - - - if (ilabel == LABEL_BASE) { - total = atoi(me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Base:%u"), total); - - } else { - - if (ilabel == LABEL_HCHC) { - hc = atoi(me->value); - if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { - hp = atoi(value); - } - - - } else if (ilabel == LABEL_HCHP) { - hp = atoi(me->value); - if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { - hc = atoi(value); - } - } - total = hc + hp; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); - } - - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); - } - } - - - else if ( ilabel == LABEL_EAST) - { - uint32_t total = atoi(me->value); - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); - } - - - else if ( ilabel == LABEL_EASF01) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u"), atoi(me->value)); - } - else if ( ilabel == LABEL_EASF02) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HP:%u"), atoi(me->value)); - } - - - else if (ilabel == LABEL_OPTARIF) - { - char contrat_value[] = " "; - - for (contrat = CONTRAT_BAS ; contrat < CONTRAT_END ; contrat++) { - GetTextIndexed(contrat_value, sizeof(contrat_value), contrat, kContratValue); - if (!strcmp(contrat_value, me->value)) { - break; - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); - } - - else if (ilabel == LABEL_NGTF) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s'"), me->value); - } - - - else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF) - { - isousc = atoi( me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); - } - - - else if (ilabel == LABEL_ADCO || ilabel == LABEL_ADSC) - { - strcpy(serialNumber, me->value); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: %s set to %s"), me->name, serialNumber); - } - - } - } - - - - -} -# 348 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void ResponseAppendTInfo(char sep) -{ - struct _ValueList * me = tinfo.getList(); - - char * p ; - boolean isNumber ; - - - - while (me->next) { - - me = me->next; - - if (me->name && me->value && *me->name && *me->value) { - isNumber = true; - p = me->value; - - - if (strcmp(me->name, "ADCO")==0 || strcmp(me->name, "ADSC")==0) { - isNumber = false; - } else { - - while (*p && isNumber) { - if ( *p < '0' || *p > '9' ) { - isNumber = false; - } - p++; - } - } - - ResponseAppend_P( PSTR("%c\"%s\":"), sep, me->name ); - - if (!isNumber) { - ResponseAppend_P( PSTR("\"%s\""), me->value ); - } else { - ResponseAppend_P( PSTR("%d"), atoi(me->value)); - } - - - sep =','; - } - } -} -# 399 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void NewFrameCallback(struct _ValueList * me) -{ - - Energy.data_valid[0] = 0; - - - - if (Settings.flag4.teleinfo_rawdata) { - Response_P(PSTR("{")); - ResponseAppendTInfo(' '); - ResponseJsonEnd(); - - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, serialNumber, false); - } -} -# 423 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void TInfoDrvInit(void) { - if (PinUsed(GPIO_TELEINFO_RX)) { - energy_flg = XNRG_15; - Energy.voltage_available = false; - } -} -# 437 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void TInfoInit(void) -{ - int baudrate; - - - if (Settings.flag4.teleinfo_baudrate) { - baudrate = 9600; - tinfo_mode = TINFO_MODE_STANDARD; - } else { - baudrate = 1200; - tinfo_mode = TINFO_MODE_HISTORIQUE; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: inferface speed %d bps"),baudrate); - - if (PinUsed(GPIO_TELEINFO_RX)) { - uint8_t rx_pin = Pin(GPIO_TELEINFO_RX); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: RX on GPIO%d"), rx_pin); - - - if (PinUsed(GPIO_TELEINFO_ENABLE)) { - uint8_t en_pin = Pin(GPIO_TELEINFO_ENABLE); - pinMode(en_pin, OUTPUT); - digitalWrite(en_pin, HIGH); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Enable with GPIO%d"), en_pin); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: always enabled")); - } - -#if defined (ESP8266) - - TInfoSerial = new TasmotaSerial(rx_pin, -1, 2); - -#else - TInfoSerial = new TasmotaSerial(rx_pin, -1, 1); -#endif - - - - if (TInfoSerial->begin(baudrate)) { - - -#if defined (ESP8266) - if (TInfoSerial->hardwareSerial() ) { - ClaimSerial(); -# 490 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using hardware serial")); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using software serial")); - } - -#elif defined (ESP32) - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: using ESP32 hardware serial")); -#endif - - tinfo.init(tinfo_mode); - - tinfo.attachADPS(ADPSCallback); - tinfo.attachData(DataCallback); - tinfo.attachNewFrame(NewFrameCallback); - tinfo_found = true; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Ready")); - } - } -} -# 518 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -void TInfoEvery250ms(void) -{ - if (!tinfo_found) { - return; - } - - if (TInfoSerial->available()) { - unsigned long start = millis(); - char c; - - - while (TInfoSerial->available()>8 && millis()-start < 100) { - - c = TInfoSerial->read(); - - tinfo.process(c & 0x7F); - } - } -} -# 545 "/workspace/Tasmota/tasmota/xnrg_15_teleinfo.ino" -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_ID_TELEINFO[] PROGMEM = "{s}ID{m}%s{e}" ; -const char HTTP_ENERGY_INDEX_TELEINFO[] PROGMEM = "{s}%s{m}%s " D_UNIT_WATTHOUR "{e}" ; -const char HTTP_ENERGY_PAPP_TELEINFO[] PROGMEM = "{s}" D_POWERUSAGE "{m}%d " D_UNIT_WATT "{e}" ; -const char HTTP_ENERGY_IINST_TELEINFO[] PROGMEM = "{s}" D_CURRENT "{m}%d " D_UNIT_AMPERE "{e}" ; -const char HTTP_ENERGY_TARIF_TELEINFO[] PROGMEM = "{s}" D_CURRENT_TARIFF "{m}Heures %s{e}" ; -const char HTTP_ENERGY_CONTRAT_TELEINFO[] PROGMEM = "{s}" D_CONTRACT "{m}%s %d" D_UNIT_AMPERE "{e}" ; -const char HTTP_ENERGY_LOAD_TELEINFO[] PROGMEM = "{s}" D_POWER_LOAD "{m}%d" D_UNIT_PERCENT "{e}" ; -const char HTTP_ENERGY_IMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_CURRENT "{m}%d" D_UNIT_AMPERE "{e}" ; -const char HTTP_ENERGY_PMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_POWER "{m}%d" D_UNIT_WATT "{e}" ; -#endif - -void TInfoShow(bool json) -{ - - - - if (json) - { - - if (isousc) { - ResponseAppend_P(PSTR(",\"Load\":%d"),(int) ((Energy.current[0]*100.0f) / isousc)); - } - - - if (!Settings.flag4.teleinfo_rawdata) { - ResponseAppendTInfo(','); - } - - -#ifdef USE_WEBSERVER - } - else - { - char name[32]; - char value[32]; - - if (getValueFromLabelIndex(LABEL_BASE, value) ) { - GetTextIndexed(name, sizeof(name), LABEL_BASE, kLabel); - WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); - } - if (getValueFromLabelIndex(LABEL_HCHC, value) ) { - GetTextIndexed(name, sizeof(name), LABEL_HCHC, kLabel); - WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); - } - if (getValueFromLabelIndex(LABEL_HCHP, value) ) { - GetTextIndexed(name, sizeof(name), LABEL_HCHP, kLabel); - WSContentSend_PD(HTTP_ENERGY_INDEX_TELEINFO, name, value); - } - if (getValueFromLabelIndex(LABEL_IMAX, value) ) { - WSContentSend_PD(HTTP_ENERGY_IMAX_TELEINFO, atoi(value)); - } - if (getValueFromLabelIndex(LABEL_PMAX, value) ) { - WSContentSend_PD(HTTP_ENERGY_PMAX_TELEINFO, atoi(value)); - } - - if (tinfo_mode==TINFO_MODE_HISTORIQUE ) { - if (tarif) { - GetTextIndexed(name, sizeof(name), tarif-1, kTarifName); - WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); - } - if (contrat && isousc) { - int percent = (int) ((Energy.current[0]*100.0f) / isousc) ; - GetTextIndexed(name, sizeof(name), contrat, kContratName); - WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); - WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); - } - } else if (tinfo_mode==TINFO_MODE_STANDARD ) { - if (getValueFromLabelIndex(LABEL_LTARF, name) ) { - WSContentSend_PD(HTTP_ENERGY_TARIF_TELEINFO, name); - } - - if (getValueFromLabelIndex(LABEL_NGTF, name) ) { - if (isousc) { - int percent = (int) ((Energy.current[0]*100.0f) / isousc) ; - WSContentSend_PD(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc); - WSContentSend_PD(HTTP_ENERGY_LOAD_TELEINFO, percent); - } - } - } - - - if (*serialNumber) { - WSContentSend_PD(HTTP_ENERGY_ID_TELEINFO, serialNumber); - } - -#endif - } -} - - - - -bool Xnrg15(uint8_t function) -{ - switch (function) - { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { TInfoEvery250ms(); } - break; - case FUNC_JSON_APPEND: - TInfoShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - TInfoShow(0); - break; - #endif - case FUNC_INIT: - TInfoInit(); - break; - case FUNC_PRE_INIT: - TInfoDrvInit(); - break; - } - return false; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_16_iem3000.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_16_iem3000.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_IEM3000 - - - - - - -#define XNRG_16 16 - - -#ifndef IEM3000_SPEED - #define IEM3000_SPEED 19200 -#endif - -#ifndef IEM3000_ADDR - #define IEM3000_ADDR 1 -#endif - -#include -TasmotaModbus *Iem3000Modbus; - -const uint16_t Iem3000_start_addresses[] { - - 0x0bb7, - 0x0bb9, - 0x0bbb, - 0x0bd3, - 0x0bd5, - 0x0bd7, - 0x0bed, - 0x0bef, - 0x0bf1, - 0x0c25, - 0xb02b, -}; - -struct IEM3000 { - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Iem3000; - - - -void IEM3000Every250ms(void) -{ - bool data_ready = Iem3000Modbus->ReceiveReady(); - uint8_t reg_count = 4; - if (Iem3000.read_state < 10) { - reg_count = 2; - } - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Iem3000Modbus->ReceiveBuffer(buffer, reg_count); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Iem3000Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Iem3000 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - int64_t value64; - if(Iem3000.read_state >= 0 && Iem3000.read_state < 10) { - ((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 { - ((uint8_t*)&value64)[7] = buffer[3]; - ((uint8_t*)&value64)[6] = buffer[4]; - ((uint8_t*)&value64)[5] = buffer[5]; - ((uint8_t*)&value64)[4] = buffer[6]; - ((uint8_t*)&value64)[3] = buffer[7]; - ((uint8_t*)&value64)[2] = buffer[8]; - ((uint8_t*)&value64)[1] = buffer[9]; - ((uint8_t*)&value64)[0] = buffer[10]; - } - - switch(Iem3000.read_state) { - case 0: - Energy.current[0] = value; - break; - - case 1: - Energy.current[1] = value; - break; - - case 2: - Energy.current[2] = value; - break; - - case 3: - Energy.voltage[0] = value; - break; - - case 4: - Energy.voltage[1] = value; - break; - - case 5: - Energy.voltage[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.frequency[0] = value; - break; - - case 10: - EnergyUpdateTotal(value64 * 0.001f, true); - break; - } - - Iem3000.read_state++; - if (sizeof(Iem3000_start_addresses)/2 == Iem3000.read_state) { - Iem3000.read_state = 0; - } - } - } - - if (0 == Iem3000.send_retry || data_ready) { - Iem3000.send_retry = 5; - Iem3000Modbus->Send(IEM3000_ADDR, 0x03, Iem3000_start_addresses[Iem3000.read_state], reg_count); - } else { - Iem3000.send_retry--; - } -} - -void Iem3000SnsInit(void) -{ - Iem3000Modbus = new TasmotaModbus(Pin(GPIO_IEM3000_RX), Pin(GPIO_IEM3000_TX)); - uint8_t result = Iem3000Modbus->Begin(IEM3000_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - Energy.frequency_common = true; - } else { - energy_flg = ENERGY_NONE; - } -} - -void Iem3000DrvInit(void) -{ - if (PinUsed(GPIO_IEM3000_RX) && PinUsed(GPIO_IEM3000_TX)) { - energy_flg = XNRG_16; - } -} - - - - - -bool Xnrg16(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { IEM3000Every250ms(); } - break; - case FUNC_INIT: - Iem3000SnsInit(); - break; - case FUNC_PRE_INIT: - Iem3000DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" -# 20 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_WE517 -# 30 "/workspace/Tasmota/tasmota/xnrg_17_ornowe517.ino" -#define XNRG_17 17 - - -#ifndef WE517_SPEED - #define WE517_SPEED 9600 -#endif - -#ifndef WE517_ADDR - #define WE517_ADDR 1 -#endif - -#define FUNCTION_CODE_READ_HOLDING_REGISTERS (0x03) - -#include -TasmotaModbus *We517Modbus; - -const uint16_t we517_start_addresses[] { - - 0x000E, - 0x0010, - 0x0012, - 0x0016, - 0x0018, - 0x001A, - 0x001E, - 0x0020, - 0x0022, - 0x0026, - 0x0026, - 0x002A, - 0x0036, - 0x0038, - 0x003A, - 0x0014, - 0x0100 -}; - -struct WE517 { - uint8_t read_state = 0; - uint8_t send_retry = 0; -} We517; - - - -void WE517Every250ms(void) -{ - bool data_ready = We517Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = We517Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, We517Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ORNO: WE517 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(We517.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 * 1000; - break; - - case 7: - Energy.active_power[1] = value * 1000; - break; - - case 8: - Energy.active_power[2] = value * 1000; - 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: - Energy.frequency[0] = value; - break; - - case 16: - EnergyUpdateTotal(value, true); - break; - } - - We517.read_state++; - if (sizeof(we517_start_addresses)/2 == We517.read_state) { - We517.read_state = 0; - } - } - } - - if (0 == We517.send_retry || data_ready) { - We517.send_retry = 5; - We517Modbus->Send(WE517_ADDR, FUNCTION_CODE_READ_HOLDING_REGISTERS, we517_start_addresses[We517.read_state], 2); - } else { - We517.send_retry--; - } -} - -void We517SnsInit(void) -{ - We517Modbus = new TasmotaModbus(Pin(GPIO_WE517_RX), Pin(GPIO_WE517_TX)); - uint8_t result = We517Modbus->Begin(WE517_SPEED); - if (result) { - if (2 == result) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ORNO: WE517 HW serial init 8E1 at %d baud"), WE517_SPEED); - Serial.begin(WE517_SPEED, SERIAL_8E1); - ClaimSerial(); - } - Energy.phase_count = 3; - Energy.frequency_common = true; - } else { - energy_flg = ENERGY_NONE; - } -} - -void We517DrvInit(void) -{ - if (PinUsed(GPIO_WE517_RX) && PinUsed(GPIO_WE517_TX)) { - energy_flg = XNRG_17; - } -} - - - - - -bool Xnrg17(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { WE517Every250ms(); } - break; - case FUNC_INIT: - We517SnsInit(); - break; - case FUNC_PRE_INIT: - We517DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xnrg_interface.ino" -# 20 "/workspace/Tasmota/tasmota/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 - -#ifdef XNRG_17 - &Xnrg17, -#endif - -#ifdef XNRG_18 - &Xnrg18, -#endif - -#ifdef XNRG_19 - &Xnrg19, -#endif - -#ifdef XNRG_20 - &Xnrg20, -#endif - -#ifdef XNRG_21 - &Xnrg21, -#endif - -#ifdef XNRG_22 - &Xnrg22, -#endif - -#ifdef XNRG_23 - &Xnrg23, -#endif - -#ifdef XNRG_24 - &Xnrg24, -#endif - -#ifdef XNRG_25 - &Xnrg25, -#endif - -#ifdef XNRG_26 - &Xnrg26, -#endif - -#ifdef XNRG_27 - &Xnrg27, -#endif - -#ifdef XNRG_28 - &Xnrg28, -#endif - -#ifdef XNRG_29 - &Xnrg29, -#endif - -#ifdef XNRG_30 - &Xnrg30, -#endif - -#ifdef XNRG_31 - &Xnrg31, -#endif - -#ifdef XNRG_32 - &Xnrg32 -#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) -{ - DEBUG_TRACE_LOG(PSTR("NRG: %d"), 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 "/workspace/Tasmota/tasmota/xsns_01_counter.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_01_counter.ino" -#ifdef USE_COUNTER - - - - -#define XSNS_01 1 - -#define USE_AC_ZERO_CROSS_DIMMER 1 - -#define D_PRFX_COUNTER "Counter" -#define D_CMND_COUNTERTYPE "Type" -#define D_CMND_COUNTERDEBOUNCE "Debounce" -#define D_CMND_COUNTERDEBOUNCELOW "DebounceLow" -#define D_CMND_COUNTERDEBOUNCEHIGH "DebounceHigh" - -const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" - "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE "|" D_CMND_COUNTERDEBOUNCELOW "|" D_CMND_COUNTERDEBOUNCEHIGH ; - -void (* const CounterCommand[])(void) PROGMEM = { - &CmndCounter, &CmndCounterType, &CmndCounterDebounce, &CmndCounterDebounceLow, &CmndCounterDebounceHigh }; - -uint8_t ctr_index[MAX_COUNTERS] = { 0, 1, 2, 3 }; - -struct COUNTER { - uint32_t timer[MAX_COUNTERS]; - uint32_t timer_low_high[MAX_COUNTERS]; - uint8_t no_pullup = 0; - uint8_t pin_state = 0; - bool any_counter = false; - -} Counter; - -#ifdef USE_AC_ZERO_CROSS_DIMMER -struct AC_ZERO_CROSS_DIMMER { - bool startReSync = false; - uint32_t current_cycle_ClockCycles = 0; - uint32_t dimm_timeClockCycles = 0; - uint32_t currentCycleCount = 0; - uint32_t tobe_cycle_timeClockCycles = 0; - uint32_t lastCycleCount = 0; - uint32_t currentSteps = 100; -} ac_zero_cross_dimmer; -#endif - -void ICACHE_RAM_ATTR CounterIsrArg(void *arg) { - uint32_t index = *static_cast(arg); - - uint32_t time = micros(); - uint32_t debounce_time; - - if (Counter.pin_state) { - - if (digitalRead(Pin(GPIO_CNTR1, index)) == bitRead(Counter.pin_state, index)) { - - return; - } - debounce_time = time - Counter.timer_low_high[index]; - if bitRead(Counter.pin_state, index) { - - if (debounce_time <= Settings.pulse_counter_debounce_high * 1000) return; - } else { - - if (debounce_time <= Settings.pulse_counter_debounce_low * 1000) return; - } - - Counter.timer_low_high[index] = time; - Counter.pin_state ^= (1<0) { - ac_zero_cross_dimmer.startReSync = true; - ac_zero_cross_dimmer.currentSteps = (ac_zero_cross_dimmer.currentCycleCount-ac_zero_cross_dimmer.lastCycleCount+(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles/2))/(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles); - ac_zero_cross_dimmer.current_cycle_ClockCycles = (ac_zero_cross_dimmer.currentCycleCount-ac_zero_cross_dimmer.lastCycleCount)/ac_zero_cross_dimmer.currentSteps; - } - ac_zero_cross_dimmer.lastCycleCount = ac_zero_cross_dimmer.currentCycleCount; - } -#endif - return; - } - } - - 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]++; - } - } -} - - - -void CounterInterruptDisable(bool state) { - if (state) { - if (Counter.any_counter) { - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (PinUsed(GPIO_CNTR1, i)) { - detachInterrupt(Pin(GPIO_CNTR1, i)); - } - } - Counter.any_counter = false; - } - } else { - if (!Counter.any_counter) { - CounterInit(); - } - } -} - -bool CounterPinState(void) -{ - if ((XdrvMailbox.index >= AGPIO(GPIO_CNTR1_NP)) && (XdrvMailbox.index < (AGPIO(GPIO_CNTR1_NP) + MAX_COUNTERS))) { - bitSet(Counter.no_pullup, XdrvMailbox.index - AGPIO(GPIO_CNTR1_NP)); - XdrvMailbox.index -= (AGPIO(GPIO_CNTR1_NP) - AGPIO(GPIO_CNTR1)); - return true; - } - return false; -} - -void CounterInit(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (PinUsed(GPIO_CNTR1, i)) { -#ifdef USE_AC_ZERO_CROSS_DIMMER - ac_zero_cross_dimmer.tobe_cycle_timeClockCycles = microsecondsToClockCycles(1000000 / Settings.pwm_frequency); -#endif - Counter.any_counter = true; - pinMode(Pin(GPIO_CNTR1, i), bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); - if ((0 == Settings.pulse_counter_debounce_low) && (0 == Settings.pulse_counter_debounce_high) && !Settings.flag4.zerocross_dimmer) { - Counter.pin_state = 0; - attachInterruptArg(Pin(GPIO_CNTR1, i), CounterIsrArg, &ctr_index[i], FALLING); - } else { - Counter.pin_state = 0x8f; - attachInterruptArg(Pin(GPIO_CNTR1, i), CounterIsrArg, &ctr_index[i], CHANGE); - } - } - } -} - -void CounterEverySecond(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (PinUsed(GPIO_CNTR1, i)) { - if (bitRead(Settings.pulse_counter_type, i)) { - uint32_t time = micros() - Counter.timer[i]; - if (time > 4200000000) { - RtcSettings.pulse_counter[i] = 4200000000; - } - } - } - } -} - -void CounterSaveState(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (PinUsed(GPIO_CNTR1, i)) { - 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 (PinUsed(GPIO_CNTR1, i)) { - 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 - if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { - RtcSettings.pulse_counter[i] = 0; - } -#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 (header) { - ResponseJsonEnd(); - } -} - -#ifdef USE_AC_ZERO_CROSS_DIMMER -void SyncACDimmer(void) -{ - if (ac_zero_cross_dimmer.startReSync) { - - for (uint32_t i = 0; i < 1; i++) { - if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) - { - - const uint32_t current_cycle = ESP.getCycleCount(); - digitalWrite(Pin(GPIO_PWM1, i), LOW); - - ac_zero_cross_dimmer.startReSync = false; - - - ac_zero_cross_dimmer.dimm_timeClockCycles = (ac_zero_cross_dimmer.tobe_cycle_timeClockCycles * (1024 - (Light.fade_running ? Light.fade_cur_10[i] : Light.fade_start_10[i]))) / 1024; - ac_zero_cross_dimmer.dimm_timeClockCycles = tmax(ac_zero_cross_dimmer.dimm_timeClockCycles, 16000); - - uint32_t timelag_ClockCycles = (current_cycle - ac_zero_cross_dimmer.currentCycleCount)%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles; - timelag_ClockCycles = ((ac_zero_cross_dimmer.dimm_timeClockCycles + ac_zero_cross_dimmer.tobe_cycle_timeClockCycles) - timelag_ClockCycles)%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles; - delayMicroseconds(clockCyclesToMicroseconds(timelag_ClockCycles)); - - #ifdef ESP8266 - pinMode(Pin(GPIO_PWM1, i), OUTPUT); - - uint32_t high = ac_zero_cross_dimmer.current_cycle_ClockCycles / 256; - uint32_t low = ac_zero_cross_dimmer.current_cycle_ClockCycles - high; - - startWaveformClockCycles(Pin(GPIO_PWM1, i), high, low, 0, -1, 0, true); - #else - analogWrite(Pin(GPIO_PWM1, i), 5); - #endif - - } - } - } -} -#endif - - - - - -void CmndCounter(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.data_len > 0) && PinUsed(GPIO_CNTR1, XdrvMailbox.index -1)) { - 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) && PinUsed(GPIO_CNTR1, XdrvMailbox.index -1)) { - 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); -} - -void CmndCounterDebounceLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - Settings.pulse_counter_debounce_low = XdrvMailbox.payload; - CounterInit(); - } - ResponseCmndNumber(Settings.pulse_counter_debounce_low); -} - -void CmndCounterDebounceHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - Settings.pulse_counter_debounce_high = XdrvMailbox.payload; - CounterInit(); - } - ResponseCmndNumber(Settings.pulse_counter_debounce_high); -} - - - - - -bool Xsns01(uint8_t function) -{ - bool result = false; - - if (Counter.any_counter) { - switch (function) { - case FUNC_EVERY_SECOND: - CounterEverySecond(); - break; - case FUNC_JSON_APPEND: - CounterShow(1); - break; -#ifdef USE_AC_ZERO_CROSS_DIMMER - case FUNC_LOOP: - SyncACDimmer(); - break; -#endif -#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; - } - } else { - switch (function) { - case FUNC_INIT: - CounterInit(); - break; - case FUNC_PIN_STATE: - result = CounterPinState(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" -#ifdef USE_ADC - - - - -#define XSNS_02 2 - -#ifdef ESP8266 -#define ANALOG_RESOLUTION 10 -#define ANALOG_RANGE 1023 -#else -#undef ANALOG_RESOLUTION -#define ANALOG_RESOLUTION 12 -#undef ANALOG_RANGE -#define ANALOG_RANGE 4095 -#endif - -#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 -# 68 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" -#define ANALOG_CT_FLAGS 0 -#define ANALOG_CT_MULTIPLIER 2146 -#define ANALOG_CT_VOLTAGE 2300 - -#define CT_FLAG_ENERGY_RESET (1 << 0) -# 83 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" -#define ANALOG_BUTTON 128 -# 94 "/workspace/Tasmota/tasmota/xsns_02_analog.ino" -#define ANALOG_JOYSTICK (ANALOG_RANGE / 3) +100 - -struct { - uint8_t present = 0; - uint8_t type = 0; -} Adcs; - -struct { - float temperature = 0; - float current = 0; - float energy = 0; - uint32_t param1 = 0; - uint32_t param2 = 0; - int param3 = 0; - int param4 = 0; - uint32_t previous_millis = 0; - uint16_t last_value = 0; - uint8_t type = 0; - uint8_t pin = 0; -} Adc[MAX_ADCS]; - -#ifdef ESP8266 -bool adcAttachPin(uint8_t pin) { - return (ADC0_PIN == pin); -} -#endif - -void AdcSaveSettings(uint32_t idx) { - char parameters[32]; - snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"), - Adc[idx].type, Adc[idx].param1, Adc[idx].param2, Adc[idx].param3, Adc[idx].param4); - SettingsUpdateText(SET_ADC_PARAM1 + idx, parameters); -} - -void AdcGetSettings(uint32_t idx) { - char parameters[32]; - Adcs.type = 0; - Adc[idx].param1 = 0; - Adc[idx].param2 = 0; - Adc[idx].param3 = 0; - Adc[idx].param4 = 0; - if (strstr(SettingsText(SET_ADC_PARAM1 + idx), ",") != nullptr) { - Adcs.type = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 1)); - Adc[idx].param1 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 2)); - Adc[idx].param2 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 3)); - Adc[idx].param3 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 4)); - Adc[idx].param4 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 5)); - } -} - -void AdcInitParams(uint8_t idx) { - if ((Adcs.type != Adc[idx].type) || (Adc[idx].param1 > 1000000)) { - if (ADC_TEMP == Adc[idx].type) { - - Adc[idx].param1 = ANALOG_NTC_BRIDGE_RESISTANCE; - Adc[idx].param2 = ANALOG_NTC_RESISTANCE; - Adc[idx].param3 = ANALOG_NTC_B_COEFFICIENT * 10000; - } - else if (ADC_LIGHT == Adc[idx].type) { - Adc[idx].param1 = ANALOG_LDR_BRIDGE_RESISTANCE; - Adc[idx].param2 = ANALOG_LDR_LUX_CALC_SCALAR; - Adc[idx].param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; - } - else if (ADC_RANGE == Adc[idx].type) { - Adc[idx].param1 = 0; - Adc[idx].param2 = ANALOG_RANGE; - Adc[idx].param3 = 0; - Adc[idx].param4 = 100; - } - else if (ADC_CT_POWER == Adc[idx].type) { - Adc[idx].param1 = ANALOG_CT_FLAGS; - Adc[idx].param2 = ANALOG_CT_MULTIPLIER; - Adc[idx].param3 = ANALOG_CT_VOLTAGE; - } - } - if ((Adcs.type != Adc[idx].type) || (0 == Adc[idx].param1) || (Adc[idx].param1 > ANALOG_RANGE)) { - if ((ADC_BUTTON == Adc[idx].type) || (ADC_BUTTON_INV == Adc[idx].type)) { - Adc[idx].param1 = ANALOG_BUTTON; - } - else if (ADC_JOY == Adc[idx].type) { - Adc[idx].param1 = ANALOG_JOYSTICK; - } - } -} - -void AdcAttach(uint8_t pin, uint8_t type) { - if (Adcs.present == MAX_ADCS) { return; } - Adc[Adcs.present].pin = pin; - if (adcAttachPin(Adc[Adcs.present].pin)) { - Adc[Adcs.present].type = type; - - Adcs.present++; - } -} - -void AdcInit(void) { - Adcs.present = 0; - for (uint32_t i = 0; i < MAX_ADCS; i++) { - if (PinUsed(GPIO_ADC_INPUT, i)) { - AdcAttach(Pin(GPIO_ADC_INPUT, i), ADC_INPUT); - } - if (PinUsed(GPIO_ADC_TEMP, i)) { - AdcAttach(Pin(GPIO_ADC_TEMP, i), ADC_TEMP); - } - if (PinUsed(GPIO_ADC_LIGHT, i)) { - AdcAttach(Pin(GPIO_ADC_LIGHT, i), ADC_LIGHT); - } - if (PinUsed(GPIO_ADC_RANGE, i)) { - AdcAttach(Pin(GPIO_ADC_RANGE, i), ADC_RANGE); - } - if (PinUsed(GPIO_ADC_CT_POWER, i)) { - AdcAttach(Pin(GPIO_ADC_CT_POWER, i), ADC_CT_POWER); - } - if (PinUsed(GPIO_ADC_JOY, i)) { - AdcAttach(Pin(GPIO_ADC_JOY, i), ADC_JOY); - } - } - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if (PinUsed(GPIO_ADC_BUTTON, i)) { - AdcAttach(Pin(GPIO_ADC_BUTTON, i), ADC_BUTTON); - } - else if (PinUsed(GPIO_ADC_BUTTON_INV, i)) { - AdcAttach(Pin(GPIO_ADC_BUTTON_INV, i), ADC_BUTTON_INV); - } - } - - if (Adcs.present) { -#ifdef ESP32 - analogSetClockDiv(1); - analogSetWidth(ANALOG_RESOLUTION); - analogSetAttenuation(ADC_11db); -#endif - for (uint32_t idx = 0; idx < Adcs.present; idx++) { - AdcGetSettings(idx); - AdcInitParams(idx); - AdcSaveSettings(idx); - } - } -} - -uint16_t AdcRead(uint32_t pin, uint32_t factor) { - - - - - - uint32_t samples = 1 << factor; - uint32_t analog = 0; - for (uint32_t i = 0; i < samples; i++) { - analog += analogRead(pin); - delay(1); - } - analog >>= factor; - return analog; -} - -#ifdef USE_RULES -void AdcEvery250ms(void) { - char adc_idx[3] = { 0 }; - uint32_t offset = 0; - for (uint32_t idx = 0; idx < Adcs.present; idx++) { -#ifdef ESP32 - snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1); - offset = 1; -#endif - if (ADC_INPUT == Adc[idx].type) { - uint16_t new_value = AdcRead(Adc[idx].pin, 5); - if ((new_value < Adc[idx].last_value -10) || (new_value > Adc[idx].last_value +10)) { - Adc[idx].last_value = new_value; - uint16_t value = Adc[idx].last_value / 10; - Response_P(PSTR("{\"ANALOG\":{\"A%ddiv10\":%d}}"), idx + offset, (value > 99) ? 100 : value); - XdrvRulesProcess(); - } - } - else if (ADC_JOY == Adc[idx].type) { - uint16_t new_value = AdcRead(Adc[idx].pin, 1); - if (new_value && (new_value != Adc[idx].last_value)) { - Adc[idx].last_value = new_value; - uint16_t value = new_value / Adc[idx].param1; - Response_P(PSTR("{\"ANALOG\":{\"Joy%s\":%d}}"), adc_idx, value); - XdrvRulesProcess(); - } else { - Adc[idx].last_value = 0; - } - } - } -} -#endif - -uint8_t AdcGetButton(uint32_t pin) { - for (uint32_t idx = 0; idx < Adcs.present; idx++) { - if (Adc[idx].pin == pin) { - if (ADC_BUTTON_INV == Adc[idx].type) { - return (AdcRead(Adc[idx].pin, 1) < Adc[idx].param1); - } - else if (ADC_BUTTON == Adc[idx].type) { - return (AdcRead(Adc[idx].pin, 1) > Adc[idx].param1); - } - } - } - return 0; -} - -uint16_t AdcGetLux(uint32_t idx) { - int adc = AdcRead(Adc[idx].pin, 2); - - double resistorVoltage = ((double)adc / ANALOG_RANGE) * ANALOG_V33; - double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * (double)Adc[idx].param1; - double ldrLux = (double)Adc[idx].param2 * FastPrecisePow(ldrResistance, (double)Adc[idx].param3 / 10000); - - return (uint16_t)ldrLux; -} - -uint16_t AdcGetRange(uint32_t idx) { - - - - int adc = AdcRead(Adc[idx].pin, 2); - double adcrange = ( ((double)Adc[idx].param2 - (double)adc) / ( ((double)Adc[idx].param2 - (double)Adc[idx].param1)) * ((double)Adc[idx].param3 - (double)Adc[idx].param4) + (double)Adc[idx].param4 ); - return (uint16_t)adcrange; -} - -void AdcGetCurrentPower(uint8_t idx, uint8_t factor) { - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - uint16_t analog_min = ANALOG_RANGE; - uint16_t analog_max = 0; - - if (0 == Adc[idx].param1) { - for (uint32_t i = 0; i < samples; i++) { - analog = analogRead(Adc[idx].pin); - if (analog < analog_min) { - analog_min = analog; - } - if (analog > analog_max) { - analog_max = analog; - } - delay(1); - } - Adc[idx].current = (float)(analog_max-analog_min) * ((float)(Adc[idx].param2) / 100000); - } - else { - analog = AdcRead(Adc[idx].pin, 5); - if (analog > Adc[idx].param1) { - Adc[idx].current = ((float)(analog) - (float)Adc[idx].param1) * ((float)(Adc[idx].param2) / 100000); - } - else { - Adc[idx].current = 0; - } - } - - float power = Adc[idx].current * (float)(Adc[idx].param3) / 10; - uint32_t current_millis = millis(); - Adc[idx].energy = Adc[idx].energy + ((power * (current_millis - Adc[idx].previous_millis)) / 3600000000); - Adc[idx].previous_millis = current_millis; -} - -void AdcEverySecond(void) { - for (uint32_t idx = 0; idx < Adcs.present; idx++) { - if (ADC_TEMP == Adc[idx].type) { - int adc = AdcRead(Adc[idx].pin, 2); - - double Rt = (adc * Adc[idx].param1) / (1024.0 * ANALOG_V33 - (double)adc); - double BC = (double)Adc[idx].param3 / 10000; - double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2)); - Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T)); - } - else if (ADC_CT_POWER == Adc[idx].type) { - AdcGetCurrentPower(idx, 5); - } - } -} - -void AdcShowContinuation(bool *jsonflg) { - if (*jsonflg) { - ResponseAppend_P(PSTR(",")); - } else { - ResponseAppend_P(PSTR(",\"ANALOG\":{")); - *jsonflg = true; - } -} - -void AdcShow(bool json) { - bool domo_flag[ADC_END] = { false }; - char adc_name[10] = { 0 }; - char adc_idx[3] = { 0 }; - uint32_t offset = 0; - - bool jsonflg = false; - for (uint32_t idx = 0; idx < Adcs.present; idx++) { -#ifdef ESP32 - snprintf_P(adc_name, sizeof(adc_name), PSTR("Analog%d"), idx +1); - snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1); - offset = 1; -#endif - - switch (Adc[idx].type) { - case ADC_INPUT: { - uint16_t analog = AdcRead(Adc[idx].pin, 5); - - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"A%d\":%d"), idx + offset, analog); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ANALOG, "", idx + offset, analog); -#endif - } - break; - } - case ADC_TEMP: { - char temperature[33]; - dtostrfd(Adc[idx].temperature, Settings.flag2.temperature_resolution, temperature); - - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "%s\":%s"), adc_idx, temperature); - if ((0 == tele_period) && (!domo_flag[ADC_TEMP])) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); - domo_flag[ADC_TEMP] = true; -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, Adc[idx].temperature); -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, adc_name, temperature, TempUnit()); -#endif - } - break; - } - case ADC_LIGHT: { - uint16_t adc_light = AdcGetLux(idx); - - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"" D_JSON_ILLUMINANCE "%s\":%d"), adc_idx, adc_light); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (!domo_flag[ADC_LIGHT])) { - DomoticzSensor(DZ_ILLUMINANCE, adc_light); - domo_flag[ADC_LIGHT] = true; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, adc_name, adc_light); -#endif - } - break; - } - case ADC_RANGE: { - uint16_t adc_range = AdcGetRange(idx); - - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"" D_JSON_RANGE "%s\":%d"), adc_idx, adc_range); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_RANGE, adc_name, adc_range); -#endif - } - break; - } - case ADC_CT_POWER: { - AdcGetCurrentPower(idx, 5); - - float voltage = (float)(Adc[idx].param3) / 10; - char voltage_chr[FLOATSZ]; - dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); - char current_chr[FLOATSZ]; - dtostrfd(Adc[idx].current, Settings.flag2.current_resolution, current_chr); - char power_chr[FLOATSZ]; - dtostrfd(voltage * Adc[idx].current, Settings.flag2.wattage_resolution, power_chr); - char energy_chr[FLOATSZ]; - dtostrfd(Adc[idx].energy, Settings.flag2.energy_resolution, energy_chr); - - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"CTEnergy%s\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - adc_idx, energy_chr, power_chr, voltage_chr, current_chr); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (!domo_flag[ADC_CT_POWER])) { - DomoticzSensor(DZ_POWER_ENERGY, power_chr); - DomoticzSensor(DZ_VOLTAGE, voltage_chr); - DomoticzSensor(DZ_CURRENT, current_chr); - domo_flag[ADC_CT_POWER] = true; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); - WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); - WSContentSend_PD(HTTP_SNS_POWER, power_chr); - WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); -#endif - } - break; - } - case ADC_JOY: { - uint16_t new_value = AdcRead(Adc[idx].pin, 1); - uint16_t value = new_value / Adc[idx].param1; - if (json) { - AdcShowContinuation(&jsonflg); - ResponseAppend_P(PSTR("\"Joy%s\":%d"), adc_idx, value); - } - break; - } - } - } - if (jsonflg) { - ResponseJsonEnd(); - } -} - - - - - -const char kAdcCommands[] PROGMEM = "|" - D_CMND_ADCPARAM; - -void (* const AdcCommand[])(void) PROGMEM = { - &CmndAdcParam }; - -void CmndAdcParam(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_ADCS)) { - uint8_t idx = XdrvMailbox.index -1; - if (XdrvMailbox.data_len) { - if (XdrvMailbox.payload > ADC_INPUT) { - AdcGetSettings(idx); - if (ChrCount(XdrvMailbox.data, ",") > 2) { - char sub_string[XdrvMailbox.data_len +1]; - - - - - - - - Adc[idx].type = XdrvMailbox.payload; - Adc[idx].param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Adc[idx].param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - if (ADC_RANGE == XdrvMailbox.payload) { - Adc[idx].param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); - Adc[idx].param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); - } else { - Adc[idx].param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); - } - if (ADC_CT_POWER == XdrvMailbox.payload) { - if (((1 == Adc[idx].param1) & CT_FLAG_ENERGY_RESET) > 0) { - for (uint32_t idx = 0; idx < MAX_ADCS; idx++) { - Adc[idx].energy = 0; - } - Adc[idx].param1 ^= CT_FLAG_ENERGY_RESET; - } - } - } else { - - - - - - - - Adcs.type = 0; - AdcInitParams(idx); - } - AdcSaveSettings(idx); - } - } - - - AdcGetSettings(idx); - Response_P(PSTR("{\"" D_CMND_ADCPARAM "%d\":[%d,%d,%d"), idx +1, Adcs.type, Adc[idx].param1, Adc[idx].param2); - if (ADC_RANGE == Adc[idx].type) { - ResponseAppend_P(PSTR(",%d,%d"), Adc[idx].param3, Adc[idx].param4); - } else { - int value = Adc[idx].param3; - uint8_t precision; - for (precision = 4; precision > 0; precision--) { - if (value % 10) { break; } - value /= 10; - } - char param3[33]; - dtostrfd(((double)Adc[idx].param3)/10000, precision, param3); - ResponseAppend_P(PSTR(",%s"), param3); - } - ResponseAppend_P(PSTR("]}")); - } -} - - - - - -bool Xsns02(uint8_t function) { - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kAdcCommands, AdcCommand); - break; - case FUNC_MODULE_INIT: - AdcInit(); - break; - default: - if (Adcs.present) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdcEvery250ms(); - break; -#endif - case FUNC_EVERY_SECOND: - AdcEverySecond(); - break; - case FUNC_JSON_APPEND: - AdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AdcShow(0); - break; -#endif - } - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_04_snfsc.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_04_snfsc.ino" -#ifdef USE_SONOFF_SC -# 57 "/workspace/Tasmota/tasmota/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]); - - if (json) { - ResponseAppend_P(PSTR(",\"SonoffSC\":{")); - ResponseAppendTHD(t, h); - ResponseAppend_P(PSTR(",\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), sc_value[2], sc_value[3], sc_value[4]); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumPressureSensor(t, h); - 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_THD("", t, h); - 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_JSON_APPEND: - SonoffScShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SonoffScShow(0); - break; -#endif - case FUNC_INIT: - SonoffScInit(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" -#ifdef ESP8266 -#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; -uint8_t ds18x20_pin_out = 0; -bool ds18x20_dual_mode = false; -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; - - if (!ds18x20_dual_mode) { - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : 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, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - delayMicroseconds(410); - return r; - } else { - digitalWrite(ds18x20_pin_out, HIGH); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(480); - digitalWrite(ds18x20_pin_out, HIGH); - 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; - if (!ds18x20_dual_mode) { - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - } else { - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(delay_high[v]); -} - -uint8_t OneWire1ReadBit(void) -{ - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - delayMicroseconds(53); - return r; -} - -uint8_t OneWire2ReadBit(void) -{ - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(3); - digitalWrite(ds18x20_pin_out, HIGH); - 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; - - if (!ds18x20_dual_mode) { - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWire1ReadBit()) { - r |= bit_mask; - } - } - } else { - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWire2ReadBit()) { - 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 { - if (!ds18x20_dual_mode) { - id_bit = OneWire1ReadBit(); - cmp_id_bit = OneWire1ReadBit(); - } else { - id_bit = OneWire2ReadBit(); - cmp_id_bit = OneWire2ReadBit(); - } - 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); - - if (PinUsed(GPIO_DSB_OUT)) { - ds18x20_pin_out = Pin(GPIO_DSB_OUT); - ds18x20_dual_mode = true; - pinMode(ds18x20_pin_out, OUTPUT); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } - - 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: { -# 389 "/workspace/Tasmota/tasmota/xsns_05_ds18x20.ino" - int16_t tempS = (((data[1] << 8) | (data[0] & 0xFE)) << 3) | ((0x10 - data[6]) & 0x0F); - ds18x20_sensor[index].temperature = ConvertTemp(tempS * 0.0625 - 0.250); - - 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) -{ - if (!ds18x20_sensors) { return; } - -#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) { - 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 (PinUsed(GPIO_DSB)) { - 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 -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_05_ds18x20_esp32.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_05_ds18x20_esp32.ino" -#ifdef ESP32 -#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_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 }; - -uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; -uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_valid[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_sensors = 0; -char ds18x20_types[12]; - - - -#include - -OneWire *ds = nullptr; - -void Ds18x20Init(void) { - ds = new OneWire(Pin(GPIO_DSB)); - - Ds18x20Search(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); -} - -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]==DS1822_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; -} - -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; - - t = NAN; - - uint8_t index = ds18x20_index[sensor]; - if (ds18x20_valid[index]) { ds18x20_valid[index]--; } - - ds->reset(); - ds->select(ds18x20_address[index]); - 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[index][0]) { - case DS18S20_CHIPID: { - int16_t tempS = (((data[1] << 8) | (data[0] & 0xFE)) << 3) | ((0x10 - data[6]) & 0x0F); - t = ConvertTemp(tempS * 0.0625 - 0.250); - ds18x20_valid[index] = SENSOR_MAX_MISS; - return true; - } - case DS1822_CHIPID: - case DS18B20_CHIPID: { - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - t = ConvertTemp(sign * temp12 * 0.0625); - ds18x20_valid[index] = SENSOR_MAX_MISS; - return true; - } - case MAX31850_CHIPID: { - int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); - t = ConvertTemp(temp14 * 0.0625); - ds18x20_valid[index] = 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_address[ds18x20_index[sensor]][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) -{ - if (!ds18x20_sensors) { return; } - - if (uptime & 1) { - - - Ds18x20Convert(); - } else { - float t; - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - - if (!Ds18x20Read(i, t)) { - Ds18x20Name(i); - AddLogMissed(ds18x20_types, ds18x20_valid[ds18x20_index[i]]); - } - } - } -} - -void Ds18x20Show(bool json) -{ - float t; - - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - if (Ds18x20Read(i, t)) { - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - Ds18x20Name(i); - - if (json) { - char address[17]; - for (uint32_t j = 0; j < 6; j++) { - sprintf(address+2*j, "%02X", ds18x20_address[ds18x20_index[i]][6-j]); - } - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); - dsxflg++; -#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 { - WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); -#endif - } - } - } -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_DSB)) { - 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 -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" -#ifdef USE_DHT -# 30 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - uint8_t lastresult; - char stype[12]; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtWaitState(uint32_t sensor, uint32_t level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (TimeReachedUsec(timeout)) { - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), - (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); - return false; - } - delayMicroseconds(1); - } - return true; -} - -bool DhtRead(uint32_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - - delayMicroseconds(2000); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - delayMicroseconds(20); - break; - } -# 134 "/workspace/Tasmota/tasmota/xsns_06_dht.ino" - uint32_t i = 0; - noInterrupts(); - if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { - for (i = 0; i < 40; i++) { - if (!DhtWaitState(sensor, 1)) { break; } - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - dht_data[i / 8] |= (1 << (7 - i % 8)); - } - if (!DhtWaitState(sensor, 0)) { break; } - } - } - interrupts(); - if (i < 40) { return false; } - - 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; - } - - float temperature = NAN; - float humidity = NAN; - switch (Dht[sensor].type) { - case GPIO_DHT11: - humidity = dht_data[0]; - temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - temperature *= -1; - } - break; - } - if (isnan(temperature) || isnan(humidity)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); - return false; - } - - if (humidity > 100) { humidity = 100.0; } - if (humidity < 0) { humidity = 0.1; } - Dht[sensor].h = ConvertHumidity(humidity); - Dht[sensor].t = ConvertTemp(temperature); - Dht[sensor].lastresult = 0; - - return true; -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= AGPIO(GPIO_DHT11)) && (XdrvMailbox.index <= AGPIO(GPIO_SI7021))) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = BGPIO(XdrvMailbox.index); - dht_sensors++; - XdrvMailbox.index = AGPIO(GPIO_DHT11); - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (PinUsed(GPIO_DHT11_OUT)) { - dht_pin_out = Pin(GPIO_DHT11_OUT); - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastresult = DHT_MAX_RETRY; - 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); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { - - if (!DhtRead(sensor)) { - Dht[sensor].lastresult++; - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - } - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), Dht[i].stype, Dht[i].t, Dht[i].h); - } -} - - - - - -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 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" -#ifdef USE_I2C -#ifdef USE_SHT -# 31 "/workspace/Tasmota/tasmota/xsns_07_sht1x.ino" -#define XSNS_07 7 -#define XI2C_08 8 - -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) { - - 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)); - - 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); - sht_humidity = ConvertHumidity(sht_humidity); - - sht_valid = SENSOR_MAX_MISS; - return true; -} - - - -void ShtDetect(void) -{ - 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 (!(uptime %4)) { - - if (!ShtRead()) { - AddLogMissed(sht_types, sht_valid); - } - } -} - -void ShtShow(bool json) -{ - if (sht_valid) { - TempHumDewShow(json, (0 == tele_period), sht_types, sht_temperature, sht_humidity); - } -} - - - - - -bool Xsns07(uint8_t function) -{ - if (!I2cEnabled(XI2C_08)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - ShtDetect(); - } - else if (sht_type) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" -#ifdef USE_I2C -#ifdef USE_HTU -# 30 "/workspace/Tasmota/tasmota/xsns_08_htu21.ino" -#define XSNS_08 8 -#define XI2C_09 9 - -#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?"; - -struct { - float temperature = 0; - float humidity = 0; - uint8_t address; - uint8_t type = 0; - uint8_t delay_temp; - uint8_t delay_humidity = 50; - uint8_t valid = 0; - char types[7]; -} Htu; - - - -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) -{ - HtuReset(); - - 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; - } - Htu.humidity = ConvertHumidity(Htu.humidity); - - Htu.valid = SENSOR_MAX_MISS; - return true; -} - - - -void HtuDetect(void) -{ - Htu.address = HTU21_ADDR; - if (I2cActive(Htu.address)) { return; } - - 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); - I2cSetActiveFound(Htu.address, Htu.types); - } -} - -void HtuEverySecond(void) -{ - if (uptime &1) { - - if (!HtuRead()) { - AddLogMissed(Htu.types, Htu.valid); - } - } -} - -void HtuShow(bool json) -{ - if (Htu.valid) { - TempHumDewShow(json, (0 == tele_period), Htu.types, Htu.temperature, Htu.humidity); - } -} - - - - - -bool Xsns08(uint8_t function) -{ - if (!I2cEnabled(XI2C_09)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - HtuDetect(); - } - else if (Htu.type) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" -#ifdef USE_I2C -#ifdef USE_BMP -# 30 "/workspace/Tasmota/tasmota/xsns_09_bmp.ino" -#define XSNS_09 9 -#define XI2C_10 10 - -#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_REGISTER_RESET 0xE0 - -#define BMP_CMND_RESET 0xB6 - -#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) -{ - 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++) { - if (I2cActive(bmp_addresses[i])) { continue; } - 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); - I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); - bmp_count++; - } - } - } -} - -void BmpRead(void) -{ - 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 - } - } -} - -void BmpShow(bool json) -{ - 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); - - float bmp_humidity = ConvertHumidity(bmp_sensors[bmp_idx].bmp_humidity); - char humidity[33]; - dtostrfd(bmp_humidity, Settings.flag2.humidity_resolution, humidity); - float f_dewpoint = CalcTempHumToDew(bmp_temperature, bmp_humidity); - char dewpoint[33]; - dtostrfd(f_dewpoint, Settings.flag2.temperature_resolution, dewpoint); -#ifdef USE_BME680 - char gas_resistance[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); -#endif - - if (json) { - char json_humidity[80]; - snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_DEWPOINT "\":%s"), humidity, dewpoint); - 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(bmp_temperature, bmp_humidity, bmp_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_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_DEW, name, dewpoint, TempUnit()); - } - 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 - } - } - } -} - -#ifdef USE_DEEPSLEEP - -void BMP_EnterSleep(void) -{ - if (DeepSleepEnabled()) { - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - case BMP280_CHIPID: - case BME280_CHIPID: - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); - break; - default: - break; - } - } - } -} - -#endif - - - - - -bool Xsns09(uint8_t function) -{ - if (!I2cEnabled(XI2C_10)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - BmpDetect(); - } - else if (bmp_count) { - switch (function) { - case FUNC_EVERY_SECOND: - BmpRead(); - break; - case FUNC_JSON_APPEND: - BmpShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - BmpShow(0); - break; -#endif -#ifdef USE_DEEPSLEEP - case FUNC_SAVE_BEFORE_RESTART: - BMP_EnterSleep(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" -#ifdef USE_I2C -#ifdef USE_BH1750 -# 33 "/workspace/Tasmota/tasmota/xsns_10_bh1750.ino" -#define XSNS_10 10 -#define XI2C_11 11 - -#define BH1750_ADDR1 0x23 -#define BH1750_ADDR2 0x5C - -#define BH1750_CONTINUOUS_HIGH_RES_MODE2 0x11 -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 -#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 - -#define BH1750_MEASUREMENT_TIME_HIGH 0x40 -#define BH1750_MEASUREMENT_TIME_LOW 0x60 - -#define D_PRFX_BH1750 "Bh1750" -#define D_CMND_RESOLUTION "Resolution" -#define D_CMND_MTREG "MTime" - -const char kBh1750Commands[] PROGMEM = D_PRFX_BH1750 "|" - D_CMND_RESOLUTION "|" D_CMND_MTREG ; - -void (* const Bh1750Command[])(void) PROGMEM = { - &CmndBh1750Resolution, &CmndBh1750MTime }; - -struct { - uint8_t addresses[2] = { BH1750_ADDR1, BH1750_ADDR2 }; - uint8_t resolution[3] = { BH1750_CONTINUOUS_HIGH_RES_MODE, BH1750_CONTINUOUS_HIGH_RES_MODE2, BH1750_CONTINUOUS_LOW_RES_MODE }; - uint8_t count = 0; - char types[7] = "BH1750"; -} Bh1750; - -struct { - uint8_t address; - uint8_t valid = 0; - uint8_t mtreg = 69; - uint16_t illuminance = 0; -} Bh1750_sensors[2]; - - - -uint8_t Bh1750Resolution(uint32_t sensor_index) { - uint8_t settings_resolution = Settings.SensorBits1.bh1750_1_resolution; - if (1 == sensor_index) { - settings_resolution = Settings.SensorBits1.bh1750_2_resolution; - } - return settings_resolution; -} - -bool Bh1750SetResolution(uint32_t sensor_index) { - Wire.beginTransmission(Bh1750_sensors[sensor_index].address); - Wire.write(Bh1750.resolution[Bh1750Resolution(sensor_index)]); - return (!Wire.endTransmission()); -} - -bool Bh1750SetMTreg(uint32_t sensor_index) { - Wire.beginTransmission(Bh1750_sensors[sensor_index].address); - uint8_t data = BH1750_MEASUREMENT_TIME_HIGH | ((Bh1750_sensors[sensor_index].mtreg >> 5) & 0x07); - Wire.write(data); - if (Wire.endTransmission()) { return false; } - Wire.beginTransmission(Bh1750_sensors[sensor_index].address); - data = BH1750_MEASUREMENT_TIME_LOW | (Bh1750_sensors[sensor_index].mtreg & 0x1F); - Wire.write(data); - if (Wire.endTransmission()) { return false; } - return Bh1750SetResolution(sensor_index); -} - -bool Bh1750Read(uint32_t sensor_index) { - if (Bh1750_sensors[sensor_index].valid) { Bh1750_sensors[sensor_index].valid--; } - - if (2 != Wire.requestFrom(Bh1750_sensors[sensor_index].address, (uint8_t)2)) { return false; } - - float illuminance = (Wire.read() << 8) | Wire.read(); - illuminance /= (1.2 * (69 / (float)Bh1750_sensors[sensor_index].mtreg)); - if (1 == Bh1750Resolution(sensor_index)) { - illuminance /= 2; - } - Bh1750_sensors[sensor_index].illuminance = illuminance; - - Bh1750_sensors[sensor_index].valid = SENSOR_MAX_MISS; - return true; -} - - - -void Bh1750Detect(void) { - for (uint32_t i = 0; i < sizeof(Bh1750.addresses); i++) { - if (I2cActive(Bh1750.addresses[i])) { continue; } - - Bh1750_sensors[Bh1750.count].address = Bh1750.addresses[i]; - if (Bh1750SetMTreg(Bh1750.count)) { - I2cSetActiveFound(Bh1750_sensors[Bh1750.count].address, Bh1750.types); - Bh1750.count++; - } - } -} - -void Bh1750EverySecond(void) { - for (uint32_t i = 0; i < Bh1750.count; i++) { - - if (!Bh1750Read(i)) { - - } - } -} - - - - - -void CmndBh1750Resolution(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Bh1750.count)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - if (1 == XdrvMailbox.index) { - Settings.SensorBits1.bh1750_1_resolution = XdrvMailbox.payload; - } else { - Settings.SensorBits1.bh1750_2_resolution = XdrvMailbox.payload; - } - Bh1750SetResolution(XdrvMailbox.index -1); - } - ResponseCmndIdxNumber(Bh1750Resolution(XdrvMailbox.index -1)); - } -} - -void CmndBh1750MTime(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Bh1750.count)) { - if ((XdrvMailbox.payload > 30) && (XdrvMailbox.payload < 255)) { - Bh1750_sensors[XdrvMailbox.index -1].mtreg = XdrvMailbox.payload; - Bh1750SetMTreg(XdrvMailbox.index -1); - } - ResponseCmndIdxNumber(Bh1750_sensors[XdrvMailbox.index -1].mtreg); - } -} - - - -void Bh1750Show(bool json) { - for (uint32_t sensor_index = 0; sensor_index < Bh1750.count; sensor_index++) { - if (Bh1750_sensors[sensor_index].valid) { - char sensor_name[10]; - strlcpy(sensor_name, Bh1750.types, sizeof(sensor_name)); - if (Bh1750.count > 1) { - snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), Bh1750_sensors[sensor_index].address); - } - - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, sensor_name, Bh1750_sensors[sensor_index].illuminance); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == sensor_index)) { - DomoticzSensor(DZ_ILLUMINANCE, Bh1750_sensors[sensor_index].illuminance); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor_name, Bh1750_sensors[sensor_index].illuminance); -#endif - } - } - } -} - - - - - -bool Xsns10(uint8_t function) { - if (!I2cEnabled(XI2C_11)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Bh1750Detect(); - } - else if (Bh1750.count) { - switch (function) { - case FUNC_EVERY_SECOND: - Bh1750EverySecond(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kBh1750Commands, Bh1750Command); - break; - case FUNC_JSON_APPEND: - Bh1750Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bh1750Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_11_veml6070.ino" -# 89 "/workspace/Tasmota/tasmota/xsns_11_veml6070.ino" -#ifdef USE_I2C -#ifdef USE_VEML6070 - - - - - - -#define XSNS_11 11 -#define XI2C_12 12 - -#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; -char veml6070_name[9]; -char str_uvrisk_text[10]; - - - -void Veml6070Detect(void) -{ - if (I2cActive(VEML6070_ADDR_L)) { return; } - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((itime << 2) | 0x02); - uint8_t status = Wire.endTransmission(); - - if (!status) { - veml6070_type = 1; - Veml6070UvTableInit(); - uint8_t veml_model = 0; - GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); - I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); - } -} - - - -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) -{ - - 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, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); - } -} - - - -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) -{ - - 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) -{ - if (!I2cEnabled(XI2C_12)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Veml6070Detect(); - } - else if (veml6070_type) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" -#ifdef USE_I2C -#ifdef USE_ADS1115 -# 43 "/workspace/Tasmota/tasmota/xsns_12_ads1115.ino" -#define XSNS_12 12 -#define XI2C_13 13 - -#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) - -struct ADS1115 { - uint8_t count = 0; - uint8_t address; - uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; - uint8_t found[4] = {false,false,false,false}; - int16_t last_values[4][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}; -} Ads1115; - - - -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) -{ - for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { - if (!Ads1115.found[i]) { - Ads1115.address = Ads1115.addresses[i]; - if (I2cActive(Ads1115.address)) { continue; } - uint16_t buffer; - if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && - I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { - Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); - I2cSetActiveFound(Ads1115.address, "ADS1115"); - Ads1115.found[i] = 1; - Ads1115.count++; - } - } - } -} - - -void Ads1115Label(char* label, uint32_t maxsize, uint8_t address) { - if (1 == Ads1115.count) { - - snprintf_P(label, maxsize, PSTR("ADS1115")); - } else { - - snprintf_P(label, maxsize, PSTR("ADS1115%c%02x"), IndexSeparator(), address); - } -} - -#ifdef USE_RULES - - -void AdsEvery250ms(void) -{ - int16_t value; - - for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { - if (Ads1115.found[t]) { - - uint8_t old_address = Ads1115.address; - Ads1115.address = Ads1115.addresses[t]; - - - uint32_t changed = 0; - for (uint32_t i = 0; i < 4; i++) { - value = Ads1115GetConversion(i); - - - - if (value >= Ads1115.last_values[t][i] + 327 || value <= Ads1115.last_values[t][i] - 327) { - Ads1115.last_values[t][i] = value; - bitSet(changed, i); - } - } - Ads1115.address = old_address; - if (changed) { - char label[15]; - Ads1115Label(label, sizeof(label), Ads1115.addresses[t]); - - Response_P(PSTR("{\"%s\":{"), label); - - bool first = true; - for (uint32_t i = 0; i < 4; i++) { - if (bitRead(changed, i)) { - ResponseAppend_P(PSTR("%s\"A%ddiv10\":%d"), (first) ? "" : ",", i, Ads1115.last_values[t][i]); - first = false; - } - } - ResponseJsonEndEnd(); - - XdrvRulesProcess(); - } - - } - } -} -#endif - -void Ads1115Show(bool json) -{ - int16_t values[4]; - - for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { - - if (Ads1115.found[t]) { - - uint8_t old_address = Ads1115.address; - Ads1115.address = Ads1115.addresses[t]; - for (uint32_t i = 0; i < 4; i++) { - values[i] = Ads1115GetConversion(i); - - } - Ads1115.address = old_address; - - char label[15]; - Ads1115Label(label, sizeof(label), Ads1115.addresses[t]); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{"), label); - for (uint32_t i = 0; i < 4; i++) { - ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); - } - ResponseJsonEnd(); - } -#ifdef USE_WEBSERVER - else { - for (uint32_t i = 0; i < 4; i++) { - WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); - } - } -#endif - } - } -} - - - - - -bool Xsns12(uint8_t function) -{ - if (!I2cEnabled(XI2C_13)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ads1115Detect(); - } - else if (Ads1115.count) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdsEvery250ms(); - break; -#endif - case FUNC_JSON_APPEND: - Ads1115Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ads1115Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" -#ifdef USE_I2C -#ifdef USE_INA219 -# 30 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" -#define XSNS_13 13 -#define XI2C_14 14 - -#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_1S_84US (0x0<<7) -#define INA219_CONFIG_BADCRES_10BIT_1S_148US (0x1<<7) -#define INA219_CONFIG_BADCRES_11BIT_1S_276US (0x2<<7) -#define INA219_CONFIG_BADCRES_12BIT_1S_532US (0x3<<7) -#define INA219_CONFIG_BADCRES_12BIT_2S_1060US (0x9<<7) -#define INA219_CONFIG_BADCRES_12BIT_4S_2130US (0xA<<7) -#define INA219_CONFIG_BADCRES_12BIT_8S_4260US (0xB<<7) -#define INA219_CONFIG_BADCRES_12BIT_16S_8510US (0xC<<7) -#define INA219_CONFIG_BADCRES_12BIT_32S_17MS (0xD<<7) -#define INA219_CONFIG_BADCRES_12BIT_64S_34MS (0xE<<7) -#define INA219_CONFIG_BADCRES_12BIT_128S_69MS (0xF<<7) - -#define INA219_CONFIG_SADCRES_MASK (0x0078) -#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0<<3) -#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x1<<3) -#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x2<<3) -#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x3<<3) -#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x9<<3) -#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0xA<<3) -#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0xB<<3) -#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0xC<<3) -#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0xD<<3) -#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0xE<<3) -#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0xF<<3) - -#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) - -#define INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS (100.0) - -uint8_t ina219_type[4] = {0,0,0,0}; -uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; - -#ifdef DEBUG_TASMOTA_SENSOR - -char __ina219_dbg1[10]; -char __ina219_dbg2[10]; -#endif - - - - -float ina219_current_multiplier; - -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"; -uint8_t ina219_count = 0; -# 132 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" -bool Ina219SetCalibration(uint8_t mode, uint16_t addr) -{ - uint16_t config = 0; - - DEBUG_SENSOR_LOG("Ina219SetCalibration: mode=%d",mode); - if (mode < 5) - { - - ina219_current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; - #ifdef DEBUG_TASMOTA_SENSOR - dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); - DEBUG_SENSOR_LOG("Ina219SetCalibration: cur_mul=%s",__ina219_dbg1); - #endif - } - else if (mode >= 10) - { - int mult = mode % 10; - int shunt_milliOhms = mode / 10; - for ( ; mult > 0 ; mult-- ) - shunt_milliOhms *= 10; - ina219_current_multiplier = 1.0 / shunt_milliOhms; - #ifdef DEBUG_TASMOTA_SENSOR - dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); - DEBUG_SENSOR_LOG("Ina219SetCalibration: shunt=%dmO => cur_mul=%s",shunt_milliOhms,__ina219_dbg1); - #endif - } - config = INA219_CONFIG_BVOLTAGERANGE_32V - | INA219_CONFIG_GAIN_8_320MV - | INA219_CONFIG_BADCRES_12BIT_16S_8510US - | INA219_CONFIG_SADCRES_12BIT_16S_8510US - | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - - return I2cWrite16(addr, INA219_REG_CONFIG, config); -} - -float Ina219GetShuntVoltage_mV(uint16_t addr) -{ - - int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - DEBUG_SENSOR_LOG("Ina219GetShuntVoltage_mV: ShReg = 0x%04X",value); - - return value * 0.01; -} - -float Ina219GetBusVoltage_V(uint16_t addr) -{ - - uint16_t value = I2cRead16(addr, INA219_REG_BUSVOLTAGE) >> 3; - DEBUG_SENSOR_LOG("Ina219GetBusVoltage_V: BusReg = 0x%04X",value); - - return value * 0.004; -} -# 201 "/workspace/Tasmota/tasmota/xsns_13_ina219.ino" -bool Ina219Read(void) -{ - for (int i=0; i= 0) && (XdrvMailbox.payload <= 255)) { - Settings.ina219_mode = XdrvMailbox.payload; - restart_flag = 2; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); - - return true; -} - - - -void Ina219Detect(void) -{ - for (uint32_t i = 0; i < sizeof(ina219_type); i++) { - uint16_t addr = ina219_addresses[i]; - if (I2cActive(addr)) { continue; } - if (Ina219SetCalibration(Settings.ina219_mode, addr)) { - I2cSetActiveFound(addr, ina219_types); - ina219_type[i] = 1; - ina219_count++; - } - } -} - -void Ina219EverySecond(void) -{ - - Ina219Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA219_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 Ina219Show(bool json) -{ - int num_found=0; - 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) -{ - if (!I2cEnabled(XI2C_14)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ina219Detect(); - } - else if (ina219_count) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_13 == XdrvMailbox.index) { - result = Ina219CommandSensor(); - } - 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 "/workspace/Tasmota/tasmota/xsns_14_sht3x.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_14_sht3x.ino" -#ifdef USE_I2C -#ifdef USE_SHT3X - - - - - - -#define XSNS_14 14 -#define XI2C_15 15 - -#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) -{ - for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { - if (I2cActive(sht3x_addresses[i])) { continue; } - float t; - float h; - 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); - I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); - sht3x_count++; - } - } -} - -void Sht3xShow(bool json) -{ - for (uint32_t i = 0; i < sht3x_count; i++) { - float t; - float h; - if (Sht3xRead(t, h, sht3x_sensors[i].address)) { - char types[11]; - snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, t, h); - } - } -} - - - - - -bool Xsns14(uint8_t function) -{ - if (!I2cEnabled(XI2C_15)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Sht3xDetect(); - } - else if (sht3x_count) { - switch (function) { - case FUNC_JSON_APPEND: - Sht3xShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sht3xShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_15_mhz19.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_15_mhz19.ino" -#ifdef USE_MHZ19 -# 33 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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; -#ifdef USE_LIGHT - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); -#endif - - 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); - } - } - } - - } - } - - } -} -# 268 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_MHZ_RXD) && PinUsed(GPIO_MHZ_TXD)) { - 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 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" -#ifdef USE_I2C -#ifdef USE_TSL2561 -# 30 "/workspace/Tasmota/tasmota/xsns_16_tsl2561.ino" -#define XSNS_16 16 -#define XI2C_16 16 - -#include - -Tsl2561 Tsl(Wire); - -uint8_t tsl2561_type = 0; -uint8_t tsl2561_valid = 0; -uint32_t tsl2561_milliLux = 0; -uint32_t tsl2561_full = 0; -uint32_t tsl2561_ir = 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; - - if (Tsl.on()) { - if (Tsl.id(id) - && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) - && Tsl2561Util::normalizedLuminosity(gain, exposure, tsl2561_full = scaledFull, tsl2561_ir = scaledIr)) { - if (! Tsl2561Util::milliLux(tsl2561_full, tsl2561_ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { - tsl2561_milliLux = 0; - } - } else{ - tsl2561_milliLux = 0; - tsl2561_full = 0; - tsl2561_ir = 0; - } - } - tsl2561_valid = SENSOR_MAX_MISS; - return true; -} - -void Tsl2561Detect(void) -{ - if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { - uint8_t id; - Tsl.begin(); - if (!Tsl.id(id)) return; - if (Tsl.on()) { - tsl2561_type = 1; - I2cSetActiveFound(Tsl.address(), tsl2561_types); - } - } -} - -void Tsl2561EverySecond(void) -{ - if (!(uptime %2)) { - - if (!Tsl2561Read()) { - AddLogMissed(tsl2561_types, tsl2561_valid); - } - } -} - -#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,\"IR\":%u,\"Broadband\":%u}"), - tsl2561_milliLux / 1000, tsl2561_milliLux % 1000, tsl2561_ir, tsl2561_full); -#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) -{ - if (!I2cEnabled(XI2C_16)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2561Detect(); - } - else if (tsl2561_type) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_17_senseair.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_17_senseair.ino" -#ifdef USE_SENSEAIR -# 29 "/workspace/Tasmota/tasmota/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; -#ifdef USE_LIGHT - LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); -#endif - 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 (PinUsed(GPIO_SAIR_RX) && PinUsed(GPIO_SAIR_TX)) { - 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) -{ - 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(",")); - ResponseAppendTHD(senseair_temperature, senseair_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_THD(senseair_types, senseair_temperature, senseair_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 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" -#ifdef USE_PMS5003 -# 31 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" -#define XSNS_18 18 - -#include - -#ifndef WARMUP_PERIOD -#define WARMUP_PERIOD 30 -#endif - -#ifndef MIN_INTERVAL_PERIOD -#define MIN_INTERVAL_PERIOD 60 -#endif - -TasmotaSerial *PmsSerial; - -struct PMS5003 { - uint16_t time = 0; - uint8_t type = 1; - uint8_t valid = 0; - uint8_t wake_mode = 1; - uint8_t ready = 1; -} Pms; - -enum PmsCommands -{ - CMD_MODE_ACTIVE, - CMD_SLEEP, - CMD_WAKEUP, - CMD_MODE_PASSIVE, - CMD_READ_DATA -}; - -const uint8_t kPmsCommands[][7] PROGMEM = { - - {0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71}, - {0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73}, - {0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74}, - {0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70}, - {0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71}}; - -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 - uint16_t checksum; -} pms_data; - - - -size_t PmsSendCmd(uint8_t command_id) -{ - return PmsSerial->write(kPmsCommands[command_id], sizeof(kPmsCommands[command_id])); -} - - - -bool PmsReadData(void) -{ - if (! PmsSerial->available()) { - return false; - } - while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { - PmsSerial->read(); - } -#ifdef PMS_MODEL_PMS3003 - if (PmsSerial->available() < 22) { -#else - if (PmsSerial->available() < 32) { -#endif - return false; - } - -#ifdef PMS_MODEL_PMS3003 - uint8_t buffer[22]; - PmsSerial->readBytes(buffer, 22); -#else - uint8_t buffer[32]; - PmsSerial->readBytes(buffer, 32); -#endif - uint16_t sum = 0; - PmsSerial->flush(); - -#ifdef PMS_MODEL_PMS3003 - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); -#else - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); -#endif - - -#ifdef PMS_MODEL_PMS3003 - for (uint32_t i = 0; i < 20; i++) { -#else - for (uint32_t i = 0; i < 30; i++) { -#endif - sum += buffer[i]; - } - -#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 - 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 - 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.valid = 10; - - return true; -} -# 172 "/workspace/Tasmota/tasmota/xsns_18_pms5003.ino" -bool PmsCommandSensor(void) -{ - if (PinUsed(GPIO_PMS5003_TX) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - if (XdrvMailbox.payload < MIN_INTERVAL_PERIOD) { - - Settings.pms_wake_interval = 0; - Pms.wake_mode = 1; - Pms.ready = 1; - PmsSendCmd(CMD_MODE_ACTIVE); - PmsSendCmd(CMD_WAKEUP); - } else { - - Settings.pms_wake_interval = XdrvMailbox.payload; - PmsSendCmd(CMD_MODE_PASSIVE); - PmsSendCmd(CMD_SLEEP); - Pms.wake_mode = 0; - Pms.ready = 0; - } - } - - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_18, Settings.pms_wake_interval); - - return true; -} - - - -void PmsSecond(void) -{ - if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { - - Pms.time++; - if ((Settings.pms_wake_interval - Pms.time <= WARMUP_PERIOD) && !Pms.wake_mode) { - - Pms.wake_mode = 1; - PmsSendCmd(CMD_WAKEUP); - } - if (Pms.time >= Settings.pms_wake_interval) { - - PmsSendCmd(CMD_READ_DATA); - Pms.ready = 1; - Pms.time = 0; - } - } - - if (Pms.ready) { - if (PmsReadData()) { - Pms.valid = 10; - if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { - PmsSendCmd(CMD_SLEEP); - Pms.wake_mode = 0; - Pms.ready = 0; - } - } else { - if (Pms.valid) { - Pms.valid--; - if (Settings.pms_wake_interval >= MIN_INTERVAL_PERIOD) { - PmsSendCmd(CMD_READ_DATA); - Pms.ready = 1; - } - } - } - } -} - - - -void PmsInit(void) -{ - Pms.type = 0; - if (PinUsed(GPIO_PMS5003_RX)) { - PmsSerial = new TasmotaSerial(Pin(GPIO_PMS5003_RX), (PinUsed(GPIO_PMS5003_TX)) ? Pin(GPIO_PMS5003_TX) : -1, 1); - if (PmsSerial->begin(9600)) { - if (PmsSerial->hardwareSerial()) { ClaimSerial(); } - - if (!PinUsed(GPIO_PMS5003_TX)) { - Settings.pms_wake_interval = 0; - Pms.ready = 1; - } - - Pms.type = 1; - } - } -} - -#ifdef USE_WEBSERVER -#ifdef PMS_MODEL_PMS3003 -const char HTTP_PMS3003_SNS[] PROGMEM = - - - - "{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_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 -#endif - -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 -#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 { - -#ifdef PMS_MODEL_PMS3003 - WSContentSend_PD(HTTP_PMS3003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); -#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 -#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_COMMAND_SENSOR: - if (XSNS_18 == XdrvMailbox.index) { - result = PmsCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - PmsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - PmsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_19_mgs.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_19_mgs.ino" -#ifdef USE_I2C -#ifdef USE_MGS - - - - - - - -#define XSNS_19 19 -#define XI2C_17 17 - -#ifndef MGS_SENSOR_ADDR -#define MGS_SENSOR_ADDR 0x04 -#endif - -#include "MutichannelGasSensor.h" - -bool mgs_detected = false; - -void MGSInit(void) { - gas.begin(MGS_SENSOR_ADDR); -} - -void MGSPrepare(void) -{ - if (I2cActive(MGS_SENSOR_ADDR)) { return; } - - gas.begin(MGS_SENSOR_ADDR); - if (!gas.isError()) { - I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); - mgs_detected = true; - } -} - -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) -{ - if (!I2cEnabled(XI2C_17)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MGSPrepare(); - } - else if (mgs_detected) { - switch (function) { - case FUNC_JSON_APPEND: - MGSShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGSShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" -#ifdef USE_NOVA_SDS -# 30 "/workspace/Tasmota/tasmota/xsns_20_novasds.ino" -#define XSNS_20 20 - -#include - -#ifndef STARTING_OFFSET -#define STARTING_OFFSET 30 -#endif -#if STARTING_OFFSET < 10 -#error "Please set STARTING_OFFSET >= 10" -#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; -uint8_t cont_mode = 1; - -struct sds011data { - uint16_t pm100; - uint16_t pm25; -} novasds_data; -uint16_t pm100_sum; -uint16_t pm25_sum; - - -#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_SLEEP 0 - #define NOVA_SDS_WORK 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, 0, 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 (!novasds_valid) - { - NovaSdsSetWorkPeriod(); - novasds_valid=1; - } - if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) - { - if(!cont_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 - Settings.novasds_startingoffset && !cont_mode) - { - 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) - { - if(!(NovaSdsReadData())) novasds_valid=0; - pm100_sum += novasds_data.pm100; - pm25_sum += novasds_data.pm25; - } - if(tele_period == Settings.tele_period-1) - { - 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); - pm100_sum = pm25_sum = 0; - } -} - - - - - - - -bool NovaSdsCommandSensor(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { - 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_startingoffset); - - return true; -} - -void NovaSdsInit(void) -{ - novasds_type = 0; - if (PinUsed(GPIO_SDS0X1_RX) && PinUsed(GPIO_SDS0X1_TX)) { - 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 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" -#ifdef USE_I2C -#ifdef USE_SGP30 -# 30 "/workspace/Tasmota/tasmota/xsns_21_sgp30.ino" -#define XSNS_21 21 -#define XI2C_18 18 - -#define SGP30_ADDRESS 0x58 - -#include "Adafruit_SGP30.h" -Adafruit_SGP30 sgp; - -bool sgp30_type = false; -bool sgp30_ready = false; -float sgp30_abshum; - - - -void sgp30_Init(void) -{ - if (I2cActive(SGP30_ADDRESS)) { return; } - - if (sgp.begin()) { - sgp30_type = true; - - I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); - } -} - - -#define POW_FUNC FastPrecisePow - -float sgp30_AbsoluteHumidity(float temperature, float humidity) { - - - - - - float temp = NAN; - const float mw = 18.01534; - const float r = 8.31447215; - - if (isnan(temperature) || isnan(humidity) ) { - return NAN; - } - - 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 = false; - if (!sgp.IAQmeasure()) { - return; - } - if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { - - sgp30_abshum = sgp30_AbsoluteHumidity(global_temperature_celsius, global_humidity); - sgp.setHumidity(sgp30_abshum*1000); - } - sgp30_ready = true; - - - 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 (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { - - dtostrfd(sgp30_abshum,4,abs_hum); - } - if (json) { - ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); - if (global_update && global_humidity>0 && !isnan(global_temperature_celsius)) { - 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) -{ - if (!I2cEnabled(XI2C_18)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - sgp30_Init(); - } - else if (sgp30_type) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" -#ifdef USE_SR04 - -#include -#include -# 32 "/workspace/Tasmota/tasmota/xsns_22_sr04.ino" -#define XSNS_22 22 - -uint8_t sr04_type = 1; -real64_t distance; - -NewPing* sonar = nullptr; -TasmotaSerial* sonar_serial = nullptr; - -uint8_t Sr04TModeDetect(void) -{ - sr04_type = 0; - if (!PinUsed(GPIO_SR04_ECHO)) { return sr04_type; } - - int sr04_echo_pin = Pin(GPIO_SR04_ECHO); - int sr04_trig_pin = (PinUsed(GPIO_SR04_TRIG)) ? Pin(GPIO_SR04_TRIG) : Pin(GPIO_SR04_ECHO); - sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); - - if (sonar_serial->begin(9600,1)) { - DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); - - if (sr04_trig_pin != -1) { - sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != NO_ECHO) ? 3 : 1; - } else { - sr04_type = 2; - } - } else { - sr04_type = 1; - } - - if (sr04_type < 2) { - delete sonar_serial; - sonar_serial = nullptr; - if (-1 == sr04_trig_pin) { - sr04_trig_pin = Pin(GPIO_SR04_ECHO); - } - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); - } else { - if (sonar_serial->hardwareSerial()) { - ClaimSerial(); - } - } - - AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); - return sr04_type; -} - -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) -{ - uint16_t ret = first; - if (first > second) { - first = second; - second = ret; - } - - if (third < first) { - return first; - } else if (third > second) { - return second; - } else { - return third; - } -} - -uint16_t Sr04TMode3Distance() { - - sonar_serial->write(0x55); - sonar_serial->flush(); - - return Sr04TMode2Distance(); -} - -uint16_t Sr04TMode2Distance(void) -{ - sonar_serial->setTimeout(300); - const char startByte = 0xff; - - if (!sonar_serial->find(startByte)) { - - return NO_ECHO; - } - - delay(5); - - uint8_t crc = sonar_serial->read(); - - uint16_t distance = ((uint16_t)crc) << 8; - - - distance += sonar_serial->read(); - crc += distance & 0x00ff; - crc += 0x00FF; - - - if (crc != sonar_serial->read()) { - AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); - return NO_ECHO; - } - - return distance; -} - -void Sr04TReading(void) { - - if (sonar_serial==nullptr && sonar==nullptr) { - Sr04TModeDetect(); - } - - switch (sr04_type) { - case 3: - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; - break; - case 2: - - while(sonar_serial->available()) sonar_serial->read(); - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; - break; - case 1: - distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; - break; - default: - distance = NO_ECHO; - } - - return; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_DISTANCE[] PROGMEM = - "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; -#endif - -void Sr04Show(bool json) -{ - - 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 (sr04_type) { - switch (function) { - case FUNC_INIT: - result = (PinUsed(GPIO_SR04_ECHO)); - break; - case FUNC_EVERY_SECOND: - Sr04TReading(); - result = true; - break; - case FUNC_JSON_APPEND: - Sr04Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sr04Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" -#ifdef USE_I2C -#ifdef USE_SI1145 -# 30 "/workspace/Tasmota/tasmota/xsns_24_si1145.ino" -#define XSNS_24 24 -#define XI2C_19 19 - -#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 - -uint16_t si1145_visible; -uint16_t si1145_infrared; -uint16_t si1145_uvindex; - -bool si1145_type = false; -uint8_t si1145_valid = 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); -} - - - -bool Si1145Read(void) -{ - if (si1145_valid) { si1145_valid--; } - - if (!Si1145Present()) { return false; } - - si1145_visible = Si1145ReadVisible(); - si1145_infrared = Si1145ReadIR(); - si1145_uvindex = Si1145ReadUV(); - si1145_valid = SENSOR_MAX_MISS; - return true; -} - -void Si1145Detect(void) -{ - if (I2cActive(SI114X_ADDR)) { return; } - - if (Si1145Begin()) { - si1145_type = true; - I2cSetActiveFound(SI114X_ADDR, "SI1145"); - } -} - -void Si1145Update(void) -{ - if (!Si1145Read()) { - AddLogMissed("SI1145", si1145_valid); - } -} - -#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_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#endif - } - } -} - - - - - -bool Xsns24(uint8_t function) -{ - if (!I2cEnabled(XI2C_19)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Si1145Detect(); - } - else if (si1145_type) { - 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 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" -#ifdef USE_I2C -#ifdef USE_LM75AD -# 31 "/workspace/Tasmota/tasmota/xsns_26_lm75ad.ino" -#define XSNS_26 26 -#define XI2C_20 20 - -#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 - -bool lm75ad_type = false; -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) -{ - for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { - lm75ad_address = lm75ad_addresses[i]; - if (I2cActive(lm75ad_address)) { - continue; } - if (!I2cSetDevice(lm75ad_address)) { - break; - } - uint16_t buffer; - if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { - if (buffer == 0x4B00) { - lm75ad_type = true; - I2cSetActiveFound(lm75ad_address, "LM75AD"); - 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) -{ - float t = LM75ADGetTemp(); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, "LM75AD", 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) -{ - if (!I2cEnabled(XI2C_20)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - LM75ADDetect(); - } - else if (lm75ad_type) { - switch (function) { - case FUNC_JSON_APPEND: - LM75ADShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - LM75ADShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -# 28 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -#ifdef USE_I2C -#ifdef USE_APDS9960 -# 52 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -#define XSNS_27 27 -#define XI2C_21 21 - - -#define APDS9960_I2C_ADDR 0x39 - -#define APDS9960_CHIPID_1 0xAB -#define APDS9960_CHIPID_2 0x9C -#define APDS9960_CHIPID_3 0xA8 - -#define APDS9930_CHIPID_1 0x12 -#define APDS9930_CHIPID_2 0x39 - -#define APDS9960_MODE_GESTURE 0 -#define APDS9960_MODE_COLOR 1 - - -#define GESTURE_THRESHOLD_OUT 10 -#define GESTURE_SENSITIVITY_1 50 -#define GESTURE_SENSITIVITY_2 20 - -#define APDS9960_LONG_RECOVERY 50 -#define APDS9960_MAX_GESTURE_CYCLES 50 - - - - - -const char APDS9960_TAG[] PROGMEM = "APDS9960"; - -#ifdef USE_WEBSERVER - -#ifdef USE_APDS9960_GESTURE -const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}"; -#endif - -#ifdef USE_APDS9960_COLOR -const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}"; -const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}"; -const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}"; -const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}"; -#endif - -#ifdef USE_APDS9960_PROXIMITY -const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; -#endif - -#endif -# 108 "/workspace/Tasmota/tasmota/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 APDS9960_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 APDS9960_ERROR 0xFF - -#ifdef USE_APDS9960_GESTURE - - -const char GESTURE_UP[] PROGMEM = "Up"; -const char GESTURE_DOWN[] PROGMEM = "Down"; -const char GESTURE_LEFT[] PROGMEM = "Left"; -const char GESTURE_RIGHT[] PROGMEM = "Right"; -const char GESTURE_LONG[] PROGMEM = "Long"; -const char GESTURE_NONE[] PROGMEM = "None"; - -enum { - DIR_NONE, - DIR_LEFT, - DIR_RIGHT, - DIR_UP, - DIR_DOWN, - DIR_NEAR, - DIR_FAR, - DIR_ALL -}; -# 291 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -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_t; - -typedef struct gesture_type { - int16_t ud_delta_ = 0; - int16_t lr_delta_ = 0; - int16_t ud_count_ = 0; - int16_t lr_count_ = 0; - int16_t state_ = 0; - int16_t motion_ = DIR_NONE; -} gesture_t; - -#endif - -#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) -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_t; -#endif - - - - - -#ifdef USE_APDS9960_GESTURE -gesture_data_t gesture_data; -gesture_t gesture; -char currentGesture[6]; -#endif - -#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) -color_data_t color_data; -#endif - -volatile uint8_t recovery_loop_counter = 0; -bool APDS9960_overload = false; -uint8_t APDS9960_aTime = DEFAULT_ATIME; -uint8_t APDS9960_type = 0; -uint8_t gesture_mode = 1; - - - - - -#ifdef USE_APDS9960_COLOR - - - - - -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; -} -#endif -# 393 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getProxIntLowThresh(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); - - return val; -} - - - - - - -inline 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; -} - - - - - - -inline void setProxIntHighThresh(uint8_t threshold) { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); -} -# 445 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getLEDDrive(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - val = (val >> 6) & 0b00000011; - - return val; -} -# 468 "/workspace/Tasmota/tasmota/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); -} -# 495 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getProximityGain(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - val = (val >> 2) & 0b00000011; - - return val; -} -# 518 "/workspace/Tasmota/tasmota/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); -} -# 545 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getAmbientLightGain() { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - val &= 0b00000011; - - return val; -} -# 568 "/workspace/Tasmota/tasmota/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); -} -# 594 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getLEDBoost(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2); - - - val = (val >> 4) & 0b00000011; - - return val; -} -# 617 "/workspace/Tasmota/tasmota/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); -} -# 683 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getProxPhotoMask(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); - - - val &= 0b00001111; - - return val; -} -# 707 "/workspace/Tasmota/tasmota/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); -} - -#ifdef USE_APDS9960_GESTURE - - - - - - -uint8_t getGestureEnterThresh(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH); - - return val; -} - - - - - - -inline 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; -} - - - - - - -inline void setGestureExitThresh(uint8_t threshold) { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold); -} -# 781 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getGestureGain(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); - - - val = (val >> 5) & 0b00000011; - - return val; -} -# 804 "/workspace/Tasmota/tasmota/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); -} -# 831 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getGestureLEDDrive(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); - - - val = (val >> 3) & 0b00000011; - - return val; -} -# 854 "/workspace/Tasmota/tasmota/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); -} -# 885 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getGestureWaitTime(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); - - - val &= 0b00000111; - - return val; -} -# 912 "/workspace/Tasmota/tasmota/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); -} - -#endif - - - - - - -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); -} - - - - - - -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) { - setMode(ALL, OFF); - - - 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); - - -#ifdef USE_APDS9960_GESTURE - 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); -#endif - - disablePower(); - - return true; -} -# 1278 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -inline 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 <= 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(OFF); - enablePower(); - setMode(AMBIENT_LIGHT, ON); -} - - - - - -void disableLightSensor(void) { - setAmbientLightIntEnable(OFF); - setMode(AMBIENT_LIGHT, OFF); -} - - - - - - -void enableProximitySensor(void) { - - setProximityGain(DEFAULT_PGAIN); - setLEDDrive(DEFAULT_LDRIVE); - setProximityIntEnable(OFF); - enablePower(); - setMode(PROXIMITY, ON); -} - - - - - -void disableProximitySensor(void) { - setProximityIntEnable(OFF); - setMode(PROXIMITY, OFF); -} - -#ifdef USE_APDS9960_GESTURE - - - - - -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(OFF); - setGestureMode(ON); - enablePower(); - setMode(WAIT, ON); - setMode(PROXIMITY, ON); - setMode(GESTURE, ON); -} - - - - - -void disableGestureSensor(void) { - resetGestureParameters(); - setGestureIntEnable(OFF); - setGestureMode(OFF); - setMode(GESTURE, OFF); -} - - - - - - -bool isGestureAvailable(void) { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); - - - val &= APDS9960_GVALID; - - - return (val == 1); -} - - - - - - -int16_t readGesture(void) { - uint8_t fifo_level = 0; - uint8_t fifo_data[128]; - uint8_t gstatus; - int16_t motion; - uint16_t i; - uint8_t gesture_loop_counter = 0; - int8_t bytes_read = 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); - -#ifdef USE_DEBUG_DRIVER - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: FIFO Level : %d"), fifo_level); -#endif - - - if (fifo_level > 0) { - bytes_read = (fifo_level * 4); - - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_GFIFO_U, (uint8_t*)fifo_data, bytes_read)) { - return APDS9960_ERROR; - } - -#ifdef USE_DEBUG_DRIVER - char output[(bytes_read * 2) + 1]; - char *ptr = &output[0]; - - for ( i = 0; i < bytes_read; i++ ) { - ptr += sprintf(ptr, "%02X", fifo_data[i]); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: FIFO Dump : %s"), output); -#endif - - - 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; - } - } -} - -#endif - - - - - -inline void enablePower(void) { - setMode(POWER, ON); -} - - - - - -inline void disablePower(void) { - setMode(POWER, OFF); -} - - - - - - -#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) - - - -inline void readAllColorAndProximityData(void) { - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) { - - - } -} - -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); -} -#endif - - - - - -#ifdef USE_APDS9960_GESTURE - - - - -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, GESTURE_UP); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_UP); - break; - case DIR_DOWN: - AddLog_P(LOG_LEVEL_DEBUG, GESTURE_DOWN); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_DOWN); - break; - case DIR_LEFT: - AddLog_P(LOG_LEVEL_DEBUG, GESTURE_LEFT); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_LEFT); - break; - case DIR_RIGHT: - AddLog_P(LOG_LEVEL_DEBUG, GESTURE_RIGHT); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_RIGHT); - break; - default: - if (APDS9960_overload) { - AddLog_P(LOG_LEVEL_DEBUG, GESTURE_LONG); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_LONG); - } else { - AddLog_P(LOG_LEVEL_DEBUG, GESTURE_NONE); - snprintf_P(currentGesture, sizeof(currentGesture), GESTURE_NONE); - } - break; - } - MqttPublishSensor(); - } - currentGesture[0] = '\0'; -} - -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; - } - } - } -} - -#endif - -void APDS9960_detect(void) { - if (APDS9960_type || I2cActive(APDS9960_I2C_ADDR)) { return; } - - APDS9960_type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); - -#ifdef USE_DEBUG_DRIVER - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: %s Chip %X"), APDS9960_TAG, APDS9960_type); -#endif - - if (APDS9960_type == APDS9960_CHIPID_1 || APDS9960_type == APDS9960_CHIPID_2 || APDS9960_type == APDS9960_CHIPID_3) { - if (APDS9960_init()) { - I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960_TAG); - - enableProximitySensor(); - -#if defined(USE_APDS9960_GESTURE) && USE_APDS9960_STARTMODE == APDS9960_MODE_GESTURE - gesture_mode = 1; - enableGestureSensor(); -#endif - -#if ( defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) ) && USE_APDS9960_STARTMODE == APDS9960_MODE_COLOR - gesture_mode = 0; - enableLightSensor(); - APDS9960_overload = false; -#endif - } else { - APDS9960_type = 0; - } - } else { - APDS9960_type = 0; - } - -#ifdef USE_APDS9960_GESTURE - currentGesture[0] = '\0'; -#endif -} - - - - - -void APDS9960_show(bool json) { - if (!APDS9960_type) { return; } - - if (!gesture_mode && !APDS9960_overload) { - -#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY) - uint16_t ambient; - - readAllColorAndProximityData(); - ambient = color_data.a/4; - - - - - -#ifdef USE_APDS9960_COLOR - calculateColorTemperature(); -#endif - if (json) { -#if defined(USE_APDS9960_COLOR) && defined(USE_APDS9960_PROXIMITY) - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u,\"Proximity\":%u}"), - APDS9960_TAG, - color_data.r, - color_data.g, - color_data.b, - ambient, - color_data.cct, - color_data.p); -#else - -#ifdef USE_APDS9960_COLOR - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u}"), - APDS9960_TAG, - color_data.r, - color_data.g, - color_data.b, - ambient, - color_data.cct); -#endif - -#ifdef USE_APDS9960_PROXIMITY - ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), - APDS9960_TAG, - color_data.p); -#endif - -#endif -#ifdef USE_WEBSERVER - } else { - -#ifdef USE_APDS9960_COLOR - WSContentSend_PD(HTTP_SNS_COLOR_RED, APDS9960_TAG, color_data.r); - WSContentSend_PD(HTTP_SNS_COLOR_GREEN, APDS9960_TAG, color_data.g); - WSContentSend_PD(HTTP_SNS_COLOR_BLUE, APDS9960_TAG, color_data.b); - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, APDS9960_TAG, ambient); - WSContentSend_PD(HTTP_SNS_CCT, APDS9960_TAG, color_data.cct); -#endif - -#ifdef USE_APDS9960_PROXIMITY - WSContentSend_PD(HTTP_SNS_PROXIMITY, APDS9960_TAG, color_data.p); -#endif - -#endif - } -#endif - -#ifdef USE_APDS9960_GESTURE - } else { - if (currentGesture[0] != '\0') { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960_TAG, currentGesture); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_GESTURE, APDS9960_TAG, currentGesture); -#endif - currentGesture[0] = '\0'; - } - } -#endif - - } -} -# 1947 "/workspace/Tasmota/tasmota/xsns_27_apds9960.ino" -bool APDS9960CommandSensor(void) { - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: -#ifdef USE_APDS9960_GESTURE - disableGestureSensor(); -#endif - gesture_mode = 0; - enableLightSensor(); - APDS9960_overload = false; - break; -#ifdef USE_APDS9960_GESTURE - case 1: - if (APDS9960_type) { - setGestureGain(DEFAULT_GGAIN); - setProximityGain(DEFAULT_PGAIN); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - case 2: - if (APDS9960_type) { - setGestureGain(GGAIN_2X); - setProximityGain(PGAIN_2X); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; -#endif - 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) { - if (!I2cEnabled(XI2C_21)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - APDS9960_detect(); - } else if (APDS9960_type) { - switch (function) { -#ifdef USE_APDS9960_GESTURE - case FUNC_EVERY_50_MSECOND: - APDS9960_loop(); - break; -#endif - 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 "/workspace/Tasmota/tasmota/xsns_28_tm1638.ino" -# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB)) { - 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 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/xsns_28_tm1638.ino" - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#ifdef USE_I2C -#ifdef USE_MCP230xx -# 31 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#define XSNS_29 29 -#define XI2C_22 22 - - - - - -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_oldoutpincount = 0; -#ifdef USE_MCP230xx_OUTPUT -uint8_t mcp230xx_outpinmapping[16]; -#endif -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 < mcp230xx_type; mcp230xx_port++) { - uint8_t reg_gppu = 0; - uint8_t reg_gpinten = 0; - uint8_t reg_iodir = 0xFF; -#ifdef USE_MCP230xx_OUTPUT - uint8_t reg_portpins = 0x00; -#endif - for (uint32_t idx = 0; idx < 8; idx++) { - switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { - case 0 ... 1: - reg_iodir |= (1 << idx); - break; - case 2 ... 4: - reg_iodir |= (1 << idx); - reg_gpinten |= (1 << idx); - int_en = 1; - break; -#ifdef USE_MCP230xx_OUTPUT - case 5 ... 6: - reg_iodir &= ~(1 << idx); - if (Settings.flag.save_state) { - reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); - } else { - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_portpins |= (1 << idx); - } - } - break; -#endif - default: - break; - } -#ifdef USE_MCP230xx_OUTPUT - if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { - reg_gppu |= (1 << idx); - } -#else - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_gppu |= (1 << idx); - } -#endif - } - 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(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif - } - devices_present -= mcp230xx_oldoutpincount; - mcp230xx_oldoutpincount = 0; - for (uint32_t idx=0;idx= 5) { - mcp230xx_outpinmapping[mcp230xx_oldoutpincount] = idx; - mcp230xx_oldoutpincount++; - } - int_millis[idx]=millis(); - } - devices_present += mcp230xx_oldoutpincount; - mcp230xx_int_en = int_en; - MCP230xx_CheckForIntCounter(); - MCP230xx_CheckForIntRetainer(); -} - -void MCP230xx_Detect(void) -{ - if (I2cActive(USE_MCP230xx_ADDR)) { return; } - - uint8_t buffer; - - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IOCON, 0x80); - if (I2cValidRead8(&buffer, USE_MCP230xx_ADDR, MCP230xx_IOCON)) { - if (0x00 == buffer) { - mcp230xx_type = 1; - I2cSetActiveFound(USE_MCP230xx_ADDR, "MCP23008"); - mcp230xx_pincount = 8; - MCP230xx_ApplySettings(); - } else { - if (0x80 == buffer) { - mcp230xx_type = 2; - I2cSetActiveFound(USE_MCP230xx_ADDR, "MCP23017"); - mcp230xx_pincount = 16; - - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IOCON, 0x00); - - MCP230xx_GPINTEN = 0x04; - MCP230xx_GPPU = 0x0C; - MCP230xx_INTF = 0x0E; - MCP230xx_INTCAP = 0x10; - MCP230xx_GPIO = 0x12; - MCP230xx_ApplySettings(); - } - } - } -} - -void MCP230xx_CheckForInterrupt(void) { - uint8_t intf; - uint8_t mcp230xx_intcap = 0; - uint8_t report_int; - for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { - if (I2cValidRead8(&intf,USE_MCP230xx_ADDR,MCP230xx_INTF+mcp230xx_port)) { - if (intf > 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 (Settings.flag3.hass_tele_on_power) { - MqttPublishSensor(); - } - } - 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 (json) { - 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); - uint8_t gpiob = 0; - if (2 == mcp230xx_type) { - gpiob = MCP230xx_readGPIO(1); - ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - (gpiob>>0)&1, (gpiob>>1)&1, (gpiob>>2)&1, (gpiob>>3)&1, (gpiob>>4)&1, (gpiob>>5)&1, (gpiob>>6)&1, (gpiob>>7)&1); - } - -#ifdef USE_MCP230xx_OUTPUT - uint8_t outputcount = 0; - for (uint32_t pinx = 0; pinx < mcp230xx_pincount; pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) { outputcount++; } - } - if (outputcount) { - uint16_t gpiototal = ((uint16_t)gpiob << 8) | gpio; - ResponseAppend_P(PSTR(",\"MCP230_OUT\":{")); - char stt[7]; - 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}")); - } -#endif - 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 (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; - uint8_t relay_no = 0; - for (relay_no = 0; relay_no < mcp230xx_pincount ; relay_no ++) { - if ( mcp230xx_outpinmapping[relay_no] == pin) break; - } - relay_no = devices_present - mcp230xx_oldoutpincount + relay_no +1; - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { - ExecuteCommandPower(relay_no, 1, SRC_IGNORE); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { - ExecuteCommandPower(relay_no, 0, SRC_IGNORE); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { - ExecuteCommandPower(relay_no, 2, SRC_IGNORE); - 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) && (paramcount > 2)) { -#else - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 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 -# 771 "/workspace/Tasmota/tasmota/xsns_29_mcp230xx.ino" -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}}")); - MqttPublishTeleSensor(); - 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); - MqttPublishTeleSensor(); -} - -#ifdef USE_MCP230xx_OUTPUT -void MCP230xx_SwitchRelay() { - for (uint32_t i = devices_present - mcp230xx_oldoutpincount; i < devices_present; i++) { - uint8_t pin = mcp230xx_outpinmapping[i - (devices_present - mcp230xx_oldoutpincount)]; - uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; - uint8_t relay_state = bitRead(XdrvMailbox.index, i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MCP: relay %d pin_no %d state %d"), i,pin, relay_state); - switch (relay_state) { - case 1: - MCP230xx_SetOutPin(pin,abs(pincmd-1)); - break; - case 0: - MCP230xx_SetOutPin(pin,pincmd); - break; - } - } -} -#endif - - - - - -bool Xsns29(uint8_t function) -{ - if (!I2cEnabled(XI2C_22)) { return false; } - - bool result = false; - - if (FUNC_PRE_INIT == function) { - MCP230xx_Detect(); - } - else if (mcp230xx_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (mcp230xx_int_en) { - mcp230xx_int_prio_counter++; - if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { - MCP230xx_CheckForInterrupt(); - mcp230xx_int_prio_counter=0; - } - } - break; - case FUNC_EVERY_SECOND: - 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(); - } - - - - - - } - break; -#ifdef USE_MCP230xx_OUTPUT - case FUNC_SET_POWER: - MCP230xx_SwitchRelay(); - break; -#endif - 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 - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" -# 46 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" -#ifdef USE_I2C -#ifdef USE_MPR121 - - - - - -#define XSNS_30 30 -#define XI2C_23 23 - - - - - - - -#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) -# 195 "/workspace/Tasmota/tasmota/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 }; -}; - -bool mpr21_found = false; -# 217 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" -void Mpr121Init(struct mpr121 *pS, bool initial) -{ - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - if (initial && I2cActive(pS->i2c_addr[i])) { continue; } - - - 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]) { - - - mpr21_found = true; - char device_name[16]; - snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); - I2cSetActiveFound(pS->i2c_addr[i], device_name); - - - 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")); - } -} -# 326 "/workspace/Tasmota/tasmota/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, false); - 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, false); - 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(); - } - } - } -} -# 410 "/workspace/Tasmota/tasmota/xsns_30_mpr121.ino" -bool Xsns30(uint8_t function) -{ - if (!I2cEnabled(XI2C_23)) { return false; } - - bool result = false; - - - static struct mpr121 mpr121; - - if (FUNC_INIT == function) { - - Mpr121Init(&mpr121, true); - } - else if (mpr21_found) { - - switch (function) { - - - 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 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" -#ifdef USE_I2C -#ifdef USE_CCS811 -# 30 "/workspace/Tasmota/tasmota/xsns_31_ccs811.ino" -#define XSNS_31 31 -#define XI2C_24 24 - -#define EVERYNSECONDS 5 - -#include "Adafruit_CCS811.h" - -Adafruit_CCS811 ccs; -uint8_t CCS811_ready = 0; -uint8_t CCS811_type = 0;; -uint16_t eCO2; -uint16_t TVOC; -uint8_t tcnt = 0; -uint8_t ecnt = 0; - - - -void CCS811Detect(void) -{ - if (I2cActive(CCS811_ADDRESS)) { return; } - - if (!ccs.begin(CCS811_ADDRESS)) { - CCS811_type = 1; - I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); - } -} - -void CCS811Update(void) -{ - tcnt++; - if (tcnt >= EVERYNSECONDS) { - tcnt = 0; - CCS811_ready = 0; - if (ccs.available()) { - if (!ccs.readData()){ - TVOC = ccs.getTVOC(); - eCO2 = ccs.geteCO2(); - CCS811_ready = 1; - if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { - ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature_celsius); - } - 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) -{ - if (!I2cEnabled(XI2C_24)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - CCS811Detect(); - } - else if (CCS811_type) { - 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 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" -#ifdef USE_I2C -#ifdef USE_MPU6050 -# 30 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" -#define XSNS_32 32 -#define XI2C_25 25 - -#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]; - float yawPitchRoll[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); - mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &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(); -} -# 119 "/workspace/Tasmota/tasmota/xsns_32_mpu6050.ino" -void MPU_6050Detect(void) -{ - for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) - { - MPU_6050_address = MPU_6050_addresses[i]; - if (!I2cSetDevice(MPU_6050_address)) { break; } - 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) { - I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); - } -} - -#define D_YAW "Yaw" -#define D_PITCH "Pitch" -#define D_ROLL "Roll" - -#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}"; -#ifdef USE_MPU6050_DMP -const char HTTP_SNS_YPR[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; -#endif -#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" -#define D_JSON_YAW "Yaw" -#define D_JSON_PITCH "Pitch" -#define D_JSON_ROLL "Roll" - -void MPU_6050Show(bool json) -{ - MPU_6050PerformReading(); - - float tempConv = ConvertTemp(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); -#ifdef USE_MPU6050_DMP - char axis_yaw[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); - char axis_pitch[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); - char axis_roll[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); -#endif - - 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); -#ifdef USE_MPU6050_DMP - char json_ypr_y[25]; - snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); - char json_ypr_p[25]; - snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); - char json_ypr_r[25]; - snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%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, - json_ypr_y, json_ypr_p, json_ypr_r); -#else - 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); -#endif -#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); -#ifdef USE_MPU6050_DMP - WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); -#endif -#endif - } -} - - - - - -bool Xsns32(uint8_t function) -{ - if (!I2cEnabled(XI2C_25)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MPU_6050Detect(); - } - else if (MPU_6050_found) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" -#ifdef USE_I2C -#ifdef USE_DS3231 -# 35 "/workspace/Tasmota/tasmota/xsns_33_ds3231.ino" -#define XSNS_33 33 -#define XI2C_26 26 - - -#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) -{ - if (I2cActive(USE_RTC_ADDR)) { return; } - - if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { - I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); - DS3231chipDetected = true; - } -} - - - - -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)); -} - -void DS3231EverySecond(void) -{ - TIME_T tmpTime; - if (!ds3231ReadStatus && 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"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } - else if (!ds3231WriteStatus && 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"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - SetDS3231Time (Rtc.utc_time); - ds3231WriteStatus = true; - } -} - - - - - -bool Xsns33(uint8_t function) -{ - if (!I2cEnabled(XI2C_26)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - DS3231Detect(); - } - else if (DS3231chipDetected) { - switch (function) { - case FUNC_EVERY_SECOND: - DS3231EverySecond(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_34_hx711.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_34_hx711.ino" -#ifdef USE_HX711 -# 35 "/workspace/Tasmota/tasmota/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" -#define D_JSON_WEIGHT_RAW "WeightRaw" -#define D_JSON_WEIGHT_DELTA "WeightDelta" - -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 raw = 0; - long last_weight = 0; - long sum_weight = 0; - long sum_raw = 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; - uint16_t weight_delta = 4; -} 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(void) -{ - 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")); } -} - -void SetWeightDelta() -{ - - if (Settings.weight_change == 0) { - Hx.weight_delta = 4; - return; - } - - - if (Settings.weight_change > 100) { - Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; - return; - } - - - Hx.weight_delta = Settings.weight_change - 1; -} -# 192 "/workspace/Tasmota/tasmota/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; - case 9: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - SetWeightDelta(); - } - 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,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), - Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, - item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); - } - - return serviced; -} - - - -long HxWeight(void) -{ - return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; -} - -void HxInit(void) -{ - Hx.type = 0; - if (PinUsed(GPIO_HX711_DAT) && PinUsed(GPIO_HX711_SCK)) { - 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); - - SetWeightDelta(); - - 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) -{ - long raw = HxRead(); - Hx.sum_raw += raw; - Hx.sum_weight += raw; - - Hx.sample_count++; - if (HX_SAMPLES == Hx.sample_count) { - long average = Hx.sum_weight / Hx.sample_count; - long raw_average = Hx.sum_raw / Hx.sample_count; - long value = average - Hx.offset; - Hx.weight = value / Hx.scale; - Hx.raw = raw_average / 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) > Hx.weight_delta) { - 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(); - MqttPublishTeleSensor(); - Hx.weight_changed = false; - } - } - } - - Hx.sum_weight = 0; - Hx.sum_raw = 0; - Hx.sample_count = 0; - } -} - -void HxSaveBeforeRestart(void) -{ - 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, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); -#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(PSTR("/" WEB_HANDLE_HX711), HandleHxAction); - break; -#endif -#endif - case FUNC_INIT: - HxInit(); - break; - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" -#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) -# 51 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" -#define XSNS_35 35 - -#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) -#undef USE_TX20_WIND_SENSOR -#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** -#endif - - -#define TX2X_BIT_TIME 1220 -#define TX2X_WEIGHT_AVG_SAMPLE 150 -#define TX2X_TIMEOUT 10 -#define TX23_READ_INTERVAL 4 - - - -extern "C" { -#include "gpio.h" -} - -#ifdef USE_TX20_WIND_SENSOR -#undef D_TX2x_NAME -#define D_TX2x_NAME "TX20" -#else -#undef D_TX2x_NAME -#define D_TX2x_NAME "TX23" -#endif - -#ifdef USE_WEBSERVER -#define D_TX20_WIND_AVG "∅" -#define D_TX20_WIND_ANGLE "∠" -#define D_TX20_WIND_DEGREE "°" -const char HTTP_SNS_TX2X[] PROGMEM = - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}" -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED " " D_TX20_WIND_AVG "{m}%s %s{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}" -#endif - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s" D_TX20_WIND_DEGREE "{e}" -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_AVG "{m}%s %s" D_TX20_WIND_DEGREE "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_ANGLE "{m}%s" D_TX20_WIND_DEGREE " (%s,%s)" D_TX20_WIND_DEGREE; -#endif - ; -#endif - - -float const tx2x_f_pi = 3.1415926535897932384626433; -float const tx2x_f_halfpi = tx2x_f_pi / 2.0; -float const tx2x_f_pi180 = tx2x_f_pi / 180.0; - -#define TX2X_DIRECTIONS_MAXSIZE 3 -const char kTx2xDirections[] 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; - -int32_t tx2x_wind_speed = 0; -int32_t tx2x_wind_direction = 0; - -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS -int32_t tx2x_wind_speed_min = 0xfff; -int32_t tx2x_wind_speed_max = 0; -float tx2x_wind_speed_avg = 0; -float tx2x_wind_direction_avg_x = 0; -float tx2x_wind_direction_avg_y = 0; -float tx2x_wind_direction_avg = 0; -int32_t tx2x_wind_direction_min = 0; -int32_t tx2x_wind_direction_max = 0; - -uint32_t tx2x_count = 0; -uint32_t tx2x_avg_samples; -uint32_t tx2x_last_uptime = 0; -bool tx2x_valuesread = false; -#endif - -#ifdef DEBUG_TASMOTA_SENSOR -uint32_t tx2x_sa = 0; -uint32_t tx2x_sb = 0; -uint32_t tx2x_sc = 0; -uint32_t tx2x_sd = 0; -uint32_t tx2x_se = 0; -uint32_t tx2x_sf = 0; -#endif -uint32_t tx2x_last_available = 0; - -#ifdef USE_TX23_WIND_SENSOR -uint32_t tx23_stage = 0; -#endif - -void ICACHE_RAM_ATTR TX2xStartRead(void) -{ -# 180 "/workspace/Tasmota/tasmota/xsns_35_tx20.ino" -#ifdef USE_TX23_WIND_SENSOR - if (0!=tx23_stage) - { - if ((2==tx23_stage) || (3==tx23_stage)) - { -#endif -#ifdef DEBUG_TASMOTA_SENSOR - tx2x_sa = 0; - tx2x_sb = 0; - tx2x_sc = 0; - tx2x_sd = 0; - tx2x_se = 0; - tx2x_sf = 0; -#else - uint32_t tx2x_sa = 0; - uint32_t tx2x_sb = 0; - uint32_t tx2x_sc = 0; - uint32_t tx2x_sd = 0; - uint32_t tx2x_se = 0; - uint32_t tx2x_sf = 0; -#endif - - delayMicroseconds(TX2X_BIT_TIME / 2); - - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint32_t dpin = (digitalRead(Pin(GPIO_TX2X_TXD_BLACK))); -#ifdef USE_TX23_WIND_SENSOR - dpin ^= 1; -#endif - if (bitcount > 41 - 5) { - - tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - - tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - - tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - - tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - - tx2x_se = tx2x_se >> 1 | (dpin << 3); - } else { - - tx2x_sf = tx2x_sf >> 1 | (dpin << 11); - } - delayMicroseconds(TX2X_BIT_TIME); - } - - uint32_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); - chk &= 0xf; - - - ; -#ifdef USE_TX23_WIND_SENSOR - if ((chk == tx2x_sd) && (0x1b==tx2x_sa) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { -#else - if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { -#endif - tx2x_last_available = uptime; - - tx2x_wind_speed = tx2x_sc; - tx2x_wind_direction = tx2x_sb; -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - if (!tx2x_valuesread) { - tx2x_wind_direction_min = tx2x_wind_direction; - tx2x_wind_direction_max = tx2x_wind_direction; - tx2x_valuesread = true; - } -#endif - } - -#ifdef USE_TX23_WIND_SENSOR - } - tx23_stage++; - } -#endif - - - - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << Pin(GPIO_TX2X_TXD_BLACK)); -} - -bool Tx2xAvailable(void) -{ - return ((uptime - tx2x_last_available) < TX2X_TIMEOUT); -} - -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS -float atan2f(float a, float b) -{ - float atan2val; - if (b > 0) { - atan2val = atanf(a/b); - } else if ((b < 0) && (a >= 0)) { - atan2val = atanf(a/b) + tx2x_f_pi; - } else if ((b < 0) && (a < 0)) { - atan2val = atanf(a/b) - tx2x_f_pi; - } else if ((b == 0) && (a > 0)) { - atan2val = tx2x_f_halfpi; - } else if ((b == 0) && (a < 0)) { - atan2val = 0 - (tx2x_f_halfpi); - } else if ((b == 0) && (a == 0)) { - atan2val = 1000; - } - return atan2val; -} - -void Tx2xCheckSampleCount(void) -{ - uint32_t tx2x_prev_avg_samples = tx2x_avg_samples; - if (Settings.tele_period) { - - tx2x_avg_samples = Settings.tele_period; - } else { - - tx2x_avg_samples = TX2X_WEIGHT_AVG_SAMPLE; - } - if (tx2x_prev_avg_samples != tx2x_avg_samples) { - tx2x_wind_speed_avg = tx2x_wind_speed; - tx2x_count = 0; - } -} - -void Tx2xResetStat(void) -{ - DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": reset statistics")); - tx2x_last_uptime = uptime; - Tx2xResetStatData(); -} - -void Tx2xResetStatData(void) -{ - tx2x_wind_speed_min = tx2x_wind_speed; - tx2x_wind_speed_max = tx2x_wind_speed; - - tx2x_wind_direction_min = tx2x_wind_direction; - tx2x_wind_direction_max = tx2x_wind_direction; -} -#endif - -void Tx2xRead(void) -{ -#ifdef USE_TX23_WIND_SENSOR - - - - - - - - if ((uptime % TX23_READ_INTERVAL)==0) { - - - tx23_stage = 0; - pinMode(Pin(GPIO_TX2X_TXD_BLACK), OUTPUT); - digitalWrite(Pin(GPIO_TX2X_TXD_BLACK), LOW); - } else if ((uptime % TX23_READ_INTERVAL)==1) { - - - tx23_stage = 1; - pinMode(Pin(GPIO_TX2X_TXD_BLACK), INPUT_PULLUP); - } -#endif - if (Tx2xAvailable()) { -#ifdef DEBUG_TASMOTA_SENSOR - DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": sa=0x%02lx sb=%ld (0x%02lx), sc=%ld (0x%03lx), sd=0x%02lx, se=%ld, sf=%ld"), tx2x_sa,tx2x_sb,tx2x_sb,tx2x_sc,tx2x_sc,tx2x_sd,tx2x_se,tx2x_sf); -#endif -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - if (tx2x_wind_speed < tx2x_wind_speed_min) { - tx2x_wind_speed_min = tx2x_wind_speed; - } - if (tx2x_wind_speed > tx2x_wind_speed_max) { - tx2x_wind_speed_max = tx2x_wind_speed; - } - - - - - if (tx2x_count <= tx2x_avg_samples) { - tx2x_count++; - } - tx2x_wind_speed_avg -= tx2x_wind_speed_avg / tx2x_count; - tx2x_wind_speed_avg += float(tx2x_wind_speed) / tx2x_count; - - tx2x_wind_direction_avg_x -= tx2x_wind_direction_avg_x / tx2x_count; - tx2x_wind_direction_avg_x += cosf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; - tx2x_wind_direction_avg_y -= tx2x_wind_direction_avg_y / tx2x_count; - tx2x_wind_direction_avg_y += sinf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; - tx2x_wind_direction_avg = atan2f(tx2x_wind_direction_avg_y, tx2x_wind_direction_avg_x) * 180.0f / tx2x_f_pi; - if (tx2x_wind_direction_avg<0.0) { - tx2x_wind_direction_avg += 360.0; - } - if (tx2x_wind_direction_avg>360.0) { - tx2x_wind_direction_avg -= 360.0; - } - - int32_t tx2x_wind_direction_avg_int = int((tx2x_wind_direction_avg/22.5)+0.5) % 16; - - - if (tx2x_wind_direction > tx2x_wind_direction_avg_int) { - - if ((tx2x_wind_direction-tx2x_wind_direction_avg_int)>8) { - - if ((tx2x_wind_direction - 16) < tx2x_wind_direction_min) { - - tx2x_wind_direction_min = tx2x_wind_direction - 16; - } - } else { - - if (tx2x_wind_direction > tx2x_wind_direction_max) { - - tx2x_wind_direction_max = tx2x_wind_direction; - } - } - } else { - - if ((tx2x_wind_direction_avg_int-tx2x_wind_direction)>8) { - - if ((tx2x_wind_direction + 16) > tx2x_wind_direction_max) { - - tx2x_wind_direction_max = tx2x_wind_direction + 16; - } - } else { - - if (tx2x_wind_direction < tx2x_wind_direction_min) { - - tx2x_wind_direction_min = tx2x_wind_direction; - } - } - } - -#ifdef DEBUG_TASMOTA_SENSOR - char diravg[FLOATSZ]; - dtostrfd(tx2x_wind_direction_avg, 1, diravg); - char cosx[FLOATSZ]; - dtostrfd(tx2x_wind_direction_avg_x, 1, cosx); - char siny[FLOATSZ]; - dtostrfd(tx2x_wind_direction_avg_y, 1, siny); - DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": dir stat - counter=%ld, actint=%ld, avgint=%ld, avg=%s (cosx=%s, siny=%s), min %d, max %d"), - (uptime-tx2x_last_uptime), - tx2x_wind_direction, - tx2x_wind_direction_avg_int, - diravg, - cosx, - siny, - tx2x_wind_direction_min, - tx2x_wind_direction_max - ); -#endif -#endif - } else { - DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": not available")); - tx2x_wind_speed = 0; - tx2x_wind_direction = 0; -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - tx2x_wind_speed_avg = 0; - tx2x_wind_direction_avg = 0; - Tx2xResetStatData(); -#endif - } - -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - Tx2xCheckSampleCount(); - if (0==Settings.tele_period && (uptime-tx2x_last_uptime)>=tx2x_avg_samples) { - Tx2xResetStat(); - } -#endif -} - -void Tx2xInit(void) -{ - if (!Settings.flag2.speed_conversion) { - Settings.flag2.speed_conversion = 2; - } -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - tx2x_valuesread = false; - Tx2xResetStat(); - Tx2xCheckSampleCount(); -#endif -#ifdef USE_TX23_WIND_SENSOR - tx23_stage = 0; - pinMode(Pin(GPIO_TX2X_TXD_BLACK), OUTPUT); - digitalWrite(Pin(GPIO_TX2X_TXD_BLACK), LOW); -#else - pinMode(Pin(GPIO_TX2X_TXD_BLACK), INPUT); -#endif - attachInterrupt(Pin(GPIO_TX2X_TXD_BLACK), TX2xStartRead, RISING); -} - -int32_t Tx2xNormalize(int32_t value) -{ - while (value>15) { - value -= 16; - } - while (value<0) { - value += 16; - } - return value; -} - -void Tx2xShow(bool json) -{ - if (!Tx2xAvailable()) { return; } - - char wind_speed_string[FLOATSZ]; - dtostrfd(ConvertSpeed(tx2x_wind_speed)/10, 1, wind_speed_string); - char wind_direction_string[FLOATSZ]; - dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_string); - char wind_direction_cardinal_string[TX2X_DIRECTIONS_MAXSIZE+1]; - GetTextIndexed(wind_direction_cardinal_string, sizeof(wind_direction_cardinal_string), tx2x_wind_direction, kTx2xDirections); -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - char wind_speed_min_string[FLOATSZ]; - dtostrfd(ConvertSpeed(tx2x_wind_speed_min)/10, 1, wind_speed_min_string); - char wind_speed_max_string[FLOATSZ]; - dtostrfd(ConvertSpeed(tx2x_wind_speed_max)/10, 1, wind_speed_max_string); - char wind_speed_avg_string[FLOATSZ]; - dtostrfd(ConvertSpeed(tx2x_wind_speed_avg)/10, 1, wind_speed_avg_string); - char wind_direction_avg_string[FLOATSZ]; - dtostrfd(tx2x_wind_direction_avg, 1, wind_direction_avg_string); - char wind_direction_avg_cardinal_string[4]; - GetTextIndexed(wind_direction_avg_cardinal_string, sizeof(wind_direction_avg_cardinal_string), int((tx2x_wind_direction_avg/22.5f)+0.5f) % 16, kTx2xDirections); - char wind_direction_range_string[FLOATSZ]; - dtostrfd(Tx2xNormalize(tx2x_wind_direction_max-tx2x_wind_direction_min)*22.5, 1, wind_direction_range_string); - char wind_direction_min_string[FLOATSZ]; - dtostrfd(Tx2xNormalize(tx2x_wind_direction_min)*22.5, 1, wind_direction_min_string); - char wind_direction_max_string[FLOATSZ]; - dtostrfd(Tx2xNormalize(tx2x_wind_direction_max)*22.5, 1, wind_direction_max_string); -#endif - - if (json) { -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS -#ifdef USE_TX2x_LEGACY_JSON - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), - wind_speed_string, - wind_speed_avg_string, - wind_speed_max_string, - wind_direction_cardinal_string, - wind_direction_string - ); -#else - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"), - wind_speed_string, - wind_speed_avg_string, - wind_speed_min_string, - wind_speed_max_string, - wind_direction_cardinal_string, - wind_direction_string, - wind_direction_avg_string, - wind_direction_avg_cardinal_string, - wind_direction_min_string, - wind_direction_max_string, - wind_direction_range_string - ); -#endif -#else -#ifdef USE_TX2x_LEGACY_JSON - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), - wind_speed_string, wind_direction_cardinal_string, wind_direction_string); -#else - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"), - wind_speed_string, wind_direction_cardinal_string, wind_direction_string); -#endif -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TX2X, - wind_speed_string, - SpeedUnit().c_str(), -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - wind_speed_avg_string, - SpeedUnit().c_str(), - wind_speed_min_string, - SpeedUnit().c_str(), - wind_speed_max_string, - SpeedUnit().c_str(), -#endif - wind_direction_cardinal_string, - wind_direction_string -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - ,wind_direction_avg_cardinal_string, - wind_direction_avg_string, - wind_direction_range_string, - wind_direction_min_string, - wind_direction_max_string -#endif - ); -#endif - } -} - - - - - -bool Xsns35(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_TX2X_TXD_BLACK)) { - switch (function) { - case FUNC_INIT: - Tx2xInit(); - break; - case FUNC_EVERY_SECOND: - Tx2xRead(); - break; -#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - case FUNC_AFTER_TELEPERIOD: - Tx2xResetStat(); - break; -#endif - case FUNC_JSON_APPEND: - Tx2xShow(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tx2xShow(false); - break; -#endif - - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" -# 22 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" -#ifdef USE_I2C -#ifdef USE_MGC3130 -# 35 "/workspace/Tasmota/tasmota/xsns_36_mgc3130.ino" -#define XSNS_36 36 -#define XI2C_27 27 - -#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** - -#define MGC3130_I2C_ADDR 0x42 - -uint8_t MGC3130_xfer = 0; -uint8_t MGC3130_reset = 0; -bool MGC3130_type = false; -char MGC3130stype[] = "MGC3130"; - -#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_handleSensorData(){ - if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ - if (MGC3130_handleTouch()){ - MGC3130_triggeredByTouch = true; - MqttPublishSensor(); - } - } - - if(MGC3130_mode == 1){ - if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ - MGC3130_handleGesture(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 2){ - if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ - MGC3130_handleAirWheel(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 3){ - if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ - MqttPublishSensor(); - } - } -} - -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(); -} - -void MGC3130_detect(void) -{ - if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } - - MGC3130_xfer = Pin(GPIO_MGC3130_XFER); - MGC3130_reset = Pin(GPIO_MGC3130_RESET); - - pinMode(MGC3130_xfer, INPUT_PULLUP); - pinMode(MGC3130_reset, OUTPUT); - digitalWrite(MGC3130_reset, LOW); - delay(10); - digitalWrite(MGC3130_reset, HIGH); - delay(50); - - if (MGC3130_receiveMessage()) { - I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); - MGC3130_currentGesture[0] = '\0'; - MGC3130_type = true; - } -} - - - - - -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 - } -} -# 557 "/workspace/Tasmota/tasmota/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) -{ - if (!I2cEnabled(XI2C_27)) { return false; } - - bool result = false; - - if ((FUNC_INIT == function) && PinUsed(GPIO_MGC3130_XFER) && PinUsed(GPIO_MGC3130_RESET)) { - 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 "/workspace/Tasmota/tasmota/xsns_37_rfsensor.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_37_rfsensor.ino" -#ifdef USE_RF_SENSOR -# 33 "/workspace/Tasmota/tasmota/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 "/workspace/Tasmota/tasmota/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); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{"), sensor); - ResponseAppendTHD(temp, humi); - ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s}"), voltage); - - if ((0 == tele_period) && !sensor_once) { -#ifdef USE_DOMOTICZ - DomoticzTempHumPressureSensor(temp, humi); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temp); - KnxSensor(KNX_HUMIDITY, humi); -#endif - sensor_once = true; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_THD(sensor, temp, humi); -#endif - } - } - } - } -} - -#endif - -#ifdef USE_ALECTO_V2 -# 389 "/workspace/Tasmota/tasmota/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); - float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); - - 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 "\":{")); - ResponseAppendTHD(temp, humi); - ResponseAppend_P(PSTR(",\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); - - if (0 == tele_period) { -#ifdef USE_DOMOTICZ - - - - -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_THD(D_ALECTOV2, temp, humi); - 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 (PinUsed(GPIO_RF_SENSOR) && (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(); - } - } - ssleep = 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 "/workspace/Tasmota/tasmota/xsns_38_az7798.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_38_az7798.ino" -#ifdef USE_AZ7798 - -#define XSNS_38 38 -# 112 "/workspace/Tasmota/tasmota/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); -#ifdef USE_LIGHT - LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); -#endif - 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 (PinUsed(GPIO_AZ_RXD) && PinUsed(GPIO_AZ_TXD)) { - 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) -{ - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,"), ktype, az_co2); - ResponseAppendTHD(az_temperature, az_humidity); - ResponseJsonEnd(); -#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_THD(ktype, az_temperature, az_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 "/workspace/Tasmota/tasmota/xsns_39_max31855.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_39_max31855.ino" -#ifdef USE_MAX31855 - - - - - - - -#define XSNS_39 39 - -const char kMax31855Types[] PROGMEM = "MAX31855|MAX6675"; - -bool max31855_initialized = false; - -struct MAX31855_ResultStruct { - uint8_t ErrorCode; - float ProbeTemperature; - float ReferenceTemperature; -} MAX31855_Result; - -void MAX31855_Init(void) { - if (PinUsed(GPIO_MAX31855CS) && PinUsed(GPIO_MAX31855CLK) && PinUsed(GPIO_MAX31855DO)) { - - - 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); - - max31855_initialized = true; - } -} - - - - - -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; -} - - - - - -float MAX31855_GetProbeTemperature(int32_t RawData) { - if (RawData & 0x80000000) { - RawData = (RawData >> 18) | 0xFFFFC000; - } else { - RawData >>= 18; - } - float result = (RawData * 0.25); - - return ConvertTemp(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 ConvertTemp(result); -} - - - - - -void MAX31855_GetResult(void) { - if (Settings.flag4.max6675) { - int32_t RawData = MAX31855_ShiftIn(16); - int32_t temp = (RawData >> 3) & ((1 << 12) - 1); - - - if (temp == ((1 << 12) - 1)) { return; } - - MAX31855_Result.ErrorCode = 0; - MAX31855_Result.ReferenceTemperature = NAN; - MAX31855_Result.ProbeTemperature = ConvertTemp(0.25 * temp); - } else { - 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); - } - } -} - -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); - - char sensor_name[10]; - GetTextIndexed(sensor_name, sizeof(sensor_name), Settings.flag4.max6675, kMax31855Types); - - if (Json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - sensor_name, 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 -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, probetemp, TempUnit()); -#endif - } -} - - - - - -bool Xsns39(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - MAX31855_Init(); - } - else if (max31855_initialized) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_40_pn532.ino" -# 20 "/workspace/Tasmota/tasmota/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 (PinUsed(GPIO_PN532_RXD) && PinUsed(GPIO_PN532_TXD)) { - 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 "/workspace/Tasmota/tasmota/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\", \"" D_JSON_DATA "\":\"%s\"}}"), uids, card_datas); -#else - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); -#endif - - MqttPublishTeleSensor(); - -#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; - } - } - return false; -} - -#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 "/workspace/Tasmota/tasmota/xsns_41_max44009.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_41_max44009.ino" -#ifdef USE_I2C -#ifdef USE_MAX44009 - - - - - - -#define XSNS_41 41 -#define XI2C_28 28 - -#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 buffer1; - uint8_t buffer2; - for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { - - max44009_address = max44009_addresses[i]; - if (I2cActive(max44009_address)) { continue; } - - 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()) { - I2cSetActiveFound(max44009_address, max44009_types); - max44009_found = 1; - break; - } - } - } - } -} - -void Max4409EverySecond(void) -{ - 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) -{ - if (!I2cEnabled(XI2C_28)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Max4409Detect(); - } - else if (max44009_found) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_42_scd30.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_42_scd30.ino" -#ifdef USE_I2C -#ifdef USE_SCD30 - -#define XSNS_42 42 -#define XI2C_29 29 - - - -#define SCD30_ADDRESS 0x61 - -#define SCD30_MAX_MISSED_READS 3 -#define SCD30_STATE_NO_ERROR 0 -#define SCD30_STATE_ERROR_DATA_CRC 1 -#define SCD30_STATE_ERROR_READ_MEAS 2 -#define SCD30_STATE_ERROR_SOFT_RESET 3 -#define SCD30_STATE_ERROR_I2C_RESET 4 -#define 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 = 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; - -void Scd30Detect(void) -{ - if (I2cActive(SCD30_ADDRESS)) { return; } - - scd30.begin(); - - uint8_t major = 0; - uint8_t minor = 0; - if (scd30.getFirmwareVersion(&major, &minor)) { return; } - uint16_t interval_sec; - if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } - if (scd30.beginMeasuring()) { return; } - - I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); - scd30Found = true; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); -} - - -void Scd30Update(void) -{ - scd30Loop_count++; - if (scd30Loop_count > (scd30Interval_sec - 1)) { - uint32_t error = 0; - switch (scd30ErrorState) { - case 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 = SCD30_STATE_ERROR_DATA_CRC; - scd30CrcError_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("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); -#endif - break; - - case ERROR_SCD30_CO2_ZERO: - scd30Co2Zero_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("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); -#endif - break; - - default: { - scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); -#endif - return; - } - break; - } - } - break; - - case SCD30_STATE_ERROR_DATA_CRC: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); -#endif - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - break; - - case SCD30_STATE_ERROR_READ_MEAS: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); -#endif - scd30Reset_count++; - error = scd30.softReset(); - if (error) { -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); -#endif - error >>= 8; - if (error == 4) { - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } else { - scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; - } - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - case SCD30_STATE_ERROR_SOFT_RESET: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("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_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); -#endif - i2cReset_count++; - error = scd30.clearI2CBus(); - if (error) { - scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); -#endif - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - default: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); -#endif - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } - } - - if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { - scd30IsDataValid = false; - } - } -} - - -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; - } - return 0; -} - -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; - } - return 0; -} - - - - - -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 - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), 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) -{ - if (scd30IsDataValid) - { - float t = ConvertTemp(scd30_Temp); - float h = ConvertHumidity(scd30_Humid); - - if (json) { - ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,"), scd30_CO2, scd30_CO2EAvg); - ResponseAppendTHD(t, h); - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); - DomoticzTempHumPressureSensor(t, h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); - WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); - WSContentSend_THD("SCD30", t, h); -#endif - } - } -} - - - - - -bool Xsns42(byte function) -{ - if (!I2cEnabled(XI2C_29)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Scd30Detect(); - } - else if (scd30Found) { - 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 "/workspace/Tasmota/tasmota/xsns_43_hre.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_43_hre.ino" -#ifdef USE_HRE -# 49 "/workspace/Tasmota/tasmota/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 (!PinUsed(GPIO_HRE_CLOCK) || !PinUsed(GPIO_HRE_DATA)) { 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 "/workspace/Tasmota/tasmota/xsns_44_sps30.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_44_sps30.ino" -#ifdef USE_I2C -#ifdef USE_SPS30 - -#define XSNS_44 44 -#define XI2C_30 30 - -#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(void) -{ - if (!I2cSetDevice(SPS30_ADDR)) { return; } - I2cSetActiveFound(SPS30_ADDR, "SPS30"); - - 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_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) -{ - if (!sps30_running) { return; } - - char str[64]; - 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\"}}")); - MqttPublishTeleSensor(); -} - -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) -{ - if (!I2cEnabled(XI2C_30)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - SPS30_Detect(); - } - else if (sps30_ready) { - switch (function) { - case FUNC_EVERY_SECOND: - SPS30_Every_Second(); - break; - case FUNC_JSON_APPEND: - SPS30_Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SPS30_Show(0); - break; - #endif - case FUNC_COMMAND_SENSOR: - if (XSNS_44 == XdrvMailbox.index) { - result = SPS30_cmd(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_45_vl53l0x.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_45_vl53l0x.ino" -#ifdef USE_I2C -#ifdef USE_VL53L0X - - - - - - -#define XSNS_45 45 -#define XI2C_31 31 - -#include -#include "VL53L0X.h" -VL53L0X sensor; - -struct { - uint16_t distance; - uint16_t distance_prev; - uint16_t buffer[5]; - uint8_t ready = 0; - uint8_t index; -} Vl53l0x; - - - -void Vl53l0Detect(void) { - if (!I2cSetDevice(0x29)) { return; } - - if (!sensor.init()) { return; } - - I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); - - sensor.setTimeout(500); - - - - - - sensor.startContinuous(); - Vl53l0x.ready = 1; - - Vl53l0x.index = 0; -} - -#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(void) { - - uint16_t dist = sensor.readRangeContinuousMillimeters(); - if ((0 == dist) || (dist > 2000)) { - dist = 9999; - } - -#ifdef USE_VL_MEDIAN - - Vl53l0x.buffer[Vl53l0x.index] = dist; - Vl53l0x.index++; - if (Vl53l0x.index >= 5) { - Vl53l0x.index = 0; - } - - - uint16_t tbuff[5]; - memmove(tbuff, Vl53l0x.buffer, sizeof(tbuff)); - uint16_t tmp; - uint8_t flag; - for (uint32_t ocnt = 0; ocnt < 5; ocnt++) { - flag = 0; - for (uint32_t 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 -} - -#ifdef USE_DOMOTICZ -void Vl53l0Every_Second(void) { - if (abs(Vl53l0x.distance - Vl53l0x.distance_prev) > 8) { - Vl53l0x.distance_prev = Vl53l0x.distance; - DomoticzSensor(DZ_ILLUMINANCE, Vl53l0x.distance); - } -} -#endif - -void Vl53l0Show(boolean json) { - if (json) { - ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), Vl53l0x.distance); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, Vl53l0x.distance); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VL53L0X, Vl53l0x.distance); -#endif - } -} - - - - - -bool Xsns45(byte function) -{ - if (!I2cEnabled(XI2C_31)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Vl53l0Detect(); - } - else if (Vl53l0x.ready) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - Vl53l0Every_250MSecond(); - break; -#ifdef USE_DOMOTICZ - case FUNC_EVERY_SECOND: - Vl53l0Every_Second(); - break; -#endif - case FUNC_JSON_APPEND: - Vl53l0Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Vl53l0Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_46_MLX90614.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_46_MLX90614.ino" -#ifdef USE_I2C -#ifdef USE_MLX90614 - -#define XSNS_46 46 -#define XI2C_32 32 - -#define I2_ADR_IRT 0x5a - -#define MLX90614_RAWIR1 0x04 -#define MLX90614_RAWIR2 0x05 -#define MLX90614_TA 0x06 -#define MLX90614_TOBJ1 0x07 -#define MLX90614_TOBJ2 0x08 - -struct { - union { - uint16_t value; - uint32_t i2c_buf; - }; - float obj_temp; - float amb_temp; - bool ready = false; -} mlx90614; - -void MLX90614_Init(void) -{ - if (!I2cSetDevice(I2_ADR_IRT)) { return; } - I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); - mlx90614.ready = true; -} - -void MLX90614_Every_Second(void) -{ - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); - if (mlx90614.value & 0x8000) { - mlx90614.obj_temp = -999; - } else { - mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; - } - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); - if (mlx90614.value & 0x8000) { - mlx90614.amb_temp = -999; - } else { - mlx90614.amb_temp = ((float)mlx90614.value * 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}"; -#endif - -void MLX90614_Show(uint8_t json) -{ - char obj_tstr[16]; - dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); - char amb_tstr[16]; - dtostrfd(mlx90614.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 - } -} - - - - - -bool Xsns46(byte function) -{ - if (!I2cEnabled(XI2C_32)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MLX90614_Init(); - } - else if (mlx90614.ready) { - switch (function) { - 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 "/workspace/Tasmota/tasmota/xsns_47_max31865.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_47_max31865.ino" -#ifdef USE_MAX31865 - - - - -#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 - -#include "Adafruit_MAX31865.h" - -int8_t max31865_init_status = 0; -uint8_t max31865_pins_used = 0; - -Adafruit_MAX31865 max31865[MAX_MAX31865S]; - -struct MAX31865_Result_Struct { - uint8_t ErrorCode; - uint16_t Rtd; - float PtdResistance; - float PtdTemp; -} MAX31865_Result[MAX_MAX31865S]; - -void MAX31865_Init(void) { - if (max31865_init_status) { return; } - - max31865_init_status = 1; - for (uint32_t i = 0; i < MAX_MAX31865S; i++) { - if (PinUsed(GPIO_SSPI_MAX31865_CS1, i)) { - max31865_pins_used |= 1 << i; - max31865[0].setPins( - Pin(GPIO_SSPI_MAX31865_CS1, i), - Pin(GPIO_SSPI_MOSI), - Pin(GPIO_SSPI_MISO), - Pin(GPIO_SSPI_SCLK) - ); - - if (!max31865[i].begin(PTD_WIRES)) { - max31865_init_status = -1; - } - } - } -} - - - - - -void MAX31865_GetResult(void) { - for (uint32_t i = 0; i < MAX_MAX31865S; i++) { - if (max31865_pins_used & (1 << i)) { - uint16_t rtd; - - rtd = max31865[i].readRTD(); - MAX31865_Result[i].Rtd = rtd; - MAX31865_Result[i].PtdResistance = max31865[i].rtd_to_resistance(rtd, MAX31865_REF_RES); - MAX31865_Result[i].PtdTemp = max31865[i].rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; - } - } -} - -void MAX31865_Show(bool Json) { - uint8_t report_once = 0; - for (uint32_t i = 0; i < MAX_MAX31865S; i++) { - if (max31865_pins_used & (1 << i)) { - char temperature[33]; - char resistance[33]; - - dtostrfd(MAX31865_Result[i].PtdResistance, Settings.flag2.temperature_resolution, resistance); - dtostrfd(MAX31865_Result[i].PtdTemp, Settings.flag2.temperature_resolution, temperature); - - if (Json) { - ResponseAppend_P(PSTR(",\"MAX31865%c%d\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - IndexSeparator(), i, temperature, resistance, MAX31865_Result[i].ErrorCode); - if ((0 == tele_period) && (!report_once)) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, MAX31865_Result[i].PtdTemp); -#endif - report_once++; - } -#ifdef USE_WEBSERVER - } else { - char sensorname[33]; - sprintf(sensorname, "MAX31865%c%d", IndexSeparator(), i); - WSContentSend_PD(HTTP_SNS_TEMP, sensorname, temperature, TempUnit()); -#endif - } - } - } -} - - - - - -bool Xsns47(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_SSPI_MAX31865_CS1, GPIO_ANY) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) { - switch (function) { - case FUNC_INIT: - MAX31865_Init(); - break; - - case FUNC_EVERY_SECOND: - MAX31865_GetResult(); - break; - - case FUNC_JSON_APPEND: - MAX31865_Show(1); - break; - -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31865_Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" -# 37 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" -#ifdef USE_I2C -#ifdef USE_CHIRP -# 49 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" -#define XSNS_48 48 -#define XI2C_33 33 - -#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 - - - - - -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { - Wire.beginTransmission(addr); - Wire.write(reg); - Wire.endTransmission(); -} - -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { - Wire.requestFrom(addr,(uint8_t)2); - uint16_t t = Wire.read() << 8; - t = t | Wire.read(); - return t; -} - - - - - -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) { - ChirpWriteI2CRegister(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) { - ChirpWriteI2CRegister(addr, CHIRP_SLEEP); -} -# 187 "/workspace/Tasmota/tasmota/xsns_48_chirp.ino" -void ChirpSelect(uint8_t sensor) { - if(sensor < chirp_found_sensors) { - chirp_current = sensor; - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); - } - if (sensor == 255) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); - } -} - - - -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)){ - 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); - - } - 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){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); - chirp_sensor[chirp_current].version == 0; - } - return true; - } - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); - 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) { - I2cSetActiveFound(address, "CHIRP"); - if (chirp_found_sensors 0); -} - - - -void ChirpDetect(void) -{ - if (chirp_next_job > 0) { return; } - - DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); - if (ChirpScan()) { - uint8_t chirp_model = 0; - GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); - } -} - - -void ChirpServiceAllSensors(uint8_t job){ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); - switch(job){ - case 0: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); - break; - case 1: - chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 2: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); - break; - case 3: - chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 4: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); - break; - case 5: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); - break; - case 6: - chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - default: - break; - } - } - } -} - - - -void ChirpEvery100MSecond(void) -{ - - if(chirp_timeout_count == 0) { - switch(chirp_next_job) { - case 0: - DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); - ChirpResetAll(); - chirp_timeout_count = 10; - chirp_next_job++; - break; - case 1: - - - chirp_next_job++; - break; - case 2: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 3: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 4: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 5: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 6: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 7: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 8: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 9: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 10: - DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); - ChirpServiceAllSensors(4); - chirp_timeout_count = 90; - chirp_next_job++; - break; - case 11: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); - ChirpServiceAllSensors(5); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 12: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); - ChirpServiceAllSensors(6); - chirp_next_job++; - break; - case 13: - DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); - chirp_next_job++; - break; - case 14: - if (Settings.tele_period > 16){ - chirp_timeout_count = (Settings.tele_period - 16) * 10; - 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 !")); - - } - chirp_next_job = 1; - break; - } - } - else { - chirp_timeout_count--; - } -} - - - - -#ifdef USE_WEBSERVER - - -const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{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_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[7]; - if(chirp_sensor[i].version == 0xff){ - 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 "\":%d"), chirp_name, i, chirp_sensor[i].moisture); - if(chirp_sensor[i].temperature!=-1){ - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); - } - ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); - } - else { - ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); - } - #ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumPressureSensor(t_temperature, chirp_sensor[i].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, "", chirp_sensor[i].moisture); - WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); - if (chirp_sensor[i].temperature!=-1) { - 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) -{ - if (!I2cEnabled(XI2C_33)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if(chirp_found_sensors > 0){ - ChirpEvery100MSecond(); - } - break; - case FUNC_COMMAND: - result = ChirpCmd(); - break; - case FUNC_JSON_APPEND: - ChirpShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ChirpShow(0); - break; -#endif - case FUNC_INIT: - ChirpDetect(); - break; - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" -# 31 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" -#ifdef USE_I2C -#ifdef USE_PAJ7620 - - - - - - -#define XSNS_50 50 -#define XI2C_34 34 - -#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} -}; - - - - - -const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; - -const uint8_t PAJ7620_PIN[]= {1,2,3,4}; - - - - - -char PAJ7620_name[] = "PAJ7620"; - -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 PAJ7620SelectBank(uint8_t bank) -{ - I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); -} - - - -void PAJ7620DecodeGesture(void) -{ - uint32_t index = 0; - switch (PAJ7620_gesture.current) { - case PAJ7620_LEFT: - index++; - case PAJ7620_RIGHT: - index++; - case PAJ7620_UP: - index++; - case PAJ7620_DOWN: - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_NEAR: - index = 4; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_FAR: - index = 5; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_CW: - index = 6; - PAJ7620_finished_gesture = true; - break; - case PAJ7620_CCW: - index = 7; - PAJ7620_finished_gesture = true; - break; - default: - index = 8; - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - } - break; - } - if (index < 8) { - GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); - } - - 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; - MqttPublishSensor(); - } -} - - - -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("PAJ: 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("PAJ: Proximity: %u"), PAJ7620_state.proximity); - MqttPublishSensor(); - } - } - 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("PAJ: 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; - } - 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("PAJ: 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("PAJ: PIN valid!!")); - PAJ7620_state.PIN.countdown = 0; - } - MqttPublishSensor(); - } - } - break; - } -} - - - -void PAJ7620Detect(void) -{ - if (I2cActive(PAJ7620_ADDR)) { return; } - - PAJ7620SelectBank(0); - PAJ7620SelectBank(0); - uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); - uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); - if (0x7620 == PAJ7620_id) { - I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); - PAJ7620_next_job = 1; - } - else { - DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); - } -} - - - -void PAJ7620Init(void) -{ - DEBUG_SENSOR_LOG(PSTR("PAJ: 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("PAJ: %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("PAJ: init sensor done %u"),millis()); - PAJ7620_next_job = 2; -} - - - -void PAJ7620Loop(void) -{ - if (0 == PAJ7620_timeout_counter) { - switch (PAJ7620_next_job) { - case 1: - PAJ7620Init(); - break; - case 2: - if (PAJ7620_mode != 0) { - PAJ7620ReadGesture(); - } - break; - } - } else { - PAJ7620_timeout_counter--; - } -} - - - -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: - ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); - break; - case 3: - if (PAJ7620_state.corner > 0) { - ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); - } - break; - case 4: - if (PAJ7620_state.PIN.valid) { - ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); - PAJ7620_state.PIN.valid = 0; - } - break; - case 5: - ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); - break; - } - } -} -# 411 "/workspace/Tasmota/tasmota/xsns_50_paj7620.ino" -bool PAJ7620CommandSensor(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - PAJ7620_mode = XdrvMailbox.payload; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); - - return true; -} - - - - - -bool Xsns50(uint8_t function) -{ - if (!I2cEnabled(XI2C_34)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PAJ7620Detect(); - } - else if (PAJ7620_next_job) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_50 == XdrvMailbox.index){ - result = PAJ7620CommandSensor(); - } - break; - case FUNC_EVERY_100_MSECOND: - PAJ7620Loop(); - break; - case FUNC_JSON_APPEND: - PAJ7620Show(1); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" -#ifdef USE_RDM6300 -# 31 "/workspace/Tasmota/tasmota/xsns_51_rdm6300.ino" -#define XSNS_51 51 - -#define RDM6300_BAUDRATE 9600 -#define RDM_TIMEOUT 100 -#define RDM6300_BLOCK 2 * 10 - -#include -TasmotaSerial *RDM6300Serial = nullptr; - -struct { - uint32_t uid = 0; - uint8_t block_time = 0; -} Rdm; - - - -uint8_t RDM6300HexNibble(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; -} - - -void RDM6300HexStringToArray(uint8_t array[], uint8_t len, char buffer[]) { - char *cp = buffer; - for (uint32_t i = 0; i < len; i++) { - uint8_t val = RDM6300HexNibble(*cp++) << 4; - array[i] = val | RDM6300HexNibble(*cp++); - } -} - - - -void RDM6300Init() { - if (PinUsed(GPIO_RDM6300_RX)) { - RDM6300Serial = new TasmotaSerial(Pin(GPIO_RDM6300_RX), -1, 1); - if (RDM6300Serial->begin(RDM6300_BAUDRATE)) { - if (RDM6300Serial->hardwareSerial()) { - ClaimSerial(); - } - } - } -} - -void RDM6300ScanForTag() { - if (!RDM6300Serial) { return; } - - if (Rdm.block_time > 0) { - Rdm.block_time--; - while (RDM6300Serial->available()) { - RDM6300Serial->read(); - } - return; - } - - if (RDM6300Serial->available()) { - - char c = RDM6300Serial->read(); - if (c != 2) { return; } - - - char rdm_buffer[14]; - uint8_t rdm_index = 0; - - rdm_buffer[rdm_index++] = c; - - uint32_t cmillis = millis(); - while (1) { - if (RDM6300Serial->available()) { - c = RDM6300Serial->read(); - rdm_buffer[rdm_index++] = c; - - if (3 == c) { break; } - if (rdm_index > 14) { break; } - } - if ((millis() - cmillis) > RDM_TIMEOUT) { - return; - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)rdm_buffer, sizeof(rdm_buffer)); - - if (rdm_buffer[13] != 3) { return; } - - Rdm.block_time = RDM6300_BLOCK; - - uint8_t rdm_array[6]; - RDM6300HexStringToArray(rdm_array, sizeof(rdm_array), (char*)rdm_buffer +1); - uint8_t accu = 0; - for (uint32_t count = 0; count < 5; count++) { - accu ^= rdm_array[count]; - } - if (accu != rdm_array[5]) { return; } - - rdm_buffer[11] = '\0'; - uint32_t uid = strtoul(rdm_buffer +3, nullptr, 16); - if (uid > 0) { - Rdm.uid = uid; - ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%08X\"}}"), Rdm.uid); - MqttPublishTeleSensor(); - } - } -} - -#ifdef USE_WEBSERVER -void RDM6300Show(void) { - if (!RDM6300Serial) { return; } - WSContentSend_PD(PSTR("{s}RDM6300 UID{m}%08X {e}"), Rdm.uid); -} -#endif - - - - - -bool Xsns51(byte function) { - bool result = false; - - switch (function) { - case FUNC_INIT: - RDM6300Init(); - break; - case FUNC_EVERY_100_MSECOND: - RDM6300ScanForTag(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RDM6300Show(); - break; -#endif - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_52_ibeacon.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_52_ibeacon.ino" -#ifdef USE_IBEACON - - - -#define XSNS_52 52 - -#include - -#define TMSBSIZ52 512 - -#define HM17_BAUDRATE 9600 - -#define IBEACON_DEBUG - - -#define HM17_V110 - - - -#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]; - char UID[32]; - char MAJOR[4]; - char MINOR[4]; - uint8_t FLAGS; - uint8_t TIME; -} ibeacons[MAX_IBEACONS]; - - -void IBEACON_Init() { - - hm17_found=0; - - - if (PinUsed(GPIO_IBEACON_RX) && PinUsed(GPIO_IBEACON_TX)) { - IBEACON_Serial = new TasmotaSerial(Pin(GPIO_IBEACON_RX), Pin(GPIO_IBEACON_TX),1,0,TMSBSIZ52); - 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",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR); - } - } - } - } else { - if (uptime%20==0) { - hm17_sendcmd(HM17_TEST); - } - } -} - -void hm17_sbclr(void) { - memset(hm17_sbuffer,0,HM17_BSIZ); - hm17_sindex=0; - -} - -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->RSSI,"0",1)) { - return 0; - } - - - if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { - for (uint32_t cnt=0;cntUID,PSTR("00000000000000000000000000000000"),32)) { - if (!strncmp(ibeacons[cnt].MAC,ib->MAC,12)) { - - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].TIME=0; - return 1; - } - } else { - if (!strncmp(ibeacons[cnt].UID,ib->UID,32)) { - - 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); - memcpy(ibeacons[cnt].UID,ib->UID,32); - memcpy(ibeacons[cnt].MAJOR,ib->MAJOR,4); - memcpy(ibeacons[cnt].MINOR,ib->MINOR,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+DISIS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS 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_cmd==HM17_DISI) { -#ifdef HM17_V110 - goto hm17_v110; -#endif - } else { - 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)) { -hm17_v110: - 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,ib.UID,ib.MAJOR,ib.MINOR); - } - 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_mac[] PROGMEM = - "{s}IBEACON-MAC : %s" " - RSSI : %s" "{m}{e}"; -const char HTTP_IBEACON_uid[] PROGMEM = - "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; - -void IBEACON_Show(void) { -char mac[14]; -char rssi[6]; -char uid[34]; - - 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 - - -#ifndef ESP32 -#define SPECIAL_SS -#endif - -#undef TMSBSIZ -#define TMSBSIZ 256 - - - - - - -#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 -# 440 "/workspace/Tasmota/tasmota/xsns_53_sml.ino" -#define USE_SML_MEDIAN_FILTER - - -#ifndef SML_MAX_VARS -#define SML_MAX_VARS 20 -#endif - - -#ifndef MAX_METERS -#define MAX_METERS 5 -#endif -double meter_vars[SML_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]; - - -#ifdef ESP32 -HardwareSerial *meter_ss[MAX_METERS]; -#else -TasmotaSerial *meter_ss[MAX_METERS]; -#endif - - -#ifndef SML_BSIZ -#define SML_BSIZ 48 -#endif -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[SML_MAX_VARS]; - -#ifndef FLT_MAX -#define FLT_MAX 99999999 -#endif - -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); -# 552 "/workspace/Tasmota/tasmota/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; - if (!meter_ss[num-1]) return 0; - return meter_ss[num-1]->available(); -} - -uint8_t Serial_read() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - if (!meter_ss[num-1]) return 0; - return meter_ss[num-1]->read(); -} - -uint8_t Serial_peek() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - if (!meter_ss[num-1]) return 0; - 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 (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 { - if (meter_desc_p[(dump2log&7)-1].type=='o') { - - 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_logindex2) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - } - } - } -} - -#ifdef ED300L -uint8_t sml_status[MAX_METERS]; -uint8_t g_mindex; -#endif - - -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; - - - -#ifdef ED300L - unsigned char *cpx=cp-5; - - if (*cp==0x64 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { - sml_status[g_mindex]=*(cp+3); - } - if (*cp==0x63 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { - sml_status[g_mindex]=*(cp+2); - } -#endif - - 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!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R') { - - 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' || meter_desc_p[meters].type=='M') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=SML_BSIZ) { - meter_spos[meters]=0; - } - if (meter_spos[meters]>=8) { - uint32_t mlen=smltbuf[meters][2]+5; - if (mlen>SML_BSIZ) mlen=SML_BSIZ; - if (meter_spos[meters]>=mlen) { - 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 (meter_desc_p[meters].type=='R') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=SML_BSIZ) { - 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!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R') 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) { - - if (*mp==0) break; - - - 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>SML_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>SML_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>SML_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[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (!strncmp(mp,"SSssSSss",8)) { - int32_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++; - mbus_dval=val; - 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); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { - int16_t val = cp[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } - else if (*mp=='s' && *(mp+1)=='s') { - int8_t val = *cp++; - mbus_dval=val; - 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++; -#ifdef ED300L - g_mindex=mindex; -#endif - 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 pos = smltbuf[mindex][2]+3; - if (pos>32) pos=32; - uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos); - if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect; - if (highByte(crc)!=smltbuf[mindex][pos+1]) 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) { - if (*mp==0) break; - - mindex=((*mp)&7)-1; - - if (mindex<0 || mindex>=meters_used) mindex=0; - if (meter_desc_p[mindex].prefix[0]=='*' && meter_desc_p[mindex].prefix[1]==0) { - nojson=1; - } else { - nojson=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]++; - sml_counters[index].sml_cnt_updated=1; - - } - } else { - - sml_counters[index].sml_counter_ltime=millis(); - } -} - -void ICACHE_RAM_ATTR SML_CounterUpd1(void) { - SML_CounterUpd(0); -} - -void ICACHE_RAM_ATTR SML_CounterUpd2(void) { - SML_CounterUpd(1); -} - -void ICACHE_RAM_ATTR SML_CounterUpd3(void) { - SML_CounterUpd(2); -} - -void ICACHE_RAM_ATTR SML_CounterUpd4(void) { - SML_CounterUpd(3); -} - -#ifdef USE_SCRIPT -struct METER_DESC script_meter_desc[MAX_METERS]; -uint8_t *script_meter; -#endif - -#ifndef METER_DEF_SIZE -#define METER_DEF_SIZE 3000 -#endif - - - -#ifdef SML_REPLACE_VARS - -#define SML_SRCBSIZE 256 - -uint32_t SML_getlinelen(char *lp) { -uint32_t cnt; - for (cnt=0; cnt') break; - if (*lp==0) break; - } - - return mlen+32; -} -#else -uint32_t SML_getscriptsize(char *lp) { - uint32_t mlen=0; - for (uint32_t cnt=0;cnt 0)) { - return true; - } - return false; -} - -void SML_Init(void) { - meters_used=METERS_USED; - meter_desc_p=meter_desc; - meter_p=meter; - - sml_desc_cnt=0; - - for (uint32_t cnt=0;cntM",-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=SML_getscriptsize(lp); - if (mlen==0) return; - script_meter=(uint8_t*)calloc(mlen,1); - if (!script_meter) { - goto dddef_exit; - } - tp=script_meter; - goto next_line; - } - } - else { - if (!*lp || *lp=='#' || *lp=='>') { - 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 (*lp1==0) { - *tp++='|'; - goto next_line; - } - *tp++=*lp1++; - index++; - if (index>=METER_DEF_SIZE) break; - } - } -#else - - if (*lp=='-' || isdigit(*lp)) { - - - if (*lp=='-') lp++; - uint8_t mnum=strtol(lp,0,10); - if (mnum<1 || mnum>meters_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; - } - } -#endif - - } - -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(); - } - uint32_t uart_index=2; - for (uint8_t meters=0; meterssetRxBufferSize(TMSBSIZ); -#else - meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,0,TMSBSIZ); -#endif -#endif - -#ifdef ESP32 - if (meter_desc_p[meters].type=='M') { - meter_ss[meters]->begin(meter_desc_p[meters].params, SERIAL_8E1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin); - } else { - meter_ss[meters]->begin(meter_desc_p[meters].params,SERIAL_8N1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin); - } -#else - if (meter_ss[meters]->begin(meter_desc_p[meters].params)) { - meter_ss[meters]->flush(); - } - if (meter_ss[meters]->hardwareSerial()) { - if (meter_desc_p[meters].type=='M') { - Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); - } - ClaimSerial(); - - } -#endif - } - } - -} - - -#ifdef USE_SML_SCRIPT_CMD -uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - -#ifdef ESP32 - meter_ss[meter]->flush(); - meter_ss[meter]->updateBaudRate(br); - - - - - - -#else - if (meter_ss[meter]->begin(br)) { - meter_ss[meter]->flush(); - } - if (meter_ss[meter]->hardwareSerial()) { - if (meter_desc_p[meter].type=='M') { - Serial.begin(br, SERIAL_8E1); - } - } -#endif - return 1; -} - -uint32_t SML_Status(uint32_t meter) { - if (meter<1 || meter>meters_used) return 0; - meter--; -#ifdef ED300L - return sml_status[meter]; -#else - return 0; -#endif -} - - -uint32_t SML_Write(uint32_t meter,char *hstr) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - SML_Send_Seq(meter,hstr); - return 1; -} - -uint32_t SML_Read(int32_t meter,char *str, uint32_t slen) { -uint8_t hflg=0; - if (meter<0) { - meter=abs(meter); - hflg=1; - } - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - - if (!meter_spos[meter]) { - return 0; - } - - smltbuf[meter][meter_spos[meter]]=0; - - if (!hflg) { - strlcpy(str,(char*)&smltbuf[meter][0],slen); - } else { - uint32_t index=0; - for (uint32_t cnt=0; cnt=slen-2) break; - } - } - meter_spos[meter]=0; - return 1; -} - -float SML_GetVal(uint32_t index) { - if (index<1 && index>SML_MAX_VARS) { index = 1;} - return meter_vars[index-1]; -} - -#endif - - -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 - } - - if (sml_counters[cindex].sml_cnt_updated) { - InjektCounterValue(sml_counters[cindex].sml_cnt_old_state,RtcSettings.pulse_counter[cindex]); - sml_counters[cindex].sml_cnt_updated=0; - } - - - } - 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; - } - } - } - 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)) { - sml_100ms_cnt=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; - uint8_t rflg = 0; - if (*cp=='r') { - rflg = 1; - cp++; - } - 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' || script_meter_desc[meter].type=='M') { - if (!rflg) { - *ucp++=0; - *ucp++=2; - slen+=2; - } - - uint16_t crc = MBUS_calculateCRC(sbuff,slen); - *ucp++=lowByte(crc); - *ucp++=highByte(crc); - slen+=2; - } - if (script_meter_desc[meter].type=='o') { - for (uint32_t cnt=0;cntwrite(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); -} - - -uint8_t CalcEvenParity(uint8_t data) { -uint8_t parity=0; - - while(data) { - parity^=(data &1); - data>>=1; - } - return parity; -} -# 2540 "/workspace/Tasmota/tasmota/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++; - uint8_t index=atoi(cp); - if ((index&7)>meters_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') { - - 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( Ina226Info[device].address, INA226_REG_CONFIG ); - - - if (config != Ina226Info[device].config) - return false; - - return true; - -} - -void Ina226ResetActive(void) -{ - Ina226Info_t *p = Ina226Info; - - for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { - p = &Ina226Info[i]; - - uint8_t addr = p->address; - if (addr) { - I2cResetActive(addr); - } - } -} - - - - - -void Ina226Init() -{ - uint32_t i; - - Ina226sFound = 0; - - Ina226Info_t *p = Ina226Info; -# 215 "/workspace/Tasmota/tasmota/xsns_54_ina226.ino" - 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 (I2cActive(addr)) { continue; } - - - - - 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 = &Ina226Info[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); - - I2cSetActiveFound(addr, Ina226Str); - - Ina226sFound++; - } -} - - - - - -float Ina226ReadBus_v(uint8_t device) -{ - uint8_t addr = Ina226Info[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 = Ina226Info[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); - - float result = ((float) reg_shunt_i) * Ina226Info[device].i_lsb; - - return result; -} - - - - - -float Ina226ReadPower_w(uint8_t device) -{ - uint8_t addr = Ina226Info[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); - - float result = ((float) reg_shunt_i) * (Ina226Info[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 (Ina226sFound && Ina226Info[device].present && Ina226TestPresence(device)){ - Ina226Read(device); - } - else { - powers[device] = currents[device] = voltages[device] = 0.0f; - - - - - - - Ina226Info[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: - Ina226ResetActive(); - Ina226Init(); - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Ina226sFound\":%d}}"),Ina226sFound); - 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 (!Ina226Info[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\":%d,\"" 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 - } - - } - -} -# 546 "/workspace/Tasmota/tasmota/xsns_54_ina226.ino" -bool Xsns54(byte callback_id) -{ - if (!I2cEnabled(XI2C_35)) { return false; } - - - bool result = false; - - - switch (callback_id) { - case FUNC_EVERY_SECOND: - Ina226EverySecond(); - 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; - case FUNC_INIT: - Ina226Init(); - break; - } - - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" -#ifdef USE_I2C -#ifdef USE_HIH6 -# 33 "/workspace/Tasmota/tasmota/xsns_55_hih_series.ino" -#define XSNS_55 55 -#define XI2C_36 36 - -#define HIH6_ADDR 0x27 - -struct HIH6 { - float temperature = 0; - float humidity = 0; - uint8_t valid = 0; - uint8_t type = 0; - char types[4] = "HIH"; -} Hih6; - -bool Hih6Read(void) -{ - Wire.beginTransmission(HIH6_ADDR); - if (Wire.endTransmission() != 0) { return false; } - - delay(40); - - uint8_t data[4]; - Wire.requestFrom(HIH6_ADDR, 4); - if (4 == Wire.available()) { - data[0] = Wire.read(); - data[1] = Wire.read(); - data[2] = Wire.read(); - data[3] = Wire.read(); - } else { return false; } - - - - Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); - - int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; - Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); - - Hih6.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Hih6Detect(void) -{ - if (I2cActive(HIH6_ADDR)) { return; } - - if (uptime < 2) { delay(20); } - Hih6.type = Hih6Read(); - if (Hih6.type) { - I2cSetActiveFound(HIH6_ADDR, Hih6.types); - } -} - -void Hih6EverySecond(void) -{ - if (uptime &1) { - - if (!Hih6Read()) { - AddLogMissed(Hih6.types, Hih6.valid); - } - } -} - -void Hih6Show(bool json) -{ - if (Hih6.valid) { - TempHumDewShow(json, (0 == tele_period), Hih6.types, Hih6.temperature, Hih6.humidity); - } -} - - - - - -bool Xsns55(uint8_t function) -{ - if (!I2cEnabled(XI2C_36)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Hih6Detect(); - } - else if (Hih6.type) { - switch (function) { - case FUNC_EVERY_SECOND: - Hih6EverySecond(); - break; - case FUNC_JSON_APPEND: - Hih6Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Hih6Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" -# 21 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" -#ifdef USE_HPMA -# 31 "/workspace/Tasmota/tasmota/xsns_56_hpma.ino" -#define XSNS_56 56 - -#include -#include - -TasmotaSerial *HpmaSerial; -HPMA115S0 *hpma115S0; - -uint8_t hpma_type = 1; -uint8_t hpma_valid = 0; - -struct hpmadata { - unsigned int pm10; - unsigned int pm2_5; -} hpma_data; - - - -void HpmaSecond(void) -{ - unsigned int pm2_5, pm10; - - - - - if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { - hpma_data.pm2_5 = pm2_5; - hpma_data.pm10 = pm10; - hpma_valid = 1; - } - -} - -void HpmaInit(void) -{ - hpma_type = 0; - if (PinUsed(GPIO_HPMA_RX) && PinUsed(GPIO_HPMA_TX)) { - HpmaSerial = new TasmotaSerial(Pin(GPIO_HPMA_RX), Pin(GPIO_HPMA_TX), 1); - hpma115S0 = new HPMA115S0(*HpmaSerial); - - if (HpmaSerial->begin(9600)) { - if (HpmaSerial->hardwareSerial()) { - ClaimSerial(); - } - hpma_type = 1; - hpma115S0->Init(); - hpma115S0->StartParticleMeasurement(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_HPMA_SNS[] PROGMEM = - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void HpmaShow(bool json) -{ - if (hpma_valid) { - char pm10[33]; - snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); - char pm2_5[33]; - snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); - - if (json) { - ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.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_HPMA_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns56(uint8_t function) -{ - bool result = false; - - if (hpma_type) { - switch (function) { - case FUNC_INIT: - HpmaInit(); - break; - case FUNC_EVERY_SECOND: - HpmaSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_56 == XdrvMailbox.index) { - return true; - } - break; - case FUNC_JSON_APPEND: - HpmaShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HpmaShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_57_tsl2591.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_57_tsl2591.ino" -#ifdef USE_I2C -#ifdef USE_TSL2591 - - - - - - - -#define XSNS_57 57 -#define XI2C_40 40 - -#define TSL2591_ADDRESS 0x29 - -#include - -Adafruit_TSL2591 tsl = Adafruit_TSL2591(); - -uint8_t tsl2591_type = 0; -uint8_t tsl2591_valid = 0; -float tsl2591_lux = 0; - -void Tsl2591Init(void) -{ - - if (I2cSetDevice(0x29)) { - if (tsl.begin()) { - tsl.setGain(TSL2591_GAIN_MED); - tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); - tsl2591_type = 1; - I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); - } - } -} - -bool Tsl2591Read(void) -{ - uint32_t lum = tsl.getFullLuminosity(); - uint16_t ir, full; - ir = lum >> 16; - full = lum & 0xFFFF; - tsl2591_lux = tsl.calculateLux(full, ir); - tsl2591_valid = 1; -} - -void Tsl2591EverySecond(void) -{ - Tsl2591Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2591[] PROGMEM = - "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; -#endif - -void Tsl2591Show(bool json) -{ - if (tsl2591_valid) { - char lux_str[10]; - dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); - if (json) { - ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); -#endif - } - } -} - - - - - -bool Xsns57(uint8_t function) -{ - if (!I2cEnabled(XI2C_40)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2591Init(); - } - else if (tsl2591_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Tsl2591EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2591Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2591Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_58_dht12.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_58_dht12.ino" -#ifdef USE_I2C -#ifdef USE_DHT12 - - - - - - -#define XSNS_58 58 -#define XI2C_41 41 - -#define DHT12_ADDR 0x5C - -struct DHT12 { - float temperature = NAN; - float humidity = NAN; - uint8_t valid = 0; - uint8_t count = 0; - char name[6] = "DHT12"; -} Dht12; - -bool Dht12Read(void) -{ - if (Dht12.valid) { Dht12.valid--; } - - Wire.beginTransmission(DHT12_ADDR); - Wire.write(0); - if (Wire.endTransmission() != 0) { return false; } - - delay(50); - - Wire.requestFrom(DHT12_ADDR, 5); - delay(5); - uint8_t humidity = Wire.read(); - uint8_t humidityTenth = Wire.read(); - uint8_t temp = Wire.read(); - uint8_t tempTenth = Wire.read(); - uint8_t checksum = Wire.read(); - - Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); - Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); - - if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } - - Dht12.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Dht12Detect(void) -{ - if (I2cActive(DHT12_ADDR)) { return; } - - if (Dht12Read()) { - I2cSetActiveFound(DHT12_ADDR, Dht12.name); - Dht12.count = 1; - } -} - -void Dht12EverySecond(void) -{ - if (uptime &1) { - - if (!Dht12Read()) { - AddLogMissed(Dht12.name, Dht12.valid); - } - } -} - -void Dht12Show(bool json) -{ - if (Dht12.valid) { - TempHumDewShow(json, (0 == tele_period), Dht12.name, Dht12.temperature, Dht12.humidity); - } -} - - - - - -bool Xsns58(uint8_t function) -{ - if (!I2cEnabled(XI2C_41)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Dht12Detect(); - } - else if (Dht12.count) { - switch (function) { - case FUNC_EVERY_SECOND: - Dht12EverySecond(); - break; - case FUNC_JSON_APPEND: - Dht12Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Dht12Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_59_ds1624.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_59_ds1624.ino" -#ifdef USE_I2C -#ifdef USE_DS1624 - - - - - - - -#define XSNS_59 59 -#define XI2C_42 42 - -#define DS1624_MEM_REGISTER 0x17 -#define DS1624_CONF_REGISTER 0xAC -#define DS1624_TEMP_REGISTER 0xAA -#define DS1624_START_REGISTER 0xEE -#define DS1624_STOP_REGISTER 0x22 - -#define DS1621_COUNTER_REGISTER 0xA8 -#define DS1621_SLOPE_REGISTER 0xA9 - -#define DS1621_CFG_1SHOT (1<<0) -#define DS1621_CFG_DONE (1<<7) - -enum { - DS1624_TYPE_DS1624, - DS1624_TYPE_DS1621 -}; - -#define DS1624_MAX_SENSORS 8 - -bool ds1624_init = false; - -struct { - float value; - uint8_t type; - int errcnt; - int misscnt; - bool valid; - char name[9]; -} ds1624_sns[DS1624_MAX_SENSORS]; - -uint32_t DS1624_Idx2Addr(uint32_t idx) { - return 0x48 + idx; -} - -void DS1624_Restart(uint8_t config, uint32_t idx) { - uint32_t addr = DS1624_Idx2Addr(idx); - if ((config & 1) == 1) { - config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - delay(10); - AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); - } - I2cValidRead(addr, DS1624_START_REGISTER, 1); -} - -void DS1624_HotPlugUp(uint32_t idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - if (I2cActive(addr)) { return; } - if (!I2cSetDevice(addr)) { return; } - - uint8_t config; - if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - uint8_t tmp; - ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; - - snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), - (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); - I2cSetActiveFound(addr, ds1624_sns[idx].name); - - ds1624_sns[idx].valid = true; - ds1624_sns[idx].errcnt = 0; - ds1624_sns[idx].misscnt = 0; - DS1624_Restart(config,idx); - AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); - } -} - -void DS1624_HotPlugDown(int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - if (!I2cActive(addr)) { return; } - I2cResetActive(addr); - ds1624_sns[idx].valid = false; - AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); -} - -bool DS1624GetTemp(float *value, int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - uint8_t config; - if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - ds1624_sns[idx].misscnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); - return false; - } - ds1624_sns[idx].misscnt=0; - if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { - ds1624_sns[idx].errcnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); - DS1624_Restart(config, idx); - return false; - } - - uint16_t t; - if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } - if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { - *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; - } else { - - *value = ((float)(int8_t)(t>>8)); - uint8_t remain; - if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } - uint8_t perc; - if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } - float fix=(float)(perc - remain)/(float)perc; - *value+=fix; - } - ds1624_sns[idx].errcnt=0; - config &= ~(DS1621_CFG_DONE); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - return true; -} - -void DS1624HotPlugScan(void) -{ - uint16_t t; - - for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { - uint32_t addr = DS1624_Idx2Addr(idx); - if (I2cActive(addr) && !ds1624_sns[idx].valid) { - continue; - } - if (ds1624_sns[idx].valid) { - if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { - DS1624_HotPlugDown(idx); - continue; - } - } - DS1624_HotPlugUp(idx); - } -} - -void DS1624EverySecond(void) -{ - float t; - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - if (!DS1624GetTemp(&t, i)) { continue; } - ds1624_sns[i].value = ConvertTemp(t); - } -} - -void DS1624Show(bool json) -{ - char temperature[33]; - bool once = true; - - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - - dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, ds1624_sns[i].name, temperature); - if ((0 == tele_period) && once) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, ds1624_sns[i].value); -#endif - once = false; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns59(uint8_t function) -{ - if (!I2cEnabled(XI2C_42)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - if (!ds1624_init) { - memset(ds1624_sns, 0, sizeof(ds1624_sns)); - ds1624_init = true; - DS1624HotPlugScan(); - } - } - switch (function) { - case FUNC_HOTPLUG_SCAN: - DS1624HotPlugScan(); - break; - case FUNC_EVERY_SECOND: - DS1624EverySecond(); - break; - case FUNC_JSON_APPEND: - DS1624Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DS1624Show(0); - break; -#endif - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" -#ifdef USE_GPS -#if defined(ESP32) && defined(USE_FLOG) - #undef USE_FLOG - #warning FLOG deactivated on ESP32 -#endif -# 117 "/workspace/Tasmota/tasmota/xsns_60_GPS.ino" -#define XSNS_60 60 - -#include "NTPServer.h" -#include "NTPPacket.h" - - - - - -#define D_CMND_UBX "UBX" - -const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; - -const char kUBXTypes[] PROGMEM = "UBX"; - -#define UBX_LAT_LON_THRESHOLD 1000 - -#define UBX_SERIAL_BUFFER_SIZE 256 -#define UBX_TCP_PORT 1234 -#define NTP_MILLIS_OFFSET 50 - - - - - -const char UBLOX_INIT[] PROGMEM = { - - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, - - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, - - - - - - -}; - -char UBX_name[4]; - -struct UBX_t { - const char UBX_HEADER[2] = { 0xB5, 0x62 }; - const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; - const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; - const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; - - struct entry_t { - int32_t lat; - int32_t lon; - uint32_t time; - }; - - union { - entry_t values; - uint8_t bytes[sizeof(entry_t)]; - } rec_buffer; - - struct POLL_MSG { - uint8_t cls; - uint8_t id; - uint16_t zero; - }; - - struct NAV_POSLLH { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - int32_t lon; - int32_t lat; - int32_t alt; - int32_t hMSL; - uint32_t hAcc; - uint32_t vAcc; - }; - - struct NAV_STATUS { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint8_t gpsFix; - uint8_t flags; - uint8_t fixStat; - uint8_t flags2; - uint32_t ttff; - uint32_t msss; - }; - - struct NAV_TIME_UTC { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint32_t tAcc; - int32_t nano; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - struct { - uint8_t UTC:1; - uint8_t WKN:1; - uint8_t TOW:1; - uint8_t padding:5; - } valid; - }; - - struct CFG_RATE { - uint8_t cls; - uint8_t id; - uint16_t len; - uint16_t measRate; - uint16_t navRate; - uint16_t timeRef; - char CK[2]; - }; - - struct { - uint32_t last_iTOW; - int32_t last_alt; - uint32_t last_hAcc; - uint32_t last_vAcc; - uint8_t gpsFix; - uint8_t non_empty_loops; - uint16_t log_interval; - int32_t timeOffset; - } state; - - struct { - uint32_t init:1; - uint32_t filter_noise:1; - uint32_t send_when_new:1; - uint32_t send_UI_only:1; - uint32_t runningNTP:1; - - uint32_t forceUTCupdate:1; - uint32_t runningVPort:1; - - } mode; - - union { - NAV_POSLLH navPosllh; - NAV_STATUS navStatus; - NAV_TIME_UTC navTime; - POLL_MSG pollMsg; - CFG_RATE cfgRate; - } Message; - - uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; - size_t TCPbufSize; -} UBX; - -enum UBXMsgType { - MT_NONE, - MT_NAV_POSLLH, - MT_NAV_STATUS, - MT_NAV_TIME, - MT_POLL -}; - -#ifdef USE_FLOG -FLOG *Flog = nullptr; -#endif -TasmotaSerial *UBXSerial; - -NtpServer timeServer(PortUdp); - -WiFiServer vPortServer(UBX_TCP_PORT); -WiFiClient vPortClient; - - - - - -void UBXcalcChecksum(char* CK, size_t msgSize) -{ - memset(CK, 0, 2); - for (int i = 0; i < msgSize; i++) { - CK[0] += ((char*)(&UBX.Message))[i]; - CK[1] += CK[0]; - } -} - -bool UBXcompareMsgHeader(const char* msgHeader) -{ - char* ptr = (char*)(&UBX.Message); - return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; -} - -void UBXinitCFG(void) -{ - for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); -} - -void UBXsendCFGLine(uint8_t _line) -{ - if (_line>sizeof(UBLOX_INIT)/16) return; - for (uint32_t i = 0; i < 16; i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line); -} - -void UBXTriggerTele(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } -} - - - -void UBXDetect(void) -{ - UBX.mode.init = 0; - if (PinUsed(GPIO_GPS_RX) && PinUsed(GPIO_GPS_TX)) { - UBXSerial = new TasmotaSerial(Pin(GPIO_GPS_RX), Pin(GPIO_GPS_TX), 1, 0, UBX_SERIAL_BUFFER_SIZE); - if (UBXSerial->begin(9600)) { - DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); - if (UBXSerial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); - } - } - } - else { - return; - } - - UBXinitCFG(); - UBX.mode.init = 1; - -#ifdef USE_FLOG - if (!Flog) { - Flog = new FLOG; - Flog->init(); - } -#endif - - UBX.state.log_interval = 10; - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - -uint32_t UBXprocessGPS() -{ - static uint32_t fpos = 0; - static char checksum[2]; - static uint8_t currentMsgType = MT_NONE; - static size_t payloadSize = sizeof(UBX.Message); - - - uint32_t data_bytes = 0; - while ( UBXSerial->available() ) { - data_bytes++; - byte c = UBXSerial->read(); - if (UBX.mode.runningVPort){ - UBX.TCPbuf[data_bytes-1] = c; - UBX.TCPbufSize = data_bytes; - } - if ( fpos < 2 ) { - - if ( c == UBX.UBX_HEADER[fpos] ) { - fpos++; - } else { - fpos = 0; - } - } else { - - - - - - if ( (fpos-2) < payloadSize ) { - ((char*)(&UBX.Message))[fpos-2] = c; - } - fpos++; - - if ( fpos == 4 ) { - - - if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { - currentMsgType = MT_NAV_POSLLH; - payloadSize = sizeof(UBX_t::NAV_POSLLH); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { - currentMsgType = MT_NAV_STATUS; - payloadSize = sizeof(UBX_t::NAV_STATUS); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { - currentMsgType = MT_NAV_TIME; - payloadSize = sizeof(UBX_t::NAV_TIME_UTC); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); - } - else { - - fpos = 0; - continue; - } - } - - if ( fpos == (payloadSize+2) ) { - - - UBXcalcChecksum(checksum, payloadSize); - } - else if ( fpos == (payloadSize+3) ) { - - - if ( c != checksum[0] ) { - - fpos = 0; - } - } - else if ( fpos == (payloadSize+4) ) { - - - fpos = 0; - if ( c == checksum[1] ) { - - return currentMsgType; - } - } - else if ( fpos > (payloadSize+4) ) { - - - fpos = 0; - } - } - } - - if (data_bytes!=0) { - UBX.state.non_empty_loops++; - DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); - } else { - UBX.state.non_empty_loops = 0; - } - return MT_NONE; -} - - - - - -#ifdef USE_FLOG -void UBXsendHeader(void) -{ - Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); - Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); - WSSend(200, CT_STREAM, F( - "\r\n" - "\r\n" - "\r\n\r\n")); -} - -void UBXsendRecord(uint8_t *buf) -{ - char record[100]; - char stime[32]; - UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; - snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); - char lat[12]; - char lon[12]; - dtostrfd((double)entry->lat/10000000.0f,7,lat); - dtostrfd((double)entry->lon/10000000.0f,7,lon); - snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); - - Webserver->sendContent_P(record); -} - -void UBXsendFooter(void) -{ - Webserver->sendContent(F("\n\n")); - Webserver->sendContent(""); - Rtc.user_time_entry = false; -} - - - -void UBXsendFile(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); -} -#endif - - - -void UBXSetRate(uint16_t interval) -{ - UBX.Message.cfgRate.cls = 0x06; - UBX.Message.cfgRate.id = 0x08; - UBX.Message.cfgRate.len = 6; - uint32_t measRate = (1000*(uint32_t)interval); - if (measRate > 0xffff) { - measRate = 0xffff; - } - UBX.Message.cfgRate.measRate = (uint16_t)measRate; - UBX.Message.cfgRate.navRate = 1; - UBX.Message.cfgRate.timeRef = 1; - UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); - DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); - UBXSerial->write(UBX.UBX_HEADER[0]); - UBXSerial->write(UBX.UBX_HEADER[1]); - for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); - DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); - } - UBX.state.log_interval = 10*interval; -} - -void UBXSelectMode(uint16_t mode) -{ - DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); - switch(mode){ -#ifdef USE_FLOG - case 0: - Flog->mode = 0; - break; - case 1: - Flog->mode = 1; - break; - case 2: - UBX.mode.filter_noise = true; - break; - case 3: - UBX.mode.filter_noise = false; - break; - case 4: - Flog->startRecording(true); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); - break; - case 5: - Flog->startRecording(false); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); - break; - case 6: - if(Flog->recording == true){ - Flog->stopRecording(); - } - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); - break; -#endif - case 7: - UBX.mode.send_when_new = 1; - break; - case 8: - UBX.mode.send_when_new = 0; - break; - case 9: - if (timeServer.beginListening()) { - UBX.mode.runningNTP = true; - } - break; - case 10: - UBX.mode.runningNTP = false; - UBXsendCFGLine(10); - UBXsendCFGLine(11); - break; - case 11: - UBX.mode.forceUTCupdate = true; - break; - case 12: - UBX.mode.forceUTCupdate = false; - break; - case 13: - Settings.latitude = UBX.rec_buffer.values.lat/10; - Settings.longitude = UBX.rec_buffer.values.lon/10; - break; - case 14: - vPortServer.begin(); - UBX.mode.runningVPort = 1; - break; - case 15: - - UBX.mode.runningVPort = 0; - break; - default: - if (mode>1000 && mode <1066) { - UBXSetRate(mode-1000); - } - break; - } - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - - - -bool UBXHandlePOSLLH() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); - if (UBX.state.gpsFix>1) { - if (UBX.mode.filter_noise) { - if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { - if(UBX.mode.runningVPort) return; - UBXinitCFG(); - AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); - UBXSerial->flush(); - UBX.state.non_empty_loops = 0; - } -} - - - -void UBXLoop50msec(void) -{ - - if (UBX.mode.runningVPort){ - if(!vPortClient.connected()) { - vPortClient = vPortServer.available(); - } - while(vPortClient.available()) { - byte _newByte = vPortClient.read(); - UBXSerial->write(_newByte); - } - - if (UBX.TCPbufSize!=0){ - vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); - UBX.TCPbufSize = 0; - } - } - - if(UBX.mode.runningNTP){ - timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET); - } -} - -void UBXLoop(void) -{ - static uint16_t counter; - static bool new_position; - - uint32_t msgType = UBXprocessGPS(); - - switch(msgType){ - case MT_NAV_POSLLH: - new_position = UBXHandlePOSLLH(); - break; - case MT_NAV_STATUS: - UBXHandleSTATUS(); - break; - case MT_NAV_TIME: - UBXHandleTIME(); - break; - default: - UBXHandleOther(); - break; - } - -#ifdef USE_FLOG - if (counter>UBX.state.log_interval) { - if (Flog->recording && new_position) { - UBX.rec_buffer.values.time = Rtc.local_time; - Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); - counter = 0; - } - } -#endif - - counter++; -} - - - - -#ifdef USE_WEBSERVER - - -#ifdef USE_FLOG -#ifdef DEBUG_TASMOTA_SENSOR - const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" - "{s} FLOG next sector for REC: {m} %u {e}" - "{s} %u sector(s) with data at sector: {m} %u {e}"; - const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; -#endif - - const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; - const char kFLOG_STATE0[] PROGMEM = "ready"; - const char kFLOG_STATE1[] PROGMEM = "recording"; - const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; - - const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; - -#endif - const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; - - const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" - "{s} GPS longitude {m}%s{e}" - "{s} GPS altitude {m}%s m{e}" - "{s} GPS hor. Accuracy {m}%s m{e}" - "{s} GPS vert. Accuracy {m}%s m{e}" - "{s} GPS sat-fix status {m}%s{e}"; - - const char kGPSFix0[] PROGMEM = "no fix"; - const char kGPSFix1[] PROGMEM = "dead reckoning only"; - const char kGPSFix2[] PROGMEM = "2D-fix"; - const char kGPSFix3[] PROGMEM = "3D-fix"; - const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; - const char kGPSFix5[] PROGMEM = "Time only fix"; - const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; - - - - -#endif - - - -void UBXShow(bool json) -{ - char lat[12]; - char lon[12]; - char alt[12]; - char hAcc[12]; - char vAcc[12]; - dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); - dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); - dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); - dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); - dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - - if (json) { - ResponseAppend_P(PSTR(",\"GPS\":{")); - if (UBX.mode.send_UI_only) { - uint32_t i = UBX.state.log_interval / 10; - ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); - } else { - ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); - } -#ifdef USE_FLOG - ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); -#endif - UBX.mode.send_UI_only = false; -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); - -#ifdef DEBUG_TASMOTA_SENSOR -#ifdef USE_FLOG - WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); - if (Flog->recording) { - WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); - } -#endif -#endif -#ifdef USE_FLOG - if (Flog->ready) { - WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); - } - if (!Flog->recording && Flog->found_saved_data) { - WSContentSend_P(HTTP_BTN_FLOG_DL); - } -#endif - if (UBX.mode.runningNTP) { - WSContentSend_P(HTTP_SNS_NTPSERVER); - } -#endif - } -} - - - - - -bool UBXCmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } - return serviced; -} - - - - - -bool Xsns60(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - UBXDetect(); - } - - if (UBX.mode.init) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_60 == XdrvMailbox.index) { - result = UBXCmd(); - } - break; - case FUNC_EVERY_50_MSECOND: - UBXLoop50msec(); - break; - case FUNC_EVERY_100_MSECOND: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXLoop(); - } - break; -#ifdef USE_FLOG - case FUNC_WEB_ADD_HANDLER: - WebServer_on(PSTR("/UBX"), UBXsendFile); - break; -#endif - case FUNC_JSON_APPEND: - UBXShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXShow(0); - } - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -# 55 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 -#ifdef USE_MIBLE - -#ifdef DEBUG_TASMOTA_SENSOR - #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); -#else - #define MINRF_LOG_BUFFER(x) -#endif - -#define USE_MI_DECRYPTION - - - - - - - -#define XSNS_61 61 - -#include -#ifdef USE_MI_DECRYPTION -#include -#endif - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03 4 -#define CGG1 5 -#define CGD1 6 -#define NLIGHT 7 -#define MJYD2S 8 -#define YEERC 9 -#define MHOC401 10 -#define MHOC303 11 -#define ATC 12 - -#define MI_TYPES 12 - -#define D_CMND_NRF "NRF" - -const char S_JSON_NRF_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NRF "%s\":%d}"; -const char S_JSON_NRF_COMMAND[] PROGMEM = "{\"" D_CMND_NRF "%s\":\"%s\"}"; -const char kNRF_Commands[] PROGMEM = "Ignore|Use|Page|Scan|Beacon|Chan|Nlight" -#ifdef USE_MI_DECRYPTION - "|Mjyd2s" - "|Key" -#endif - ; - -enum NRF_Commands { - CMND_NRF_IGNORE, - CMND_NRF_USE, - CMND_NRF_PAGE, - CMND_NRF_SCAN, - CMND_NRF_BEACON, - CMND_NRF_CHAN, - CMND_NRF_NLIGHT -#ifdef USE_MI_DECRYPTION - , CMND_NRF_MJYD2S - , CMND_NRF_KEY -#endif - }; - -const uint16_t kMINRFDeviceID[MI_TYPES]={ 0x0098, - 0x01aa, - 0x045b, - 0x055b, - 0x0347, - 0x0576, - 0x03dd, - 0x07f6, - 0x0153, - 0x0387, - 0x06d3, - 0x0a1c - }; - -const char kMINRFDeviceType1[] PROGMEM = "Flora"; -const char kMINRFDeviceType2[] PROGMEM = "MJ_HT_V1"; -const char kMINRFDeviceType3[] PROGMEM = "LYWSD02"; -const char kMINRFDeviceType4[] PROGMEM = "LYWSD03"; -const char kMINRFDeviceType5[] PROGMEM = "CGG1"; -const char kMINRFDeviceType6[] PROGMEM = "CGD1"; -const char kMINRFDeviceType7[] PROGMEM = "NLIGHT"; -const char kMINRFDeviceType8[] PROGMEM = "MJYD2S"; -const char kMINRFDeviceType9[] PROGMEM = "YEERC"; -const char kMINRFDeviceType10[] PROGMEM = "MHOC401"; -const char kMINRFDeviceType11[] PROGMEM = "MHOC303"; -const char kMINRFDeviceType12[] PROGMEM = "ATC"; -const char * kMINRFDeviceType[] PROGMEM = {kMINRFDeviceType1,kMINRFDeviceType2,kMINRFDeviceType3,kMINRFDeviceType4,kMINRFDeviceType5,kMINRFDeviceType6,kMINRFDeviceType7,kMINRFDeviceType8,kMINRFDeviceType9,kMINRFDeviceType10,kMINRFDeviceType11,kMINRFDeviceType12}; - - -const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; -const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; -const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46}; -const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0x33049deb}; - -const uint32_t kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; -const uint32_t kMINRFCGDPDU[3] = {0x5da0d752,0xc10c16e7,0x29c497c1}; - -const uint32_t kMINRFYRCPDU[3] = {0x216D63E2,0x5C3DD47E,0x0A5D0E96}; -const uint32_t kMINRFATCPDU[3] = {0xA6E4D00A,0xD0CDAD5A,0x8B03FB3A}; - - -const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; -const uint8_t kMINRFlsfrList_C[3] = {0x38,0x25,0x2e}; -const uint8_t kMINRFlsfrList_D[3] = {0x26,0x23,0x20}; - - -#pragma pack(1) -struct mi_beacon_t{ - uint16_t PID; - uint8_t counter; - uint8_t MAC[6]; - uint8_t spare; - uint8_t type; - uint8_t ten; - uint8_t size; - union { - struct{ - int16_t temp; - uint16_t hum; - }HT; - uint8_t bat; - uint16_t temp; - uint16_t hum; - uint32_t lux:24; - uint8_t moist; - uint16_t fert; - struct{ - uint16_t num; - uint8_t longPress; - }Btn; - }; -}; - -struct CGDPacket_t { - uint8_t MAC[6]; - uint16_t mode; - union { - struct { - int16_t temp; - uint16_t hum; - }; - uint8_t bat; - }; -}; - -struct bleAdvPacket_t { - uint8_t pduType; - uint8_t payloadSize; - uint8_t MAC[6]; -}; - -#ifdef USE_MI_DECRYPTION -struct encPayload_t { - uint8_t cipher[5]; - uint8_t ExtCnt[3]; - uint8_t tag[4]; -}; - -struct encPacket_t{ - - uint16_t PID; - uint8_t frameCnt; - uint8_t MAC[6]; - encPayload_t payload; -}; - -struct mjysd02_Packet_t{ - uint8_t padding[11]; - uint8_t payloadSize; - uint8_t padding3; - uint16_t UUID; - uint16_t frameCtrl; - uint16_t PID; - uint8_t frameCnt; - uint8_t data[18]; -}; - -struct ATCPacket_t{ - uint8_t MAC[6]; - int16_t temp; - uint8_t hum; - uint8_t batPer; - uint16_t batMV; - uint8_t frameCnt; -}; - -union mi_bindKey_t{ - struct{ - uint8_t key[16]; - uint8_t MAC[6]; - }; - uint8_t buf[22]; -}; -#endif -union FIFO_t{ - bleAdvPacket_t bleAdv; - mi_beacon_t miBeacon; - CGDPacket_t CGDPacket; - uint8_t raw[32]; -}; - -#pragma pack(0) - -struct { - const uint8_t channel[3] = {37,38,39}; - const uint8_t frequency[3] = { 2,26,80}; - - uint16_t timer; - uint16_t ignore = 0; - uint8_t currentChan=0; - uint8_t channelIgnore = 0; - uint8_t confirmedSensors = 0; - uint8_t packetMode; - uint8_t perPage = 4; - uint8_t firstUsedPacketMode = 1; - uint8_t activeLight = 0; - - FIFO_t buffer; - - struct { - uint8_t MAC[6]; - uint32_t time; - uint32_t PDU[3]; - bool active = false; - } beacon; - - struct { - uint32_t allwaysAggregate:1; - - uint32_t noSummary:1; - uint32_t minimalSummary:1; - uint32_t directBridgeMode:1; - } option; - - struct { - uint32_t shallTriggerTele:1; - uint32_t triggeredTele:1; - uint32_t activeScan:1; - uint32_t stopScan:1; - - } mode; - - - - - -#ifdef DEBUG_TASMOTA_SENSOR - uint8_t streamBuffer[sizeof(buffer)]; - uint8_t lsfrBuffer[sizeof(buffer)]; -#endif -} MINRF; - -struct mi_sensor_t{ - uint8_t type; - uint8_t lastCnt; - uint8_t shallSendMQTT; - uint8_t showedUp; - uint8_t MAC[6]; - - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t PIR:1; - uint32_t Btn:1; - }; - uint32_t raw; - } feature; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t motion:1; - uint32_t noMotion:1; - uint32_t Btn:1; - }; - uint32_t raw; - } eventType; - - uint32_t lastTime; - uint32_t lux; - float temp; - union { - struct { - uint8_t moisture; - uint16_t fertility; - }; - struct { - float hum; - }; - struct { - uint16_t events; - uint32_t NMT; - }; - uint16_t Btn; - }; - union { - uint8_t bat; - }; -}; - -struct mi_light_t{ - uint8_t MAC[6]; - uint32_t PDU[3]; - uint8_t type; - uint8_t bat; - struct { - uint16_t events; - uint8_t lastCnt; - uint8_t shallSendMQTT; - }; - uint32_t NMT; - uint32_t lastTime; - uint8_t lux; - uint8_t eventType; -}; - -struct scan_entry_t { - uint8_t MAC[6]; - uint16_t cid; - uint16_t svc; - uint16_t uuid; - uint8_t showedUp; -}; - -std::vector MIBLEsensors; -std::vector MINRFscanResult; -#ifdef USE_MI_DECRYPTION -std::vector MIBLEbindKeys; -#endif -std::vector MIBLElights; - -static union{ - scan_entry_t MINRFdummyEntry; - uint8_t MINRFtempBuf[23]; -}; - - - -void MINRFinit(void){ - MINRFinitBLE(1); - - MINRF.option.allwaysAggregate = 1; - - MINRF.option.noSummary = 0; - MINRF.option.minimalSummary = 0; - MINRF.option.directBridgeMode = 0; -} -# 431 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -bool MINRFinitBLE(uint8_t _mode) -{ - if (MINRF.timer%1000 == 0){ - NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); - NRF24radio.setAutoAck(false); - NRF24radio.setDataRate(RF24_1MBPS); - NRF24radio.disableCRC(); - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); - NRF24radio.setRetries(0,0); - NRF24radio.setPALevel(RF24_PA_MIN); - NRF24radio.setAddressWidth(4); - - - NRF24radio.powerUp(); - } - if(NRF24radio.isChipConnected()){ - - MINRFchangePacketModeTo(_mode); - return true; - } - - return false; -} - - - - - -void MINRFhopChannel() -{ - for (uint32_t i = 0; i<3;i++){ - MINRF.currentChan++; - if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue; - if(MINRF.currentChan >= sizeof(MINRF.channel)) { - MINRF.currentChan = 0; - if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue; - } - break; - } - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); -} - - - - - - - -bool MINRFreceivePacket(void) -{ - if(!NRF24radio.available()) { - return false; - } - while(NRF24radio.available()) { - - - NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); -#ifdef DEBUG_TASMOTA_SENSOR - memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); -#endif - MINRFswapbuf((uint8_t*)&MINRF.buffer, sizeof(MINRF.buffer) ); - - - - switch (MINRF.packetMode) { - case 0: case NLIGHT: case MJYD2S: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); - break; - case FLORA: case LYWSD02: case MHOC303: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); - break; - case MJ_HT_V1: case LYWSD03: case CGG1: case CGD1: case MHOC401: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - case YEERC: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_C[MINRF.currentChan]); - break; - case ATC: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_D[MINRF.currentChan]); - break; - } - - - } - - return true; -} - - -void MINRFshowBuffer(uint8_t (&buf)[32]){ - - - - - DEBUG_SENSOR_LOG(PSTR("NRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x ") - ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], - buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], - buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] - ); -} - - - - - - - -void MINRFswapbuf(uint8_t *buf, uint8_t len) -{ - - while(len--) { - uint8_t a = *buf; - uint8_t v = 0; - if (a & 0x80) v |= 0x01; - if (a & 0x40) v |= 0x02; - if (a & 0x20) v |= 0x04; - if (a & 0x10) v |= 0x08; - if (a & 0x08) v |= 0x10; - if (a & 0x04) v |= 0x20; - if (a & 0x02) v |= 0x40; - if (a & 0x01) v |= 0x80; - *(buf++) = v; - } -} -# 566 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) -{ - while(len--) { - uint8_t res = 0; - - for (uint8_t i = 1; i; i <<= 1) { - if (lfsr & 0x01) { - lfsr ^= 0x88; - res |= i; - } - lfsr >>= 1; - } - *(buf++) ^= res; -#ifdef DEBUG_TASMOTA_SENSOR - MINRF.lsfrBuffer[31-len] = lfsr; -#endif - } -} - - - - -bool MINRFhandleBeacon(scan_entry_t * entry, uint32_t offset); - - - - - -void MINRFhandleScan(void){ - if(MINRFscanResult.size()>20 || MINRF.mode.stopScan) { - MINRF.mode.activeScan=false; - MINRFcomputefirstUsedPacketMode(); - uint32_t i = 0; - MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(), - MINRFscanResult.end(), - [&i](scan_entry_t e) { - if(e.showedUp>2) AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF: Beacon %02u: %02X%02X%02X%02X%02X%02X Cid: %04X Svc: %04X UUID: %04X"),i,e.MAC[0],e.MAC[1],e.MAC[2],e.MAC[3],e.MAC[4],e.MAC[5],e.cid,e.svc,e.uuid); - i++; - return ((e.showedUp < 3)); - }), - MINRFscanResult.end()); - MINRF.mode.stopScan=false; - return; - } - - MINRFreverseMAC(MINRF.buffer.bleAdv.MAC); - for(uint32_t i=0; i30) break; - uint32_t ADtype = _buf[i+1]; - - if (size+i>32+offset) size=32-i+offset-2; - if (size>30) break; - char _stemp[(size*2)]; - uint32_t backupSize; - switch(ADtype){ - case 0x01: - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Flags: %02x"), _buf[i+2]); - break; - case 0x02: case 0x03: - entry->uuid = _buf[i+3]*256 + _buf[i+2]; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: UUID: %04x"), entry->uuid); - success = true; - break; - case 0x08: case 0x09: - backupSize = _buf[i+size+1]; - _buf[i+size+1] = 0; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Name: %s"), (char*)&_buf[i+2]); - success = true; - _buf[i+size+1] = backupSize; - break; - case 0x0a: - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: TxPow: %02u"), _buf[i+2]); - break; - case 0xff: - entry->cid = _buf[i+3]*256 + _buf[i+2]; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Cid: %04x"), entry->cid); - ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2)); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); - success = true; - break; - case 0x16: - entry->svc = _buf[i+3]*256 + _buf[i+2]; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Svc: %04x"), entry->svc); - ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2)); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); - success = true; - break; - default: - ToHex_P((unsigned char*)&_buf+i+2,size-1,_stemp,(size*2)); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp); - } - i+=size; - } - MINRF.beacon.time = 0; - } - return success; -} - - - - - -void MINRFbeaconCounter(void) { - if (MINRF.beacon.active) { - MINRF.beacon.time++; - - - - - - - Response_P(PSTR("{%s:{\"Beacon\":%u}}"), D_CMND_NRF, MINRF.beacon.time); - XdrvRulesProcess(); - } -} - - - - - -void MINRFcomputeBeaconPDU(uint8_t (&_MAC)[6], uint32_t (&PDU)[3], uint32_t offset){ - uint32_t _PDU[3]; - for (uint32_t i = 0; i<3; i++){ - bleAdvPacket_t packet; - memcpy((uint8_t *)&packet.MAC, (uint8_t *)&_MAC, sizeof(packet.MAC)); - MINRFreverseMAC(packet.MAC); - MINRFwhiten((uint8_t *)&packet, sizeof(packet), MINRF.channel[i] | 0x40); - MINRFswapbuf((uint8_t*)&packet,sizeof(packet)); - uint32_t pdu = packet.MAC[0+offset]<<24 | packet.MAC[1+offset]<<16 | packet.MAC[2+offset]<<8 | packet.MAC[3+offset]; - _PDU[i] = pdu; - } - memcpy(PDU,_PDU,sizeof(_PDU)); -} - -#ifdef USE_MI_DECRYPTION -int MINRFdecryptPacket(char *_buf){ - encPacket_t *packet = (encPacket_t*)_buf; - - - - - int ret = 0; - unsigned char output[16] = {0}; - uint8_t nonce[12]; - const unsigned char authData[1] = {0x11}; - - - for (uint32_t i = 0; i<6; i++){ - nonce[i] = packet->MAC[5-i]; - } - memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); - nonce[8] = packet->frameCnt; - memcpy((uint8_t*)&nonce+9,(uint8_t*)&packet->payload.ExtCnt,3); - - uint8_t _bindkey[16] = {0x0}; - for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ - - memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); - break; - } - - - - - } - - memcpy(output,packet->payload.cipher, sizeof(packet->payload.cipher)); - - br_aes_small_ctrcbc_keys keyCtx; - br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); - - br_ccm_context ctx; - br_ccm_init(&ctx, &keyCtx.vtable); - br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData),sizeof(packet->payload.cipher),sizeof(packet->payload.tag)); - br_ccm_aad_inject(&ctx, authData, sizeof(authData)); - br_ccm_flip(&ctx); - br_ccm_run(&ctx, 0, output, sizeof(packet->payload.cipher)); - - ret = br_ccm_check_tag(&ctx, packet->payload.tag); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, output[0],output[1],output[2],output[3],output[4]); - memcpy((uint8_t*)(packet->payload.cipher)+1,output,sizeof(packet->payload.cipher)); - return ret; -} - -int MINRFdecryptMJYD2SPacket(char *_buf, uint8_t _light, char* _output){ - int ret = 0; - uint8_t nonce[12]; - const unsigned char authData[1] = {0x11}; - uint8_t tag[4]; - mjysd02_Packet_t *packet = (mjysd02_Packet_t*)_buf; - - - for (uint32_t i = 0; i<6; i++){ - nonce[i] = MIBLElights[_light-1].MAC[5-i]; - } - memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); - nonce[8] = packet->frameCnt; - memcpy((uint8_t*)&nonce+9,(uint8_t*)&packet->padding[0] + packet->payloadSize + 5, 3); - - - uint8_t _bindkey[16]; - for(uint32_t i=0; ipayloadSize){ - case 22: - _size = 7; - _offset = 2; - _tagSize = 4; - break; - case 25: - _size = packet->payloadSize - 21; - _offset = -1; - _tagSize = 4; - break; - case 27: - _size = packet->payloadSize - 21; - _offset = 1; - _tagSize = 3; - break; - default: - return 0; - break; - } - - memcpy(_output,(uint8_t*)&packet->padding[0] + packet->payloadSize - _offset, _size); - - - br_aes_small_ctrcbc_keys keyCtx; - br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); - - br_ccm_context ctx; - br_ccm_init(&ctx, &keyCtx.vtable); - br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData),_size,4); - br_ccm_aad_inject(&ctx, authData, sizeof(authData)); - br_ccm_flip(&ctx); - br_ccm_run(&ctx, 0, _output, _size); - - - br_ccm_get_tag(&ctx, tag); - ret = memcmp(tag,(uint8_t*)&packet->padding[0] + packet->payloadSize + 8, _tagSize); - return ret; -} -#endif -# 891 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -void MINRFreverseMAC(uint8_t _MAC[]){ - uint8_t _reversedMAC[6]; - for (uint8_t i=0; i<6; i++){ - _reversedMAC[5-i] = _MAC[i]; - } - memcpy(_MAC,_reversedMAC, sizeof(_reversedMAC)); -} -#ifdef USE_MI_DECRYPTION -void MINRFAddKey(char* payload){ - mi_bindKey_t keyMAC; - memset(keyMAC.buf,0,sizeof(keyMAC)); - MINRFKeyMACStringToBytes(payload,keyMAC.buf); - bool unknownKey = true; - for(uint32_t i=0; i= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _keyMAC[(index/2)] += value << (((index + 1) % 2) * 4); - index++; - } - DEBUG_SENSOR_LOG(PSTR("NRF: %s to:"),_string); - DEBUG_SENSOR_LOG(PSTR("NRF: key-array: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"),_keyMAC[0],_keyMAC[1],_keyMAC[2],_keyMAC[3],_keyMAC[4],_keyMAC[5],_keyMAC[6],_keyMAC[7],_keyMAC[8],_keyMAC[9],_keyMAC[10],_keyMAC[11],_keyMAC[12],_keyMAC[13],_keyMAC[14],_keyMAC[15]); - DEBUG_SENSOR_LOG(PSTR("NRF: MAC-array: %02X%02X%02X%02X%02X%02X"),_keyMAC[16],_keyMAC[17],_keyMAC[18],_keyMAC[19],_keyMAC[20],_keyMAC[21]); -} -#endif - - - - - - -void MINRFMACStringToBytes(char* _string, uint8_t _MAC[]) { - uint32_t index = 0; - UpperCase(_string,_string); - while (index < 12) { - char c = _string[index]; - uint8_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _MAC[(index/2)] += value << (((index + 1) % 2) * 4); - index++; - } - -} - - - - - -void MINRFcomputefirstUsedPacketMode(void){ - for (uint32_t i = 0; iMI_TYPES) MINRF.firstUsedPacketMode=0; - break; - } - } -} -# 985 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -void MINRFrecalcBuffer(uint8_t *_buf, uint32_t offset){ - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); - MINRFswapbuf((uint8_t*)&MINRF.buffer,sizeof(MINRF.buffer)); - memcpy(_buf+offset,MINRF.buffer.raw,32); - MINRFswapbuf(_buf,32+offset); - MINRFwhiten(_buf, 32+offset, MINRF.channel[MINRF.currentChan] | 0x40); -} - - - - - - -void MINRFchangePacketModeTo(uint8_t _mode) { - uint32_t (_nextchannel) = MINRF.currentChan+1; - if (_nextchannel>2) _nextchannel=0; - - switch(_mode){ - case 0: - NRF24radio.openReadingPipe(0,0x6B7D9171); - break; - case FLORA: - NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); - break; - case MJ_HT_V1: - NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); - break; - case LYWSD02: case MHOC303: - NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); - break; - case LYWSD03: case MHOC401: - NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); - break; - case CGG1: - NRF24radio.openReadingPipe(0,kMINRFCGGPDU[_nextchannel]); - break; - case CGD1: - NRF24radio.openReadingPipe(0,kMINRFCGDPDU[_nextchannel]); - break; - case NLIGHT: case MJYD2S: - if (MIBLElights.size()==0) break; - NRF24radio.openReadingPipe(0,MIBLElights[MINRF.activeLight].PDU[_nextchannel]); - MINRF.activeLight++; - break; - case YEERC: - NRF24radio.openReadingPipe(0,kMINRFYRCPDU[_nextchannel]); - break; - case ATC: - NRF24radio.openReadingPipe(0,kMINRFATCPDU[_nextchannel]); - break; - } - - MINRF.packetMode = _mode; -} -# 1047 "/workspace/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -uint32_t MINRFgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type){ - - DEBUG_SENSOR_LOG(PSTR("NRF: will test ID-type: %x"), _type); - bool _success = false; - for (uint32_t i=0;i 2){ - MINRF.confirmedSensors++; - } - } -} - - - - - -void MINRFtriggerTele(void){ - MINRF.mode.triggeredTele= true; - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - #ifdef USE_RULES - RulesTeleperiod(); - #endif - } -} - - - - - -void MINRFhandleMiBeaconPacket(void){ - MINRFreverseMAC(MINRF.buffer.miBeacon.MAC); - uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.MAC, MINRF.buffer.miBeacon.PID); - if(_slot==0xff) return; - DEBUG_SENSOR_LOG(PSTR("NRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size()); - mi_sensor_t *_sensorVec = &MIBLEsensors[_slot]; - DEBUG_SENSOR_LOG(PSTR("NRF: %u %u %u"),_slot,_sensorVec->type,MINRF.buffer.miBeacon.type); - float _tempFloat; - int decryptRet; - - switch(_sensorVec->type){ - case MJ_HT_V1: case CGG1: case YEERC: - memcpy(MINRFtempBuf,(uint8_t*)&MINRF.buffer.miBeacon.spare, 32-9); - memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); - break; -#ifdef USE_MI_DECRYPTION - case LYWSD03: case MHOC401: - decryptRet = MINRFdecryptPacket((char*)&MINRF.buffer); - if(decryptRet==1) _sensorVec->showedUp=255; - break; -#endif - } - - DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kNRFSlaveType[_sensorVec->type-1],_slot); - switch(MINRF.buffer.miBeacon.type){ - case 0x1: - if(MINRF.buffer.miBeacon.counter==_sensorVec->lastCnt) break; - - _sensorVec->lastCnt=MINRF.buffer.miBeacon.counter; - _sensorVec->Btn=MINRF.buffer.miBeacon.Btn.num + (MINRF.buffer.miBeacon.Btn.longPress/2)*6; - _sensorVec->eventType.Btn = 1; - break; - case 0x04: - _tempFloat=(float)(MINRF.buffer.miBeacon.temp)/10.0f; - if(_tempFloat<60){ - _sensorVec->temp=_tempFloat; - _sensorVec->eventType.temp = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); - } - DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), MINRF.buffer.miBeacon.temp ); - break; - case 0x06: - _tempFloat=(float)(MINRF.buffer.miBeacon.hum)/10.0f; - if(_tempFloat<101){ - _sensorVec->hum=_tempFloat; - _sensorVec->eventType.hum = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); - } - DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), MINRF.buffer.miBeacon.hum); - break; - case 0x07: - _sensorVec->lux=MINRF.buffer.miBeacon.lux & 0x00ffffff; - _sensorVec->eventType.lux = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), MINRF.buffer.miBeacon.lux & 0x00ffffff); - break; - case 0x08: - _tempFloat =(float)MINRF.buffer.miBeacon.moist; - if(_tempFloat<100){ - _sensorVec->moisture=_tempFloat; - _sensorVec->eventType.moist = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); - } - DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), MINRF.buffer.miBeacon.moist); - break; - case 0x09: - _tempFloat=(float)(MINRF.buffer.miBeacon.fert); - if(_tempFloat<65535){ - _sensorVec->fertility=_tempFloat; - _sensorVec->eventType.fert = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); - } - DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), MINRF.buffer.miBeacon.fert); - break; - case 0x0a: - if(MINRF.buffer.miBeacon.bat<101){ - _sensorVec->bat = MINRF.buffer.miBeacon.bat; - _sensorVec->eventType.bat = 1; - DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - } - DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), MINRF.buffer.miBeacon.bat); - break; - case 0x0d: - _tempFloat=(float)(MINRF.buffer.miBeacon.HT.temp)/10.0f; - if(_tempFloat<60){ - _sensorVec->temp = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); - } - _tempFloat=(float)(MINRF.buffer.miBeacon.HT.hum)/10.0f; - if(_tempFloat<100){ - _sensorVec->hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); - } - _sensorVec->eventType.tempHum = 1; - DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), MINRF.buffer.miBeacon.HT.temp, MINRF.buffer.miBeacon.HT.hum); - break; - } - if(MIBLEsensors[_slot].eventType.raw == 0) return; - MIBLEsensors[_slot].shallSendMQTT = 1; - if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; -} - - - - - -void MINRFhandleCGD1Packet(void){ - MINRFreverseMAC(MINRF.buffer.CGDPacket.MAC); - uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.CGDPacket.MAC, 0x0576); - DEBUG_SENSOR_LOG(PSTR("NRF: Sensor slot: %u"), _slot); - if(_slot==0xff) return; - - switch (MINRF.buffer.CGDPacket.mode){ - case 0x0401: - float _tempFloat; - _tempFloat=(float)(MINRF.buffer.CGDPacket.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); - } - _tempFloat=(float)(MINRF.buffer.CGDPacket.hum)/10.0f; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); - } - DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), MINRF.buffer.CGDPacket.temp, MINRF.buffer.CGDPacket.hum); - MIBLEsensors[_slot].eventType.tempHum = 1; - break; - case 0x0102: - if(MINRF.buffer.CGDPacket.bat<101){ - MIBLEsensors[_slot].bat = MINRF.buffer.CGDPacket.bat; - DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - } - MIBLEsensors[_slot].eventType.bat = 1; - break; - default: - DEBUG_SENSOR_LOG(PSTR("NRF: unexpected CGD1-packet")); - MINRF_LOG_BUFFER(MINRF.buffer.raw); - } - if(MIBLEsensors[_slot].eventType.raw == 0) return; - MIBLEsensors[_slot].shallSendMQTT = 1; - if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; -} - -void MINRFhandleNlightPacket(void){ - uint32_t offset = 6; - uint8_t _buf[32+offset]; - MINRFrecalcBuffer((uint8_t*)&_buf,offset); - - uint32_t _frame_PID = _buf[15]<<24 | _buf[16]<<16 | _buf[17]<<8 | _buf[18]; - if(_frame_PID!=0x4030dd03) return; - - uint32_t _idx = MINRF.activeLight-1; - if((millis() - MIBLElights[_idx].lastTime)<1500) return; - if(_buf[19]!=MIBLElights[_idx].lastCnt){ - MIBLElights[_idx].lastCnt = _buf[19]; - MIBLElights[_idx].events++; - MIBLElights[_idx].shallSendMQTT = 1; - MIBLElights[_idx].lastTime = millis(); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: NLIGHT %u: events: %u, Cnt:%u"), _idx,MIBLElights[_idx].events, MIBLElights[_idx].lastCnt); - } -} - -void MINRFhandleMJYD2SPacket(void){ - uint32_t offset = 8; - uint8_t _buf[32+offset]; - MINRFrecalcBuffer((uint8_t*)&_buf,offset); - mjysd02_Packet_t *_packet = (mjysd02_Packet_t*)&_buf; - if(_packet->PID!=0x07f6) return; - - - uint32_t _idx = MINRF.activeLight-1; - switch(_packet->frameCtrl){ - case 0x5910: - if(_packet->frameCnt!=MIBLElights[_idx].lastCnt){ - - MIBLElights[_idx].lastCnt = _packet->frameCnt; - if(millis()-MIBLElights[_idx].lastTime>120000){ - MIBLElights[_idx].eventType = 1; - MIBLElights[_idx].events++; - MIBLElights[_idx].shallSendMQTT = 1; - MIBLElights[_idx].lastTime = millis(); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: MJYD2S secondary PIR")); - } - } - break; - case 0x5948: case 0x5958: - uint8_t output[16]; - if(_packet->frameCnt==MIBLElights[_idx].lastCnt) break; - int32_t ret = MINRFdecryptMJYD2SPacket((char*)&_buf, MINRF.activeLight,(char*)&output); - if(ret==0){ - MIBLElights[_idx].lastCnt = _packet->frameCnt; - switch(output[0]){ - case 0x0f: - if(output[1] == 0){ - if(millis()-MIBLElights[_idx].lastTime>1000){ - MIBLElights[_idx].eventType = 1; - MIBLElights[_idx].shallSendMQTT = 1; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("NRF: MJYD2S primary PIR")); - MIBLElights[_idx].events++; - } - MIBLElights[_idx].lastTime = millis(); - MIBLElights[_idx].lux = output[3]; - } - break; - case 0x07: - if(output[1] == 0x10){ - MIBLElights[_idx].eventType = 2; - MIBLElights[_idx].lux = output[3]; - MIBLElights[_idx].shallSendMQTT = 1; - } - break; - case 0x0a: - MIBLElights[_idx].bat = output[3]; - break; - case 0x17: - MIBLElights[_idx].NMT = output[6]<<24 | output[5]<<16 | output[4]<<8 | output[3]; - MIBLElights[_idx].eventType = 3; - MIBLElights[_idx].shallSendMQTT = 1; - - break; - } - } - } - -} - - -void MINRFhandleLightPacket(void){ - switch(MIBLElights[MINRF.activeLight-1].type){ - case NLIGHT: - - MINRFhandleNlightPacket(); - break; - case MJYD2S: - - MINRFhandleMJYD2SPacket(); - break; - } - if(MIBLElights[MINRF.activeLight-1].shallSendMQTT==1) MINRFtriggerTele(); -} - -void MINRFaddLight(uint8_t _MAC[], uint8_t _type){ - for(uint32_t i=0; iMAC, 0x0a1c); - - - if(_slot==0xff) return; - - MIBLEsensors[_slot].temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; - MIBLEsensors[_slot].hum = (float)_packet->hum; - MIBLEsensors[_slot].bat = _packet->batPer; - MIBLEsensors[_slot].eventType.tempHum = 1; - MIBLEsensors[_slot].eventType.bat = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - if (MINRF.option.directBridgeMode) MINRF.mode.shallTriggerTele = 1; -} - - - - - -void MINRF_EVERY_50_MSECOND() { - - if(MINRF.timer>6000){ - DEBUG_SENSOR_LOG(PSTR("NRF: check for FAKE sensors")); - MINRFpurgeFakeSensors(); - MINRF.timer=0; - } - MINRF.timer++; - - if (!MINRFreceivePacket()){ - if(MINRF.mode.shallTriggerTele){ - MINRFtriggerTele(); - MINRF.mode.shallTriggerTele = 0; - } - - - } - - else { - switch (MINRF.packetMode) { - case 0: - if (MINRF.beacon.active){ - MINRFhandleBeacon(&MINRFdummyEntry,6); - } - else MINRFhandleScan(); - break; - case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03: case YEERC: case MHOC401: case MHOC303: - MINRFhandleMiBeaconPacket(); - break; - case CGD1: - MINRFhandleCGD1Packet(); - break; - case NLIGHT: - MINRFhandleLightPacket(); - break; - case ATC: - MINRFhandleATCPacket(); - break; - default: - break; - } - } - if (MINRF.beacon.active || MINRF.mode.activeScan) { - MINRF.firstUsedPacketMode=0; - } - - if(MINRF.packetMode==NLIGHT){ - if(MINRF.activeLight+1>MIBLElights.size()){ - MINRF.activeLight=0; - MINRF.packetMode+=2; - } - else MINRF.packetMode+=2; - } - else{ - MINRF.packetMode = (MINRF.packetMode+1>MI_TYPES) ? MINRF.firstUsedPacketMode : MINRF.packetMode+1; - for (uint32_t i = MINRF.packetMode; i 0) { - if (XdrvMailbox.payload == 0) XdrvMailbox.payload = MINRF.perPage; - MINRF.perPage = XdrvMailbox.payload; - } - else XdrvMailbox.payload = MINRF.perPage; - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_NRF_IGNORE: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload == 0){ - MINRF.ignore = 0; - MINRF.firstUsedPacketMode = 1; - } - else if (XdrvMailbox.payload < MI_TYPES+1) { - bitSet(MINRF.ignore,XdrvMailbox.payload); - MINRFcomputefirstUsedPacketMode(); - MINRF.timer = 5900; - Response_P(S_JSON_NRF_COMMAND, command, kMINRFDeviceType[XdrvMailbox.payload-1]); - } - else if (XdrvMailbox.payload == 65535) { - MINRF.ignore = 65535; - } - } - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.ignore); - break; - case CMND_NRF_USE: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload == 0){ - MINRF.ignore = 65535; - MINRF.firstUsedPacketMode = 1; - } - else if (XdrvMailbox.payload < MI_TYPES+1) { - bitClear(MINRF.ignore,XdrvMailbox.payload); - MINRFcomputefirstUsedPacketMode(); - MINRF.timer = 5900; - Response_P(S_JSON_NRF_COMMAND, command, kMINRFDeviceType[XdrvMailbox.payload-1]); - } - else if (XdrvMailbox.payload == 65535) { - MINRF.ignore = 0; - } - } - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.ignore); - break; - case CMND_NRF_SCAN: - if (XdrvMailbox.data_len > 0) { - MINRF.beacon.active = false; - switch(XdrvMailbox.payload){ - case 0: - MINRF.mode.activeScan = true; - MINRF.mode.stopScan = false; - MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(), - MINRFscanResult.end(), - [](scan_entry_t&) { return true; }), - MINRFscanResult.end()); - break; - case 1: - MINRF.mode.activeScan = true; - MINRF.mode.stopScan = false; - break; - case 2: - MINRF.mode.stopScan = true; - break; - } - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - break; - case CMND_NRF_BEACON: - if (XdrvMailbox.data_len > 0) { - if(XdrvMailbox.data_len<3){ - if (XdrvMailbox.payload < MINRFscanResult.size()) { - MINRFstartBeacon(XdrvMailbox.payload); - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - } - if (XdrvMailbox.data_len==12){ - memset(MINRF.beacon.MAC,0,sizeof(MINRF.beacon.MAC)); - MINRFMACStringToBytes(XdrvMailbox.data, MINRF.beacon.MAC); - MINRF.beacon.time=0; - MINRF.beacon.active=true; - Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); - } - MINRFcomputeBeaconPDU(MINRF.beacon.MAC,MINRF.beacon.PDU,0); - } - break; - case CMND_NRF_NLIGHT: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.data_len==12){ - uint8_t _MAC[6] = {0}; - MINRFMACStringToBytes(XdrvMailbox.data, _MAC); - Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); - MINRFaddLight(_MAC, 7); - } - } - break; - case CMND_NRF_CHAN: - if (XdrvMailbox.data_len == 1) { - switch(XdrvMailbox.payload){ - case 0: case 1: case 2: - bitRead(MINRF.channelIgnore,XdrvMailbox.payload) == 0 ? bitSet(MINRF.channelIgnore,XdrvMailbox.payload) : bitClear(MINRF.channelIgnore,XdrvMailbox.payload); - break; - } - } - Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore); - break; -#ifdef USE_MI_DECRYPTION - case CMND_NRF_MJYD2S: - if (XdrvMailbox.data_len==44){ - MINRFAddKey(XdrvMailbox.data); - uint8_t _MAC[6] = {0}; - MINRFMACStringToBytes((XdrvMailbox.data)+32, _MAC); - MINRFaddLight(_MAC, 8); - Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); - } - break; - - case CMND_NRF_KEY: - if (XdrvMailbox.data_len==44){ - MINRFAddKey(XdrvMailbox.data); - Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data); - } - break; -#endif - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; -const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%dus/cm{e}"; -const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; -const char HTTP_NRF24NEW[] PROGMEM = "{s}%sL01%c{m}%u%s / %u{e}"; - -void MINRFShow(bool json) -{ - if (json) { -#ifdef USE_HOME_ASSISTANT - bool _noSummarySave = MINRF.option.noSummary; - bool _minimalSummarySave = MINRF.option.minimalSummary; - if(hass_mode==2){ - MINRF.option.noSummary = false; - MINRF.option.minimalSummary = false; - } -#endif - if(!MINRF.mode.triggeredTele){ - if(MINRF.option.noSummary) return; - } - - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MINRF.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; - if(MINRF.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; - - if(MIBLEsensors[i].showedUp < 3){ - DEBUG_SENSOR_LOG(PSTR("NRF: sensor not fully registered yet")); - if(MIBLEsensors[i].type != YEERC) break; - } - - ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"),kMINRFDeviceType[MIBLEsensors[i].type-1],MIBLEsensors[i].MAC[3],MIBLEsensors[i].MAC[4],MIBLEsensors[i].MAC[5]); - - uint32_t _positionCurlyBracket = strlen(mqtt_data); - - if((!MINRF.mode.triggeredTele && !MINRF.option.minimalSummary)||MINRF.mode.triggeredTele){ - bool tempHumSended = false; - if(MIBLEsensors[i].feature.tempHum){ - if(MIBLEsensors[i].eventType.tempHum || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ - if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp) -#ifdef USE_HOME_ASSISTANT - ||(!hass_mode==2) -#endif - ) { - ResponseAppend_P(PSTR(",")); - ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); - tempHumSended = true; - } - } - } - if(MIBLEsensors[i].feature.temp && !tempHumSended){ - if(MIBLEsensors[i].eventType.temp || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].temp) -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ) { - char temperature[FLOATSZ]; - dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - } - } - if(MIBLEsensors[i].feature.hum && !tempHumSended){ - if(MIBLEsensors[i].eventType.hum || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].hum)) { - char hum[FLOATSZ]; - dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); - } - } - } - if (MIBLEsensors[i].feature.lux){ - if(MIBLEsensors[i].eventType.lux || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ - if (MIBLEsensors[i].lux!=0x0ffffff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ) { - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); - } - } - } - if (MIBLEsensors[i].feature.moist){ - if(MIBLEsensors[i].eventType.moist || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ - if (MIBLEsensors[i].moisture!=0xff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ) { - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); - } - } - } - if (MIBLEsensors[i].feature.fert){ - if(MIBLEsensors[i].eventType.fert || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ - if (MIBLEsensors[i].fertility!=0xffff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ) { - ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); - } - } - } - if (MIBLEsensors[i].feature.Btn){ - if(MIBLEsensors[i].eventType.Btn){ - ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); - } - } - } - if (MIBLEsensors[i].feature.PIR){ - if(MIBLEsensors[i].eventType.motion || !MINRF.mode.triggeredTele){ - if(MINRF.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); - ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); - } - else if(MIBLEsensors[i].eventType.noMotion && MINRF.mode.triggeredTele){ - ResponseAppend_P(PSTR(",\"PIR\":0")); - } - } - - if (MIBLEsensors[i].feature.NMT || !MINRF.mode.triggeredTele){ - if(MIBLEsensors[i].eventType.NMT){ - ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); - } - } - if (MIBLEsensors[i].feature.bat){ - if(MIBLEsensors[i].eventType.bat || !MINRF.mode.triggeredTele || MINRF.option.allwaysAggregate){ - if (MIBLEsensors[i].bat != 0x00 -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ) { - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); - } - } - } - if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); - ResponseAppend_P(PSTR("}")); - mqtt_data[_positionCurlyBracket] = '{'; - MIBLEsensors[i].eventType.raw = 0; - if(MIBLEsensors[i].shallSendMQTT==1){ - MIBLEsensors[i].shallSendMQTT = 0; - continue; - } - } - for(uint32_t i=0; iMINRF.confirmedSensors){ - j = MINRF.confirmedSensors; - } - char stemp[5] ={0}; - if (MINRF.confirmedSensors-(_page*MINRF.perPage)>1 && MINRF.perPage!=1) { - sprintf_P(stemp,"-%u",j); - } - if (MINRF.confirmedSensors==0) i=-1; - - WSContentSend_PD(HTTP_NRF24NEW, NRF24type, NRF24.chipType, i+1,stemp,MINRF.confirmedSensors); - for (i ; iFLORA){ - WSContentSend_THD(kMINRFDeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); - if(MIBLEsensors[i].bat!=0x00){ - WSContentSend_PD(HTTP_BATTERY, kMINRFDeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); - } - } - } - if(MINRF.beacon.active){ - WSContentSend_PD(HTTP_MINRF_HL); - WSContentSend_PD(HTTP_MINRF_HL); - WSContentSend_PD(HTTP_MINRF_MAC, F("Beacon"), D_MAC_ADDRESS, MINRF.beacon.MAC[0], MINRF.beacon.MAC[1],MINRF.beacon.MAC[2],MINRF.beacon.MAC[3],MINRF.beacon.MAC[4],MINRF.beacon.MAC[5]); - WSContentSend_PD(PSTR("{s}Beacon Time{m}%u seconds{e}"),MINRF.beacon.time); - } - - for(uint32_t i=0; i0){ - WSContentSend_PD(HTTP_BATTERY, kMINRFDeviceType[MIBLElights[i].type-1], MIBLElights[i].bat); - } - if(MIBLElights[i].lux>0){ - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFDeviceType[MIBLElights[i].type-1], MIBLElights[i].lux); - } - } - } - - if(counter>3) { - _page++; - counter = 0; - } - counter++; - if(MINRF.confirmedSensors%MINRF.perPage==0 && _page==MINRF.confirmedSensors/MINRF.perPage) _page=0; - if(_page>MINRF.confirmedSensors/MINRF.perPage) _page=0; -#endif - } -} - - - - - -bool Xsns61(uint8_t function) -{ - bool result = false; - if (NRF24.chipType) { - switch (function) { - case FUNC_INIT: - MINRFinit(); - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF: started")); - break; - case FUNC_EVERY_50_MSECOND: - MINRF_EVERY_50_MSECOND(); - break; - case FUNC_EVERY_SECOND: - MINRFbeaconCounter(); - break; - case FUNC_COMMAND: - result = NRFCmd(); - break; - case FUNC_JSON_APPEND: - MINRFShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MINRFShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -# 46 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -#ifdef ESP32 - -#ifdef USE_MI_ESP32 - -#define XSNS_62 62 -#define USE_MI_DECRYPTION - -#include -#include -#ifdef USE_MI_DECRYPTION -#include -#endif - -void MI32scanEndedCB(NimBLEScanResults results); -void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); - -struct { - uint16_t perPage = 4; - uint32_t period; - union { - struct { - uint32_t init:1; - uint32_t connected:1; - uint32_t autoScan:1; - uint32_t canScan:1; - uint32_t runningScan:1; - uint32_t canConnect:1; - uint32_t willConnect:1; - uint32_t readingDone:1; - uint32_t shallSetTime:1; - uint32_t willSetTime:1; - uint32_t shallReadBatt:1; - uint32_t willReadBatt:1; - uint32_t shallSetUnit:1; - uint32_t willSetUnit:1; - uint32_t shallTriggerTele:1; - uint32_t triggeredTele:1; - uint32_t shallClearResults:1; - uint32_t shallShowStatusInfo:1; - uint32_t firstAutodiscoveryDone:1; - uint32_t activeBeacon; - }; - uint32_t all = 0; - } mode; - struct { - uint8_t sensor; - uint8_t beaconScanCounter; - } state; - struct { - uint32_t allwaysAggregate:1; - uint32_t noSummary:1; - uint32_t directBridgeMode:1; - uint32_t holdBackFirstAutodiscovery:1; - uint32_t showRSSI:1; - uint32_t ignoreBogusBattery:1; - uint32_t minimalSummary:1; - } option; -} MI32; - -#pragma pack(1) - - struct { - uint16_t temp; - uint8_t hum; - uint16_t volt; - } LYWSD0x_HT; - struct { - uint8_t spare; - uint16_t temp; - uint16_t hum; - } CGD1_HT; - struct { - uint16_t temp; - uint8_t spare; - uint32_t lux; - uint8_t moist; - uint16_t fert; - } Flora_TLMF; - - -struct mi_beacon_t{ - uint16_t frame; - uint16_t productID; - uint8_t counter; - uint8_t MAC[6]; - uint8_t spare; - uint8_t type; - uint8_t ten; - uint8_t size; - union { - struct{ - uint16_t temp; - uint16_t hum; - }HT; - uint8_t bat; - uint16_t temp; - uint16_t hum; - uint32_t lux; - uint8_t moist; - uint16_t fert; - uint32_t NMT; - struct{ - uint16_t num; - uint8_t longPress; - }Btn; - }; - uint8_t padding[12]; -}; - -struct cg_packet_t { - uint16_t frameID; - uint8_t MAC[6]; - uint16_t mode; - union { - struct { - int16_t temp; - uint16_t hum; - }; - uint8_t bat; - }; -}; - -struct encPacket_t{ - - uint16_t PID; - uint8_t frameCnt; - uint8_t MAC[6]; - uint8_t payload[16]; -}; - -union mi_bindKey_t{ - struct{ - uint8_t key[16]; - uint8_t MAC[6]; - }; - uint8_t buf[22]; -}; - -struct ATCPacket_t{ - uint8_t MAC[6]; - int16_t temp; - uint8_t hum; - uint8_t batPer; - uint16_t batMV; - uint8_t frameCnt; -}; - -#pragma pack(0) - -struct mi_sensor_t{ - uint8_t type; - uint8_t lastCnt; - uint8_t shallSendMQTT; - uint8_t MAC[6]; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t PIR:1; - uint32_t Btn:1; - }; - uint32_t raw; - } feature; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t motion:1; - uint32_t noMotion:1; - uint32_t Btn:1; - }; - uint32_t raw; - } eventType; - - int RSSI; - uint32_t lastTime; - uint32_t lux; - float temp; - union { - struct { - uint8_t moisture; - uint16_t fertility; - char firmware[6]; - }; - struct { - float hum; - }; - struct { - uint16_t events; - uint32_t NMT; - }; - uint16_t Btn; - }; - union { - uint8_t bat; - }; -}; - -struct scan_entry_t { - uint8_t MAC[6]; - uint16_t CID; - uint16_t SVC; - uint16_t UUID; - int32_t RSSI; -}; - -struct generic_beacon_t { - uint8_t MAC[6]; - uint32_t time; - int32_t RSSI; - uint16_t CID; - uint16_t UUID; - uint16_t SVC; - bool active = false; -}; - -std::vector MIBLEsensors; -std::vector MIBLEbindKeys; -std::array MIBLEbeacons; -std::vector MINBLEscanResult; - -static BLEScan* MI32Scan; - - - - - -#define D_CMND_MI32 "MI32" - -const char S_JSON_MI32_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s\":%d}"; -const char S_JSON_MI32_COMMAND[] PROGMEM = "{\"" D_CMND_MI32 "%s%s\"}"; - -const char S_JSON_MI32_BCOMMAND_SVALUE[] PROGMEM = "{\"" D_CMND_MI32 "%s%u\":\"%s\"}"; -const char kMI32_Commands[] PROGMEM = "Period|Time|Page|Battery|Unit|Key|Beacon"; - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03MMC 4 -#define CGG1 5 -#define CGD1 6 -#define NLIGHT 7 -#define MJYD2S 8 -#define YEERC 9 -#define MHOC401 10 -#define MHOC303 11 -#define ATC 12 - -#define MI32_TYPES 12 - -const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, - 0x01aa, - 0x045b, - 0x055b, - 0x0347, - 0x0576, - 0x03dd, - 0x07f6, - 0x0153, - 0x0387, - 0x06d3, - 0x0a1c - }; - -const char kMI32DeviceType1[] PROGMEM = "Flora"; -const char kMI32DeviceType2[] PROGMEM = "MJ_HT_V1"; -const char kMI32DeviceType3[] PROGMEM = "LYWSD02"; -const char kMI32DeviceType4[] PROGMEM = "LYWSD03"; -const char kMI32DeviceType5[] PROGMEM = "CGG1"; -const char kMI32DeviceType6[] PROGMEM = "CGD1"; -const char kMI32DeviceType7[] PROGMEM = "NLIGHT"; -const char kMI32DeviceType8[] PROGMEM = "MJYD2S"; -const char kMI32DeviceType9[] PROGMEM = "YEERC"; -const char kMI32DeviceType10[] PROGMEM ="MHOC401"; -const char kMI32DeviceType11[] PROGMEM ="MHOC303"; -const char kMI32DeviceType12[] PROGMEM ="ATC"; -const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12}; - - - - - -enum MI32_Commands { - CMND_MI32_PERIOD, - CMND_MI32_TIME, - CMND_MI32_PAGE, - CMND_MI32_BATTERY, - CMND_MI32_UNIT, - CMND_MI32_KEY, - CMND_MI32_BEACON - }; - -enum MI32_TASK { - MI32_TASK_SCAN = 0, - MI32_TASK_CONN = 1, - MI32_TASK_TIME = 2, - MI32_TASK_BATT = 3, - MI32_TASK_UNIT = 4, -}; - -enum MI32_BEACON_CMND { - MI32_BEACON_ON = 0, - MI32_BEACON_OFF = 1, - MI32_BEACON_DEL = 2, -}; - - - - - -class MI32SensorCallback : public NimBLEClientCallbacks { - void onConnect(NimBLEClient* pclient) { - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("connected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); - MI32.mode.willConnect = 0; - MI32.mode.connected = 1; - } - void onDisconnect(NimBLEClient* pclient) { - MI32.mode.connected = 0; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("disconnected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); - } - bool onConnParamsUpdateRequest(NimBLEClient* MI32Client, const ble_gap_upd_params* params) { - if(params->itvl_min < 24) { - return false; - } else if(params->itvl_max > 40) { - return false; - } else if(params->latency > 2) { - return false; - } else if(params->supervision_timeout > 100) { - return false; - } - return true; - } -}; - -class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks { - void onResult(NimBLEAdvertisedDevice* advertisedDevice) { - - int RSSI = advertisedDevice->getRSSI(); - uint8_t addr[6]; - memcpy(addr,advertisedDevice->getAddress().getNative(),6); - MI32_ReverseMAC(addr); - if (advertisedDevice->getServiceDataCount() == 0) { - - if(MI32.state.beaconScanCounter==0 && !MI32.mode.activeBeacon){ - MI32Scan->erase(advertisedDevice->getAddress()); - return; - } - else{ - MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); - return; - } - - } - uint16_t UUID = advertisedDevice->getServiceDataUUID(0).getNative()->u16.value; - - - size_t ServiceDataLength = advertisedDevice->getServiceData(0).length(); - if(UUID==0xfe95) { - MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); - } - else if(UUID==0xfdcd) { - MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); - } - else if(UUID==0x181a) { - MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); - } - else { - if(MI32.state.beaconScanCounter!=0 || MI32.mode.activeBeacon){ - MI32HandleGenericBeacon(advertisedDevice->getPayload(), advertisedDevice->getPayloadLength(), RSSI, addr); - } - - MI32Scan->erase(advertisedDevice->getAddress()); - } - }; -}; - - -static MI32AdvCallbacks MI32ScanCallbacks; -static MI32SensorCallback MI32SensorCB; -static NimBLEClient* MI32Client; - - - - - -void MI32scanEndedCB(NimBLEScanResults results){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Scan ended")); - MI32.mode.runningScan = 0; -} - -void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Notified length: %u"),length); - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case LYWSD02: case MHOC401: - MI32readHT_LY((char*)pData); - MI32.mode.readingDone = 1; - break; - default: - MI32.mode.readingDone = 1; - break; - } -} -# 469 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -void MI32stripColon(char* _string){ - uint32_t _length = strlen(_string); - uint32_t _index = 0; - while (_index < _length) { - char c = _string[_index]; - if(c==':'){ - memmove(_string+_index,_string+_index+1,_length-_index); - } - _index++; - } - _string[_index] = 0; -} -# 489 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -void MI32HexStringToBytes(char* _string, uint8_t* _byteArray) { - MI32stripColon(_string); - UpperCase(_string,_string); - uint32_t index = 0; - uint32_t _end = strlen(_string); - memset(_byteArray,0,_end/2); - while (index < _end) { - char c = _string[index]; - uint8_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _byteArray[(index/2)] += value << (((index + 1) % 2) * 4); - index++; - } -} - - - - - - -void MI32_ReverseMAC(uint8_t _mac[]){ - uint8_t _reversedMAC[6]; - for (uint8_t i=0; i<6; i++){ - _reversedMAC[5-i] = _mac[i]; - } - memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); -} - -#ifdef USE_MI_DECRYPTION -void MI32AddKey(char* payload){ - mi_bindKey_t keyMAC; - MI32HexStringToBytes(payload,keyMAC.buf); - bool unknownKey = true; - for(uint32_t i=0; iMAC[i]; - } - memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2); - nonce[8] = packet->frameCnt; - memcpy((uint8_t*)&nonce+9,(uint8_t*)&_buf[_bufSize-9],3); - - memcpy((uint8_t*)&tag,(uint8_t*)&_buf[_bufSize-6],4); - - - MI32_ReverseMAC(packet->MAC); - uint8_t _bindkey[16] = {0x0}; - bool foundNoKey = true; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: search key for MAC: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]); - for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ - memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: decryption Key found")); - foundNoKey = false; - break; - } - } - if(foundNoKey){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: no Key found !!")); - return -2; - } - - br_aes_small_ctrcbc_keys keyCtx; - br_aes_small_ctrcbc_init(&keyCtx, _bindkey, sizeof(_bindkey)); - - br_ccm_context ctx; - br_ccm_init(&ctx, &keyCtx.vtable); - br_ccm_reset(&ctx, nonce, sizeof(nonce), sizeof(authData), data_len, sizeof(tag)); - br_ccm_aad_inject(&ctx, authData, sizeof(authData)); - br_ccm_flip(&ctx); - - - memcpy(payload,packet->payload,data_len); - br_ccm_run(&ctx, 0, payload, data_len); - memcpy((uint8_t*)packet->payload+1,payload,data_len); - - ret = br_ccm_check_tag(&ctx, &tag); - - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]); - return ret-1; -} -#endif - -#ifdef USE_HOME_ASSISTANT - - - - -void MI32nullifyEndOfMQTT_DATA(){ - char *p = mqtt_data + strlen(mqtt_data); - while(true){ - *p--; - if(p[0]==':'){ - p[1] = 0; - break; - } - } - ResponseAppend_P(PSTR("null")); -} -#endif -# 636 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter){ - - DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_MI32, _type); - bool _success = false; - for (uint32_t i=0;i= NIMBLE_MAX_CONNECTIONS) { - MI32.mode.willConnect = 0; - DEBUG_SENSOR_LOG(PSTR("%s: max connection already reached"),D_CMND_MI32); - return false; - } - if(!MI32Client) { - - MI32Client = NimBLEDevice::createClient(); - MI32Client->setClientCallbacks(&MI32SensorCB , false); - MI32Client->setConnectionParams(12,12,0,48); - MI32Client->setConnectTimeout(30); - - } - vTaskDelay(300/ portTICK_PERIOD_MS); - if (!MI32Client->connect(_address,false)) { - MI32.mode.willConnect = 0; - - - return false; - } - return true; - -} - -void MI32StartScanTask(){ - if (MI32.mode.connected) return; - MI32.mode.runningScan = 1; - xTaskCreatePinnedToCore( - MI32ScanTask, - "MI32ScanTask", - 4096, - NULL, - 0, - NULL, - 0); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Start scanning"),D_CMND_MI32); -} - -void MI32ScanTask(void *pvParameters){ - if (MI32Scan == nullptr) MI32Scan = NimBLEDevice::getScan(); - - MI32Scan->setInterval(70); - MI32Scan->setWindow(50); - MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks,true); - MI32Scan->setActiveScan(false); - MI32Scan->start(0, MI32scanEndedCB, true); - - uint32_t timer = 0; - for(;;){ - if(MI32.mode.shallClearResults){ - MI32Scan->clearResults(); - MI32.mode.shallClearResults=0; - } - vTaskDelay(10000/ portTICK_PERIOD_MS); - } - vTaskDelete( NULL ); -} - -void MI32StartSensorTask(){ - MI32.mode.willConnect = 1; - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MHOC401: - break; - default: - MI32.mode.willConnect = 0; - return; - } - - xTaskCreatePinnedToCore( - MI32SensorTask, - "MI32SensorTask", - 4096, - NULL, - 15, - NULL, - 0); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Start sensor connections"),D_CMND_MI32); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: with sensor: %u"),D_CMND_MI32, MI32.state.sensor); -} - -void MI32SensorTask(void *pvParameters){ - if (MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - MI32Client->disconnect(); - - MI32.mode.willConnect = 0; - MI32.mode.willReadBatt = 0; - vTaskDelay(100/ portTICK_PERIOD_MS); - vTaskDelete( NULL ); - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - - timer = 150; - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MHOC401: - MI32.mode.readingDone = 0; - if(MI32connectLYWSD03forNotification()) timer=0; - break; - default: - break; - } - - while (!MI32.mode.readingDone){ - if (timer>150){ - break; - } - timer++; - vTaskDelay(100/ portTICK_PERIOD_MS); - } - MI32Client->disconnect(); - DEBUG_SENSOR_LOG(PSTR("%s: requested disconnect"),D_CMND_MI32); - } - - MI32.mode.connected = 0; - vTaskDelete( NULL ); -} - -bool MI32connectLYWSD03forNotification(){ - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xebe0ccb0,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); - static BLEUUID charUUID(0xebe0ccc1,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - } - if (pChr){ - if(pChr->canNotify()) { - if(pChr->subscribe(true,MI32notifyCB,false)) { - return true; - } - } - } - return false; -} - -void MI32StartTimeTask(){ - MI32.mode.willConnect = 1; - xTaskCreatePinnedToCore( - MI32TimeTask, - "MI32TimeTask", - 4096, - NULL, - 15, - NULL, - 0); - - -} - -void MI32TimeTask(void *pvParameters){ - if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { - MI32.mode.shallSetTime = 0; - vTaskDelete( NULL ); - } - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID charUUID(0xEBE0CCB7,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - - } - if (pChr){ - if(pChr->canWrite()) { - union { - uint8_t buf[5]; - uint32_t time; - } _utc; - _utc.time = Rtc.utc_time; - _utc.buf[4] = Rtc.time_timezone / 60; - - if(!pChr->writeValue(_utc.buf,sizeof(_utc.buf),true)) { - MI32.mode.willConnect = 0; - MI32Client->disconnect(); - } - else { - MI32.mode.shallSetTime = 0; - MI32.mode.willSetTime = 0; - } - } - } - MI32Client->disconnect(); - } - - MI32.mode.connected = 0; - MI32.mode.canScan = 1; - vTaskDelete( NULL ); -} - -void MI32StartUnitTask(){ - MI32.mode.willConnect = 1; - xTaskCreatePinnedToCore( - MI32UnitTask, - "MI32UnitTask", - 4096, - NULL, - 15, - NULL, - 0); - - -} - -void MI32UnitTask(void *pvParameters){ - if (MIBLEsensors[MI32.state.sensor].type != LYWSD02 && MIBLEsensors[MI32.state.sensor].type != MHOC303) { - MI32.mode.shallSetUnit = 0; - vTaskDelete( NULL ); - } - - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID charUUID(0xEBE0CCBE,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - } - - if(pChr->canRead()){ - uint8_t curUnit; - const char *buf = pChr->readValue().c_str(); - if( buf[0] != 0 && buf[0]<101 ){ - curUnit = buf[0]; - } - - if(pChr->canWrite()) { - curUnit = curUnit == 0x01?0xFF:0x01; - - if(!pChr->writeValue(&curUnit,sizeof(curUnit),true)) { - MI32.mode.willConnect = 0; - MI32Client->disconnect(); - } - else { - MI32.mode.shallSetUnit = 0; - MI32.mode.willSetUnit = 0; - } - } - } - MI32Client->disconnect(); - } - - MI32.mode.connected = 0; - MI32.mode.canScan = 1; - vTaskDelete( NULL ); -} - -void MI32StartBatteryTask(){ - if (MI32.mode.connected) return; - MI32.mode.willReadBatt = 1; - MI32.mode.willConnect = 1; - MI32.mode.canScan = 0; - - switch (MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: case MJ_HT_V1: case CGG1: case NLIGHT: case MJYD2S: case YEERC: case MHOC401: - MI32.mode.willConnect = 0; - MI32.mode.willReadBatt = 0; - return; - } - - xTaskCreatePinnedToCore( - MI32BatteryTask, - "MI32BatteryTask", - 4096, - NULL, - 15, - NULL, - 0); -} - -void MI32BatteryTask(void *pvParameters){ - - - MI32.mode.connected = 0; - if(MI32ConnectActiveSensor()){ - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(30/ portTICK_PERIOD_MS); - } - - switch(MIBLEsensors[MI32.state.sensor].type){ - case FLORA: case LYWSD02: case CGD1: - MI32batteryRead(MIBLEsensors[MI32.state.sensor].type); - break; - } - MI32Client->disconnect(); - } - MI32.mode.willReadBatt = 0; - MI32.mode.connected = 0; - vTaskDelete( NULL ); -} - -void MI32batteryRead(uint32_t _type){ - uint32_t timer = 0; - while (!MI32.mode.connected){ - if (timer>1000){ - break; - } - timer++; - vTaskDelay(10/ portTICK_PERIOD_MS); - } - DEBUG_SENSOR_LOG(PSTR("%s connected for battery"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - - switch(_type){ - case FLORA: - { - static BLEUUID _serviceUUID(0x00001204,0x0000,0x1000,0x800000805f9b34fb); - static BLEUUID _charUUID(0x00001a02,0x0000,0x1000,0x800000805f9b34fb); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - case LYWSD02: - { - static BLEUUID _serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - static BLEUUID _charUUID(0xEBE0CCC4,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - case CGD1: - { - static BLEUUID _serviceUUID((uint16_t)0x180F); - static BLEUUID _charUUID((uint16_t)0x2A19); - pSvc = MI32Client->getService(_serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(_charUUID); - } - } - break; - } - - if (pChr){ - DEBUG_SENSOR_LOG(PSTR("%s: got %s char %s"),D_CMND_MI32, kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1], pChr->getUUID().toString().c_str()); - if(pChr->canRead()) { - const char *buf = pChr->readValue().c_str(); - MI32readBat((char*)buf); - } - } - MI32.mode.readingDone = 1; -} - - - - - -void MI32parseMiBeacon(char * _buf, uint32_t _slot, uint16_t _bufSize){ - float _tempFloat; - mi_beacon_t _beacon; - - if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1 || MIBLEsensors[_slot].type==YEERC){ - memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); - memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); - _beacon.counter = _buf[4]; - } - else{ - memcpy((char *)&_beacon, _buf, _bufSize); - } - - MIBLEsensors[_slot].lastCnt = _beacon.counter; -#ifdef USE_MI_DECRYPTION - int decryptRet = 0; - switch(MIBLEsensors[_slot].type){ - case LYWSD03MMC: case MHOC401: - if (_beacon.frame == 0x5858){ - decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize, LYWSD03MMC); - - } - else return; - break; - case MJYD2S: - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: %x"),_beacon.frame); - if (_beacon.frame == 0x5948){ - memmove((uint8_t*)&_beacon.MAC+6,(uint8_t*)&_beacon.MAC, _bufSize); - memcpy((uint8_t*)&_beacon.MAC,MIBLEsensors[_slot].MAC,6); - _bufSize+=6; - MI32_ReverseMAC(_beacon.MAC); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MJYD2S: special packet")); - } - if (_beacon.frame != 0x5910){ - decryptRet = MI32_decryptPacket((char*)&_beacon.productID,_bufSize,MJYD2S); - } - break; - } -if(decryptRet!=0){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MI32: decryption failed with error: %d"),decryptRet); - return; -} -#endif - - if(MIBLEsensors[_slot].type==6){ - DEBUG_SENSOR_LOG(PSTR("CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); - return; - } - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u with payload type: %02x"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot,_beacon.type); - switch(_beacon.type){ - case 0x01: - MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6; - MIBLEsensors[_slot].eventType.Btn = 1; - MI32.mode.shallTriggerTele = 1; - - break; - case 0x04: - _tempFloat=(float)(_beacon.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - MIBLEsensors[_slot].eventType.temp = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); - } - - break; - case 0x06: - _tempFloat=(float)(_beacon.hum)/10.0f; - if(_tempFloat<101){ - MIBLEsensors[_slot].hum=_tempFloat; - MIBLEsensors[_slot].eventType.hum = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); - } - - break; - case 0x07: - MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; - if(MIBLEsensors[_slot].type==MJYD2S){ - MIBLEsensors[_slot].eventType.noMotion = 1; - } - MIBLEsensors[_slot].eventType.lux = 1; - - break; - case 0x08: - MIBLEsensors[_slot].moisture=_beacon.moist; - MIBLEsensors[_slot].eventType.moist = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); - - break; - case 0x09: - MIBLEsensors[_slot].fertility=_beacon.fert; - MIBLEsensors[_slot].eventType.fert = 1; - DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); - - break; - case 0x0a: - if(MI32.option.ignoreBogusBattery){ - if(MIBLEsensors[_slot].type==LYWSD03MMC || MIBLEsensors[_slot].type==MHOC401){ - break; - } - } - if(_beacon.bat<101){ - MIBLEsensors[_slot].bat = _beacon.bat; - MIBLEsensors[_slot].eventType.bat = 1; - DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - } - - break; - case 0x0d: - _tempFloat=(float)(_beacon.HT.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); - } - _tempFloat=(float)(_beacon.HT.hum)/10.0f; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - - break; -#ifdef USE_MI_DECRYPTION - case 0x0f: - if (_beacon.ten!=0) break; - MIBLEsensors[_slot].eventType.motion = 1; - MIBLEsensors[_slot].lastTime = millis(); - MIBLEsensors[_slot].events++; - MIBLEsensors[_slot].lux = _beacon.lux; - MIBLEsensors[_slot].eventType.lux = 1; - MIBLEsensors[_slot].NMT = 0; - MI32.mode.shallTriggerTele = 1; - - break; - case 0x17: - MIBLEsensors[_slot].NMT = _beacon.NMT; - MIBLEsensors[_slot].eventType.NMT = 1; - MI32.mode.shallTriggerTele = 1; - - break; -#endif - default: - if (MIBLEsensors[_slot].type==NLIGHT){ - MIBLEsensors[_slot].eventType.motion = 1; - MIBLEsensors[_slot].events++; - MIBLEsensors[_slot].NMT = 0; - MIBLEsensors[_slot].lastTime = millis(); - MI32.mode.shallTriggerTele = 1; - - } - else{ - AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)_buf,_bufSize); - } - break; - } - if(MIBLEsensors[_slot].eventType.raw == 0) return; - MIBLEsensors[_slot].shallSendMQTT = 1; - if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; -} - -void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ - ATCPacket_t *_packet = (ATCPacket_t*)_buf; - uint32_t _slot = MIBLEgetSensorSlot(_packet->MAC, 0x0a1c, _packet->frameCnt); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); - if(_slot==0xff) return; - - MIBLEsensors[_slot].RSSI=RSSI; - - MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; - MIBLEsensors.at(_slot).hum = (float)_packet->hum; - MIBLEsensors[_slot].eventType.tempHum = 1; - MIBLEsensors.at(_slot).bat = _packet->batPer; - MIBLEsensors[_slot].eventType.bat = 1; - - MIBLEsensors[_slot].shallSendMQTT = 1; - if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; - -} - -void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ - uint8_t _addr[6]; - memcpy(_addr,addr,6); - uint32_t _slot = MIBLEgetSensorSlot(_addr, 0x0576, 0); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); - if(_slot==0xff) return; - MIBLEsensors[_slot].RSSI=RSSI; - cg_packet_t _packet; - memcpy((char*)&_packet,_buf,sizeof(_packet)); - switch (_packet.mode){ - case 0x0401: - float _tempFloat; - _tempFloat=(float)(_packet.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors.at(_slot).temp = _tempFloat; - MIBLEsensors[_slot].eventType.temp = 1; - DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); - } - _tempFloat=(float)(_packet.hum)/10.0f; - if(_tempFloat<100){ - MIBLEsensors.at(_slot).hum = _tempFloat; - MIBLEsensors[_slot].eventType.hum = 1; - DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); - } - DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), _packet.temp, _packet.hum); - break; - case 0x0102: - if(_packet.bat<101){ - MIBLEsensors.at(_slot).bat = _packet.bat; - MIBLEsensors[_slot].eventType.bat = 1; - DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - } - break; - default: - DEBUG_SENSOR_LOG(PSTR("MI32: unexpected CGD1-packet")); - } - if(MIBLEsensors[_slot].eventType.raw == 0) return; - MIBLEsensors[_slot].shallSendMQTT = 1; - if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; -} - -void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { - if(bufsize<9) { - return; - } - uint16_t _type= buf[3]*256 + buf[2]; - - uint8_t _addr[6]; - memcpy(_addr,addr,6); - uint16_t _slot = MIBLEgetSensorSlot(_addr, _type, buf[4]); - if(_slot!=0xff) { - MIBLEsensors[_slot].RSSI=RSSI; - MI32parseMiBeacon(buf,_slot,bufsize); - } -} -# 1456 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID){ - AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("MI32: Beacon:____________")); - for (uint32_t i = 0; i19) { - AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full")); - MI32.state.beaconScanCounter = 1; - return; - } - for(auto _scanResult : MINBLEscanResult){ - if(memcmp(addr,_scanResult.MAC,6)==0){ - - return; - } - } - scan_entry_t _new; - _new.RSSI = RSSI; - _new.CID = 0; - _new.SVC = 0; - _new.UUID = 0; - memcpy(_new.MAC,addr,sizeof(_new.MAC)); - MI32ParseGenericBeacon(payload,payloadLength,&_new.CID,&_new.SVC,&_new.UUID); - MINBLEscanResult.push_back(_new); -} -# 1542 "/workspace/Tasmota/tasmota/xsns_62_MI_ESP32.ino" -void MI32addBeacon(uint8_t index, char* data){ - auto &_new = MIBLEbeacons[index-1]; - MI32HexStringToBytes(data,_new.MAC); - char _MAC[18]; - ToHex_P(MIBLEbeacons[index-1].MAC,6,_MAC,18,':'); - char _empty[6] = {0}; - _new.time = 0; - if(memcmp(_empty,_new.MAC,6) == 0){ - _new.active = false; - AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon%u deactivated"), index); - } - else{ - _new.active = true; - MI32.mode.activeBeacon = 1; - AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: beacon added with MAC: %s"), _MAC); - } -} - - - - - -void MI32showScanResults(){ - AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: found %u devices in scan:"), MINBLEscanResult.size()); - for(auto _scanResult : MINBLEscanResult){ - char _MAC[18]; - ToHex_P(_scanResult.MAC,6,_MAC,18,':'); - AddLog_P2(LOG_LEVEL_INFO,PSTR("MAC: %s _ CID: %04x _ SVC: %04x _ UUID: %04x _ RSSI: %d"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.RSSI); - } - MINBLEscanResult.clear(); -} - - - - -void MI32readHT_LY(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0 && _buf[1] != 0){ - memcpy(&LYWSD0x_HT,(void *)_buf,sizeof(LYWSD0x_HT)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u, V: %u"),D_CMND_MI32,LYWSD0x_HT.temp,LYWSD0x_HT.hum, LYWSD0x_HT.volt); - uint32_t _slot = MI32.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - - } - _tempFloat=(float)LYWSD0x_HT.hum; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){ - MIBLEsensors[_slot].bat = ((float)LYWSD0x_HT.volt-2100.0f)/12.0f; - MI32.mode.willReadBatt = 0; - MIBLEsensors[_slot].eventType.bat = 1; - } - MIBLEsensors[_slot].shallSendMQTT = 1; - MI32.mode.shallTriggerTele = 1; - } -} - -bool MI32readBat(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_MI32,_buf[0]); - uint32_t _slot = MI32.state.sensor; - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - if(_buf[0]<101){ - MIBLEsensors[_slot].bat=_buf[0]; - if(MIBLEsensors[_slot].type==FLORA){ - memcpy(MIBLEsensors[_slot].firmware, _buf+2, 5); - MIBLEsensors[_slot].firmware[5] = '\0'; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Firmware: %s"),D_CMND_MI32,MIBLEsensors[_slot].firmware); - } - MIBLEsensors[_slot].eventType.bat = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - MI32.mode.shallTriggerTele = 1; - return true; - } - } - return false; -} - - - - - - -void MI32Every50mSecond(){ - if(MI32.mode.shallTriggerTele){ - MI32.mode.shallTriggerTele = 0; - MI32triggerTele(); - } -} - - - - - - -void MI32EverySecond(bool restart){ - static uint32_t _counter = MI32.period - 15; - static uint32_t _nextSensorSlot = 0; - - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MIBLEsensors[i].type==NLIGHT || MIBLEsensors[i].type==MJYD2S){ - MIBLEsensors[i].NMT++; - } - } - - uint32_t _idx = 0; - uint32_t _activeBeacons = 0; - for (auto &_beacon : MIBLEbeacons){ - _idx++; - if(_beacon.active == false) continue; - _activeBeacons++; - _beacon.time++; - Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _beacon.time); - XdrvRulesProcess(); - } - if(_activeBeacons==0) MI32.mode.activeBeacon = 0; - - if(MI32.state.beaconScanCounter!=0){ - MI32.state.beaconScanCounter--; - if(MI32.state.beaconScanCounter==0){ - MI32showScanResults(); - } - } - - if(MI32.mode.shallShowStatusInfo == 1){ - MI32StatusInfo(); - } - - if(restart){ - _counter = 0; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 1; - MI32.mode.willReadBatt = 0; - MI32.mode.willConnect = 0; - return; - } - - if (MI32.mode.shallSetTime) { - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - if (MI32.mode.willSetTime == 0){ - MI32.mode.willSetTime = 1; - MI32StartTask(MI32_TASK_TIME); - } - } - - if (MI32.mode.shallSetUnit) { - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - if (MI32.mode.willSetUnit == 0){ - MI32.mode.willSetUnit = 1; - MI32StartTask(MI32_TASK_UNIT); - } - } - - if (MI32.mode.willReadBatt) return; - - if (_counter>MI32.period) { - _counter = 0; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 1; - } - - if(MI32.mode.connected == 1 || MI32.mode.willConnect == 1) return; - - if(MIBLEsensors.size()==0) { - if (MI32.mode.runningScan == 0 && MI32.mode.canScan == 1) MI32StartTask(MI32_TASK_SCAN); - return; - } - - if(_counter==0) { - - MI32.state.sensor = _nextSensorSlot; - MI32.mode.canScan = 0; - - if (MI32.mode.connected || MI32.mode.willConnect) return; - _nextSensorSlot++; - MI32.mode.canConnect = 1; - if(MI32.mode.connected == 0) { - if (MI32.mode.shallReadBatt) { - - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("will connect to %s"),kMI32DeviceType[MIBLEsensors[MI32.state.sensor].type-1] ); - - MI32StartTask(MI32_TASK_BATT); - } -#ifndef USE_MI_DECRYPTION - else{ - MI32StartTask(MI32_TASK_CONN); - } -#endif - } - if (_nextSensorSlot>(MIBLEsensors.size()-1)) { - _nextSensorSlot= 0; - _counter++; - if (MI32.mode.shallReadBatt){ - MI32.mode.shallReadBatt = 0; - } - MI32.mode.canConnect = 0; - MI32.mode.canScan = 1; - } - } - else _counter++; - if (MI32.state.sensor>MIBLEsensors.size()-1) { - _nextSensorSlot = 0; - MI32.mode.canScan = 1; - } - MI32StartTask(MI32_TASK_SCAN); -} - - - - - -bool MI32Cmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_MI32); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MI32), disp_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMI32_Commands); - switch (command_code) { - case CMND_MI32_PERIOD: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload==1) { - MI32EverySecond(true); - XdrvMailbox.payload = MI32.period; - } - else { - MI32.period = XdrvMailbox.payload; - } - } - else { - XdrvMailbox.payload = MI32.period; - } - Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MI32_TIME: - if (XdrvMailbox.data_len > 0) { - if(MIBLEsensors.size()>XdrvMailbox.payload){ - if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02 || MIBLEsensors[XdrvMailbox.payload].type == MHOC303){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: will set Time"),D_CMND_MI32); - MI32.state.sensor = XdrvMailbox.payload; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - MI32.mode.shallSetTime = 1; - MI32.mode.willSetTime = 0; - } - } - } - Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MI32_UNIT: - if (XdrvMailbox.data_len > 0) { - if(MIBLEsensors.size()>XdrvMailbox.payload){ - if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02 || MIBLEsensors[XdrvMailbox.payload].type == MHOC303){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: will set Unit"),D_CMND_MI32); - MI32.state.sensor = XdrvMailbox.payload; - MI32.mode.canScan = 0; - MI32.mode.canConnect = 0; - MI32.mode.shallSetUnit = 1; - MI32.mode.willSetUnit = 0; - } - } - } - Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MI32_PAGE: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload == 0) XdrvMailbox.payload = MI32.perPage; - MI32.perPage = XdrvMailbox.payload; - } - else XdrvMailbox.payload = MI32.perPage; - Response_P(S_JSON_MI32_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MI32_BATTERY: - MI32EverySecond(true); - MI32.mode.shallReadBatt = 1; - MI32.mode.canConnect = 1; - XdrvMailbox.payload = MI32.period; - Response_P(S_JSON_MI32_COMMAND, command, ""); - break; -#ifdef USE_MI_DECRYPTION - case CMND_MI32_KEY: - if (XdrvMailbox.data_len==44){ - MI32AddKey(XdrvMailbox.data); - Response_P(S_JSON_MI32_COMMAND, command, XdrvMailbox.data); - } - break; -#endif - case CMND_MI32_BEACON: - if (XdrvMailbox.data_len == 0) { - switch(XdrvMailbox.index){ - case 0: - MI32.state.beaconScanCounter = 8; - Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("\"scanning\"")); - break; - case 1: case 2: case 3: case 4: - char _MAC[18]; - ToHex_P(MIBLEbeacons[XdrvMailbox.index-1].MAC,6,_MAC,18,':'); - Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,_MAC); - break; - } - } - else { - if(XdrvMailbox.data_len == 12 || XdrvMailbox.data_len == 17){ - switch(XdrvMailbox.index){ - case 1: case 2: case 3: case 4: - MI32addBeacon(XdrvMailbox.index,XdrvMailbox.data); - break; - } - } - Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,XdrvMailbox.data); - } - break; - - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - - -const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916{m}%u%s / %u{e}"; -const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; -const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; -const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; -const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; -const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; -const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; -const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; - -void MI32Show(bool json) -{ - if (json) { -#ifdef USE_HOME_ASSISTANT - bool _noSummarySave = MI32.option.noSummary; - bool _minimalSummarySave = MI32.option.minimalSummary; - if(hass_mode==2){ - if(MI32.option.holdBackFirstAutodiscovery){ - if(!MI32.mode.firstAutodiscoveryDone){ - MI32.mode.firstAutodiscoveryDone = 1; - return; - } - } - MI32.option.noSummary = false; - MI32.option.minimalSummary = false; - } -#endif - - if(!MI32.mode.triggeredTele){ - MI32.mode.shallClearResults=1; - if(MI32.option.noSummary) return; - } - - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MI32.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; - if(MI32.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; - - ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), - kMI32DeviceType[MIBLEsensors[i].type-1], - MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); - - uint32_t _positionCurlyBracket = strlen(mqtt_data); - - if((!MI32.mode.triggeredTele && !MI32.option.minimalSummary)||MI32.mode.triggeredTele){ - bool tempHumSended = false; - if(MIBLEsensors[i].feature.tempHum){ - if(MIBLEsensors[i].eventType.tempHum || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ - if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp) -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - ResponseAppend_P(PSTR(",")); - ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); - tempHumSended = true; - } - } - } - if(MIBLEsensors[i].feature.temp && !tempHumSended){ - if(MIBLEsensors[i].eventType.temp || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].temp) -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - char temperature[FLOATSZ]; - dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - } - } - if(MIBLEsensors[i].feature.hum && !tempHumSended){ - if(MIBLEsensors[i].eventType.hum || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].hum) -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - char hum[FLOATSZ]; - dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); - } - } - } - if (MIBLEsensors[i].feature.lux){ - if(MIBLEsensors[i].eventType.lux || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ - if (MIBLEsensors[i].lux!=0x0ffffff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); -#ifdef USE_HOME_ASSISTANT - if (MIBLEsensors[i].lux==0x0ffffff) MI32nullifyEndOfMQTT_DATA(); -#endif - } - } - } - if (MIBLEsensors[i].feature.moist){ - if(MIBLEsensors[i].eventType.moist || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ - if (MIBLEsensors[i].moisture!=0xff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); -#ifdef USE_HOME_ASSISTANT - if (MIBLEsensors[i].moisture==0xff) MI32nullifyEndOfMQTT_DATA(); -#endif - } - } - } - if (MIBLEsensors[i].feature.fert){ - if(MIBLEsensors[i].eventType.fert || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ - if (MIBLEsensors[i].fertility!=0xffff -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); -#ifdef USE_HOME_ASSISTANT - if (MIBLEsensors[i].fertility==0xffff) MI32nullifyEndOfMQTT_DATA(); -#endif - } - } - } - if (MIBLEsensors[i].feature.Btn){ - if(MIBLEsensors[i].eventType.Btn -#ifdef USE_HOME_ASSISTANT - ||(hass_mode==2) -#endif - ){ - ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); - } - } - } - if (MIBLEsensors[i].feature.PIR){ - if(MIBLEsensors[i].eventType.motion || !MI32.mode.triggeredTele){ - if(MI32.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); - ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); - } - else if(MIBLEsensors[i].eventType.noMotion && MI32.mode.triggeredTele){ - ResponseAppend_P(PSTR(",\"PIR\":0")); - } - } - - if (MIBLEsensors[i].type == FLORA && !MI32.mode.triggeredTele) { - if (MIBLEsensors[i].firmware[0] != '\0') { - ResponseAppend_P(PSTR(",\"Firmware\":\"%s\""), MIBLEsensors[i].firmware); - } - } - - if (MIBLEsensors[i].feature.NMT || !MI32.mode.triggeredTele){ - if(MIBLEsensors[i].eventType.NMT){ - ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); - } - } - if (MIBLEsensors[i].feature.bat){ - if(MIBLEsensors[i].eventType.bat || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ - if (MIBLEsensors[i].bat != 0x00 -#ifdef USE_HOME_ASSISTANT - ||(hass_mode!=-1) -#endif - ) { - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); -#ifdef USE_HOME_ASSISTANT - if (MIBLEsensors[i].bat == 0x00) MI32nullifyEndOfMQTT_DATA(); -#endif - } - } - } - if (MI32.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].RSSI); - - if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); - ResponseAppend_P(PSTR("}")); - mqtt_data[_positionCurlyBracket] = '{'; - MIBLEsensors[i].eventType.raw = 0; - if(MIBLEsensors[i].shallSendMQTT==1){ - MIBLEsensors[i].shallSendMQTT = 0; - continue; - } - } - MI32.mode.triggeredTele = 0; - - uint32_t _idx = 0; - for (auto _beacon : MIBLEbeacons){ - _idx++; - if(!_beacon.active) continue; - char _MAC[18]; - ToHex_P(_beacon.MAC,6,_MAC,18,':'); - ResponseAppend_P(PSTR(",\"Beacon%u\":{\"MAC\":\"%s\",\"CID\":\"0x%04x\",\"SVC\":\"0x%04x\"," - "\"UUID\":\"0x%04x\",\"Time\":%u,\"RSSI\":%d}"), - _idx,_MAC,_beacon.CID,_beacon.SVC,_beacon.UUID,_beacon.time,_beacon.RSSI); - } -#ifdef USE_HOME_ASSISTANT - if(hass_mode==2){ - MI32.option.noSummary = _noSummarySave; - MI32.option.minimalSummary = _minimalSummarySave; - } -#endif -#ifdef USE_WEBSERVER - } else { - static uint16_t _page = 0; - static uint16_t _counter = 0; - int32_t i = _page * MI32.perPage; - uint32_t j = i + MI32.perPage; - if (j+1>MIBLEsensors.size()){ - j = MIBLEsensors.size(); - } - char stemp[5] ={0}; - if (MIBLEsensors.size()-(_page*MI32.perPage)>1 && MI32.perPage!=1) { - sprintf_P(stemp,"-%u",j); - } - if (MIBLEsensors.size()==0) i=-1; - - WSContentSend_PD(HTTP_MI32, i+1,stemp,MIBLEsensors.size()); - for (i; iFLORA) { - if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)) { - WSContentSend_THD(kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); - } - } -#ifdef USE_MI_DECRYPTION - if (MIBLEsensors[i].type==NLIGHT || MIBLEsensors[i].type==MJYD2S) { -#else - if (MIBLEsensors[i].type==NLIGHT) { -#endif - WSContentSend_PD(HTTP_EVENTS, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].events); - if(MIBLEsensors[i].NMT>0) WSContentSend_PD(HTTP_NMT, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].NMT); - } - if (MIBLEsensors[i].lux!=0x00ffffff) { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux); - } - if(MIBLEsensors[i].bat!=0x00){ - WSContentSend_PD(HTTP_BATTERY, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); - } - if (MIBLEsensors[i].type==YEERC){ - WSContentSend_PD(HTTP_LASTBUTTON, kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].Btn); - } - } - _counter++; - if(_counter>3) { - _page++; - _counter=0; - } - if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; } - if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; } - - - uint32_t _idx=0; - if(MI32.mode.activeBeacon){ - WSContentSend_PD(HTTP_MI32_HL); - char _sbeacon[] = "Beacon1"; - for (auto &_beacon : MIBLEbeacons){ - _idx++; - if(!_beacon.active) continue; - WSContentSend_PD(HTTP_MI32_HL); - _sbeacon[6] = _idx + 0x30; - char _MAC[18]; - ToHex_P(_beacon.MAC,6,_MAC,18,':'); - WSContentSend_PD(HTTP_MI32_MAC, _sbeacon, D_MAC_ADDRESS, _MAC); - WSContentSend_PD(HTTP_RSSI, _sbeacon, _beacon.RSSI); - if(_beacon.CID!=0) WSContentSend_PD(PSTR("{s}Beacon%u CID{m}0x%04X{e}"),_idx, _beacon.CID); - if(_beacon.SVC!=0) WSContentSend_PD(PSTR("{s}Beacon%u SVC{m}0x%04X{e}"),_idx, _beacon.SVC); - if(_beacon.UUID!=0) WSContentSend_PD(PSTR("{s}Beacon%u UUID{m}0x%04X{e}"),_idx, _beacon.UUID); - WSContentSend_PD(PSTR("{s}Beacon%u Time{m}%u seconds{e}"),_idx, _beacon.time); - } - } -#endif - } -} - - - - - -bool Xsns62(uint8_t function) -{ - bool result = false; - if (FUNC_INIT == function){ - MI32Init(); - } - - if (MI32.mode.init) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - MI32Every50mSecond(); - break; - case FUNC_EVERY_SECOND: - MI32EverySecond(false); - break; - case FUNC_COMMAND: - result = MI32Cmd(); - break; - case FUNC_JSON_APPEND: - MI32Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MI32Show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" -# 42 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" -#ifdef ESP8266 - -#ifdef USE_HM10 - -#define XSNS_62 62 - -#include -#include - -TasmotaSerial *HM10Serial; -#define HM10_BAUDRATE 115200 - -#define HM10_MAX_TASK_NUMBER 12 -uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; - -#define HM10_MAX_RX_BUF 384 - -struct { - uint8_t current_task_delay; - uint8_t last_command; - uint16_t perPage = 4; - uint16_t firmware; - uint32_t period; - uint32_t serialSpeed; - union { - uint32_t time; - uint8_t timebuf[4]; - }; - uint16_t autoScanInterval; - struct { - uint32_t awaiting:8; - uint32_t init:1; - uint32_t pending_task:1; - uint32_t connected:1; - uint32_t subscribed:1; - uint32_t autoScan:1; - uint32_t shallTriggerTele:1; - uint32_t triggeredTele:1; - } mode; - struct { - uint8_t sensor; - - } state; - struct { - uint32_t allwaysAggregate:1; - uint32_t showRSSI:1; - uint32_t ignoreBogusBattery:1; - uint32_t noSummary:1; - uint32_t minimalSummary:1; - uint32_t noRealTime:1; - } option; - char *rxBuffer; -} HM10; - -#pragma pack(1) - -struct LYWSD0x_HT_t{ - uint16_t temp; - uint8_t hum; - uint16_t volt; -}; -struct CGD1_HT_t{ - uint8_t spare; - uint16_t temp; - uint16_t hum; -}; -struct Flora_TLMF_t{ - uint16_t temp; - uint8_t spare; - uint32_t lux; - uint8_t moist; - uint16_t fert; - uint32_t ID; -}; - -struct mi_beacon_t{ - uint16_t frame; - uint16_t productID; - uint8_t counter; - uint8_t MAC[6]; - uint8_t spare; - uint8_t type; - uint8_t ten; - uint8_t size; - union { - struct{ - uint16_t temp; - uint16_t hum; - }HT; - uint8_t bat; - uint16_t temp; - uint16_t hum; - uint32_t lux; - uint8_t moist; - uint16_t fert; - uint32_t NMT; - struct{ - uint16_t num; - uint8_t longPress; - }Btn; - }; - uint8_t padding[12]; -}; - -struct ATCPacket_t{ - uint8_t MAC[6]; - int16_t temp; - uint8_t hum; - uint8_t batPer; - uint16_t batMV; - uint8_t frameCnt; -}; - -#pragma pack(0) - -struct mi_sensor_t{ - uint8_t type; - uint8_t lastCnt; - uint8_t shallSendMQTT; - uint8_t showedUp; - uint8_t MAC[6]; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t PIR:1; - uint32_t Btn:1; - }; - uint32_t raw; - } feature; - union { - struct { - uint32_t temp:1; - uint32_t hum:1; - uint32_t tempHum:1; - uint32_t lux:1; - uint32_t moist:1; - uint32_t fert:1; - uint32_t bat:1; - uint32_t NMT:1; - uint32_t motion:1; - uint32_t noMotion:1; - uint32_t Btn:1; - }; - uint32_t raw; - } eventType; - - int rssi; - uint32_t lastTime; - uint32_t lux; - float temp; - union { - struct { - uint8_t moisture; - uint16_t fertility; - char firmware[6]; - }; - struct { - float hum; - }; - struct { - uint16_t events; - uint32_t NMT; - }; - uint16_t Btn; - }; - union { - uint8_t bat; - }; -}; - - -std::vector MIBLEsensors; - - - - - -#define D_CMND_HM10 "HM10" - -const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; -const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; -const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto|Page"; - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03MMC 4 -#define CGG1 5 -#define CGD1 6 -#define NLIGHT 7 -#define MJYD2S 8 -#define YEERC 9 -#define MHOC401 10 -#define MHOC303 11 -#define ATC 12 - -#define HM10_TYPES 12 - -const uint16_t kHM10SlaveID[HM10_TYPES]={ - 0x0098, - 0x01aa, - 0x045b, - 0x055b, - 0x0347, - 0x0576, - 0x03dd, - 0x07f6, - 0x0153, - 0x0387, - 0x06d3, - 0x0a1c - }; - -const char kHM10DeviceType1[] PROGMEM = "Flora"; -const char kHM10DeviceType2[] PROGMEM = "MJ_HT_V1"; -const char kHM10DeviceType3[] PROGMEM = "LYWSD02"; -const char kHM10DeviceType4[] PROGMEM = "LYWSD03"; -const char kHM10DeviceType5[] PROGMEM = "CGG1"; -const char kHM10DeviceType6[] PROGMEM = "CGD1"; -const char kHM10DeviceType7[] PROGMEM = "NLIGHT"; -const char kHM10DeviceType8[] PROGMEM = "MJYD2S"; -const char kHM10DeviceType9[] PROGMEM = "YEERC"; -const char kHM10DeviceType10[] PROGMEM ="MHOC401"; -const char kHM10DeviceType11[] PROGMEM ="MHOC303"; -const char kHM10DeviceType12[] PROGMEM ="ATC"; - -const char * kHM10DeviceType[] PROGMEM = {kHM10DeviceType1,kHM10DeviceType2,kHM10DeviceType3,kHM10DeviceType4,kHM10DeviceType5,kHM10DeviceType6,kHM10DeviceType7,kHM10DeviceType8,kHM10DeviceType9,kHM10DeviceType10,kHM10DeviceType11,kHM10DeviceType12}; - - - - - -enum HM10_Commands { - CMND_HM10_DISC_SCAN, - CMND_HM10_AT, - CMND_HM10_PERIOD, - CMND_HM10_BAUD, - CMND_HM10_TIME, - CMND_HM10_AUTO, - CMND_HM10_PAGE - }; - -enum HM10_awaitData: uint8_t { - none = 0, - tempHumLY = 1, - TLMF = 2, - bat = 3, - tempHumCGD1 = 4, - discScan = 5, - tempHumMJ = 6 - }; - - - - - -#define TASK_HM10_NOTASK 0 -#define TASK_HM10_ROLE1 1 -#define TASK_HM10_IMME1 2 -#define TASK_HM10_RENEW 3 -#define TASK_HM10_RESET 4 -#define TASK_HM10_DISC 5 -#define TASK_HM10_CONN 6 -#define TASK_HM10_VERSION 7 -#define TASK_HM10_NAME 8 -#define TASK_HM10_FEEDBACK 9 -#define TASK_HM10_DISCONN 10 -#define TASK_HM10_SUB_L3 11 - -#define TASK_HM10_SCAN9 13 -#define TASK_HM10_UN_L3 14 - -#define TASK_HM10_READ_BT_L3 16 -#define TASK_HM10_SUB_L2 17 -#define TASK_HM10_UN_L2 18 -#define TASK_HM10_READ_BT_L2 19 -#define TASK_HM10_TIME_L2 20 -#define TASK_HM10_SHOW0 21 -#define TASK_HM10_READ_BF_FL 22 -#define TASK_HM10_CALL_TLMF_FL 23 -#define TASK_HM10_READ_TLMF_FL 24 -#define TASK_HM10_SUB_HT_CGD1 25 -#define TASK_HM10_UN_HT_CGD1 26 -#define TASK_HM10_READ_B_CGD1 27 - -#define TASK_HM10_READ_B_MJ 29 -#define TASK_HM10_SUB_HT_MJ 30 - -#define TASK_HM10_STATUS_EVENT 32 - -#define TASK_HM10_DONE 99 - - - - - -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ - HM10_TASK_LIST[slot][0] = task; - HM10_TASK_LIST[slot][1] = delay; - HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; - HM10.current_task_delay = HM10_TASK_LIST[0][1]; -} - -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ - HM10.last_command = HM10_TASK_LIST[slot][0]; - HM10_TASK_LIST[slot][0] = task; -} - -void HM10_ReverseMAC(uint8_t _mac[]){ - uint8_t _reversedMAC[6]; - for (uint8_t i=0; i<6; i++){ - _reversedMAC[5-i] = _mac[i]; - } - memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); -} - - - - - -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_ROLE1,1,1); - HM10_Launchtask(TASK_HM10_IMME1,2,1); - HM10_Launchtask(TASK_HM10_RESET,3,1); - HM10_Launchtask(TASK_HM10_VERSION,4,10); - HM10_Launchtask(TASK_HM10_SCAN9,5,2); - HM10_Launchtask(TASK_HM10_DISC,6,2); - HM10_Launchtask(TASK_HM10_STATUS_EVENT,7,2); - } - -void HM10_Discovery_Scan(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_DISC,1,1); - HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); - } - -void HM10_Read_LYWSD03(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L3,2,20); - HM10_Launchtask(TASK_HM10_UN_L3,3,80); - - HM10_Launchtask(TASK_HM10_DISCONN,4,5); - } - -void HM10_Read_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L2,2,20); - HM10_Launchtask(TASK_HM10_UN_L2,3,80); - HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Time_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,0); - HM10_Launchtask(TASK_HM10_CONN,1,5); - HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); - HM10_Launchtask(TASK_HM10_TIME_L2,3,20); - HM10_Launchtask(TASK_HM10_DISCONN,4,5); - } - -void HM10_Read_Flora(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,0); - HM10_Launchtask(TASK_HM10_CONN,1,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,2,5); - HM10_Launchtask(TASK_HM10_READ_BF_FL,3,20); - HM10_Launchtask(TASK_HM10_CALL_TLMF_FL,4,30); - HM10_Launchtask(TASK_HM10_DISCONN,5,10); - } - -void HM10_Read_CGD1(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_HT_CGD1,2,20); - HM10_Launchtask(TASK_HM10_UN_HT_CGD1,3,10); - HM10_Launchtask(TASK_HM10_READ_B_CGD1,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Read_MJ_HT_V1(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_READ_B_MJ,2,20); - HM10_Launchtask(TASK_HM10_SUB_HT_MJ,3,10); - HM10_Launchtask(TASK_HM10_DISCONN,4,5); - } -# 444 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" -uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){ - - DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type); - bool _success = false; - for (uint32_t i=0;ibegin(HM10.serialSpeed)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); - if (HM10Serial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("%s: claim HW"),D_CMND_HM10); - } - HM10_Reset(); - HM10.mode.pending_task = 1; - HM10.mode.init = 1; - HM10.period = Settings.tele_period; - DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); - - - HM10.option.noRealTime = 1; - HM10.option.allwaysAggregate = 1; - HM10.option.showRSSI = 0; - HM10.option.ignoreBogusBattery = 1; - HM10.option.noSummary = 0; - HM10.option.minimalSummary = 0; - - HM10.rxBuffer = new char[HM10_MAX_RX_BUF]; - } - return; -} - - - - - -void HM10parseMiBeacon(char * _buf, uint32_t _slot){ - float _tempFloat; - mi_beacon_t _beacon; - if (MIBLEsensors[_slot].type==MJ_HT_V1 || MIBLEsensors[_slot].type==CGG1){ - memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)-1); - memcpy((uint8_t*)&_beacon.MAC,(uint8_t*)&_beacon.MAC+1,6); - } - else{ - memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon)); - } - HM10_ReverseMAC(_beacon.MAC); - if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){ - if (MIBLEsensors[_slot].showedUp>3) return; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: remove garbage sensor"),D_CMND_HM10); - DEBUG_SENSOR_LOG(PSTR("%s i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors[_slot].MAC[5], MIBLEsensors[_slot].MAC[4],MIBLEsensors[_slot].MAC[3],MIBLEsensors[_slot].MAC[2],MIBLEsensors[_slot].MAC[1],MIBLEsensors[_slot].MAC[0]); - DEBUG_SENSOR_LOG(PSTR("%s n: %x %x %x %x %x %x"),D_CMND_HM10, _beacon.MAC[5], _beacon.MAC[4], _beacon.MAC[3],_beacon.MAC[2],_beacon.MAC[1],_beacon.MAC[0]); - MIBLEsensors.erase(MIBLEsensors.begin()+_slot); - return; - } - if (MIBLEsensors[_slot].showedUp<4) MIBLEsensors[_slot].showedUp++; - - DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); - DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); - - - if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){ - DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); - return; - } - DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot); - switch(_beacon.type){ - case 0x01: - MIBLEsensors[_slot].Btn=_beacon.Btn.num + (_beacon.Btn.longPress/2)*6; - MIBLEsensors[_slot].eventType.Btn = 1; - - break; - case 0x04: - _tempFloat=(float)(_beacon.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); - MIBLEsensors[_slot].eventType.temp = 1; - } - DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); - break; - case 0x06: - _tempFloat=(float)(_beacon.hum)/10.0f; - if(_tempFloat<101){ - MIBLEsensors[_slot].hum=_tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); - MIBLEsensors[_slot].eventType.hum = 1; - } - DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum); - break; - case 0x07: - if(MIBLEsensors[_slot].type==MJYD2S){ - MIBLEsensors[_slot].eventType.noMotion = 1; - } - MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; - DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); - break; - case 0x08: - if(_beacon.moist<101){ - MIBLEsensors[_slot].moisture=_beacon.moist; - DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); - MIBLEsensors[_slot].eventType.moist = 1; - } - DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); - break; - case 0x09: - if(_beacon.fert<65535){ - MIBLEsensors[_slot].fertility=_beacon.fert; - DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); - MIBLEsensors[_slot].eventType.fert = 1; - } - DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); - break; - case 0x0a: - if(_beacon.bat<101){ - MIBLEsensors[_slot].bat = _beacon.bat; - DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); - MIBLEsensors[_slot].eventType.bat = 1; - } - DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat); - break; - case 0x0d: - _tempFloat=(float)(_beacon.HT.temp)/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); - } - _tempFloat=(float)(_beacon.HT.hum)/10.0f; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); - break; - } - if(MIBLEsensors[_slot].eventType.raw == 0) return; - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; -} - -void HM10parseATC(char * _buf, uint32_t _slot){ - ATCPacket_t *_packet = (ATCPacket_t*)_buf; - if(memcmp(_packet->MAC,MIBLEsensors.at(_slot).MAC,6)!=0) return; - MIBLEsensors.at(_slot).temp = (float)(__builtin_bswap16(_packet->temp))/10.0f; - MIBLEsensors.at(_slot).hum = (float)_packet->hum; - MIBLEsensors.at(_slot).bat = _packet->batPer; - MIBLEsensors[_slot].shallSendMQTT = 1; -} - -char* HM10ParseResponse(char *buf, uint16_t bufsize) { - if (!strncmp(buf,"HMSoft",6)) { - const char* _fw = "000"; - memcpy((void *)_fw,(void *)(buf+8),3); - HM10.firmware = atoi(_fw); - DEBUG_SENSOR_LOG(PSTR("%s: Firmware: %d"),D_CMND_HM10, HM10.firmware); - return buf; - } - char * _pos = nullptr; - uint32_t _idx = 0; - char _subStr[] = "SA:"; - while(_pos = (char*) memchr(buf+_idx, 'I', 60)){ - _idx=_pos-buf; - if(memcmp(&_pos+1,_subStr,3)){ - break; - } - } - if(_pos) { - uint8_t _newMacArray[6] = {0}; - memcpy((void *)_newMacArray,(void *)(_pos+4),6); - uint32_t _rssi = 255- (uint8_t)(_pos[11]); - HM10_ReverseMAC(_newMacArray); - DEBUG_SENSOR_LOG(PSTR("%s: MAC-array: %02x%02x%02x%02x%02x%02x"),D_CMND_HM10,_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); - uint16_t _type=0xffff; - - for (_idx =10;_idx<32;_idx++){ - if((uint8_t)_pos[_idx] == 0xfe){ - if((uint8_t)_pos[_idx-2] == 0x16 && (uint8_t)_pos[_idx-1] == 0x95){ - _pos = _pos+_idx+1; - _type = (uint8_t)_pos[3]*256 + (uint8_t)_pos[2]; - DEBUG_SENSOR_LOG(PSTR("%s: type %04x _ %02x %02x"),D_CMND_HM10,_type, _pos[3],_pos[2]); - break; - } - } - else if ((uint8_t)_pos[_idx] == 0x1a){ - if ((uint8_t)_pos[_idx+1] == 0x18){ - if((uint8_t)_pos[_idx+4] == 0x95 && (uint8_t)_pos[_idx+3] == 0x16) continue; - _type = 0xa1c; - _pos = _pos+_idx+2; - break; - } - } - } - uint16_t _slot = MIBLEgetSensorSlot(_newMacArray, _type, _rssi); - if(_slot!=0xff){ - if (_type==0xa1c) HM10parseATC(_pos,_slot); - else HM10parseMiBeacon(_pos,_slot); - } - if(bufsize>64) return _pos+12; - else return nullptr; - } - else if (strstr(buf, "LOST")){ - HM10.current_task_delay = 0; - HM10.mode.connected = false; - } - else if (strstr(buf, "CONNF")){ - HM10.mode.connected = false; - HM10.current_task_delay = 0; - } - else if (strstr(buf, "CONN")){ - HM10.current_task_delay = 0; - } - else { - DEBUG_SENSOR_LOG(PSTR("%s: empty response"),D_CMND_HM10); - return buf; - } - return _pos; -} - -void HM10readHT_LY(char *_buf){ - - if(_buf[0]==0x4f && _buf[1]==0x4b) return; - if(_buf[0] != 0 && _buf[1] != 0){ - LYWSD0x_HT_t *packet = (LYWSD0x_HT_t*)_buf; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u"),D_CMND_HM10,packet->temp,packet->hum); - uint32_t _slot = HM10.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(packet->temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - HM10.mode.awaiting = none; - HM10.current_task_delay = 0; - MIBLEsensors[_slot].showedUp=255; - } - _tempFloat=(float)packet->hum; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("LYWSD0x: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - if (MIBLEsensors[_slot].type == LYWSD03MMC || MIBLEsensors[_slot].type == MHOC401){ - MIBLEsensors[_slot].bat = ((float)packet->volt-2100.0f)/12.0f; - MIBLEsensors[_slot].eventType.bat = 1; - } - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; - } -} - -void HM10readHT_CGD1(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0]==0x4f && _buf[1]==0x4b) return; - if(_buf[0] == 0){ - if(_buf[1]==0 && _buf[2]==0 && _buf[3]==0 && _buf[4]==0) return; - CGD1_HT_t *_packet = (CGD1_HT_t*)_buf; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H * 100: %u"),D_CMND_HM10,_packet->temp,_packet->hum); - uint32_t _slot = HM10.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(_packet->temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - HM10.mode.awaiting = none; - HM10.current_task_delay = 0; - MIBLEsensors[_slot].showedUp=255; - } - _tempFloat=(float)_packet->hum/100.0f; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; - } -} - -void HM10readHT_MJ_HT_V1(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0]!=0x54 && _buf[1]!=0x3d) return; - - - uint32_t _temp = (atoi(_buf+2) * 10) + atoi(_buf+5); - uint32_t _hum = (atoi(_buf+9) * 10) + atoi(_buf+12); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, H * 10: %u"),D_CMND_HM10,_temp,_hum); - uint32_t _slot = HM10.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)_temp/10.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; - HM10.mode.awaiting = none; - HM10.current_task_delay = 0; - MIBLEsensors[_slot].showedUp=255; - } - _tempFloat=(float)_hum/10.0f; - if(_tempFloat<100){ - MIBLEsensors[_slot].hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated")); - } - MIBLEsensors[_slot].eventType.tempHum = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; -} - -void HM10readTLMF(char *_buf){ - AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)_buf,16); - Flora_TLMF_t *_packet = (Flora_TLMF_t*)_buf; - if(_packet->ID==0xFB003C02){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, L: %u, M: %u, F: %u"),D_CMND_HM10,_packet->temp,_packet->lux,_packet->moist,_packet->fert); - uint32_t _slot = HM10.state.sensor; - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - MIBLEsensors[_slot].showedUp=255; - - static float _tempFloat; - _tempFloat=(float)(_packet->temp)/10.0f; - MIBLEsensors[_slot].temp=_tempFloat; - - MIBLEsensors[_slot].lux = _packet->lux; - MIBLEsensors[_slot].moisture = _packet->moist; - MIBLEsensors[_slot].fertility = _packet->fert; - MIBLEsensors[_slot].eventType.temp = 1; - MIBLEsensors[_slot].eventType.lux = 1; - MIBLEsensors[_slot].eventType.moist = 1; - MIBLEsensors[_slot].eventType.fert = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; - - HM10.mode.awaiting = none; - HM10.current_task_delay = 0; - } -} - -bool HM10readBat(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0]==0x4f && _buf[1]==0x4b) return false; - uint32_t _slot = HM10.state.sensor; - - - - if(_buf[0] != 0){ - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_HM10,_buf[0]); - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - if(_buf[0]<101){ - MIBLEsensors[_slot].bat=_buf[0]; - MIBLEsensors[_slot].showedUp=255; - MIBLEsensors[_slot].eventType.bat = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - HM10.mode.shallTriggerTele = 1; - return true; - } - } - return false; -} - - - - - -bool HM10SerialHandleFeedback(){ - bool success = false; - uint32_t i = 0; - - while(HM10Serial->available()) { - if(iread(); - } - i++; - success = true; - } - - if(i==0){ - if(HM10.mode.shallTriggerTele){ - HM10.mode.shallTriggerTele=0; - if(HM10.option.noRealTime){ - HM10.mode.triggeredTele=0; - return success; - } - HM10.mode.triggeredTele=1; - HM10triggerTele(); - } - return success; - } - - switch (HM10.mode.awaiting){ - case bat: - if (HM10.mode.connected) { - if (HM10readBat(HM10.rxBuffer)){ - HM10.mode.awaiting = none; - HM10.current_task_delay = 0; - } - } - break; - case tempHumLY: - if (HM10.mode.connected) HM10readHT_LY(HM10.rxBuffer); - break; - case tempHumCGD1: - if (HM10.mode.connected) HM10readHT_CGD1(HM10.rxBuffer); - break; - case TLMF: - if (HM10.mode.connected) HM10readTLMF(HM10.rxBuffer); - break; - case discScan: - if(success) { - char *_src = HM10ParseResponse(HM10.rxBuffer,i); - if(_src){ - HM10ParseResponse(_src,i-(_src-HM10.rxBuffer)); - } - } - break; - case tempHumMJ: - if (HM10.mode.connected) HM10readHT_MJ_HT_V1(HM10.rxBuffer); - break; - case none: - if(success) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: response: %s"),D_CMND_HM10, (char *)HM10.rxBuffer); - - - - HM10ParseResponse(HM10.rxBuffer,i); - } - break; - } - memset(HM10.rxBuffer,0,i); - return success; -} - - - - - -void HM10_TaskEvery100ms(){ - if (HM10.current_task_delay == 0) { - uint8_t i = 0; - bool runningTaskLoop = true; - while (runningTaskLoop) { - switch(HM10_TASK_LIST[i][0]) { - case TASK_HM10_ROLE1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set role to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+ROLE1"); - break; - case TASK_HM10_IMME1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set imme to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+IMME1"); - break; - case TASK_HM10_DISC: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: start discovery"),D_CMND_HM10); - HM10.current_task_delay = 90; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaiting = discScan; - HM10Serial->write("AT+DISA?"); - break; - case TASK_HM10_VERSION: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read version"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+VERR?"); - break; - case TASK_HM10_NAME: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read name"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+NAME?"); - break; - case TASK_HM10_CONN: - char _con[20]; - sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors[HM10.state.sensor].MAC[0],MIBLEsensors[HM10.state.sensor].MAC[1],MIBLEsensors[HM10.state.sensor].MAC[2],MIBLEsensors[HM10.state.sensor].MAC[3],MIBLEsensors[HM10.state.sensor].MAC[4],MIBLEsensors[HM10.state.sensor].MAC[5]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: %s connect %s"),D_CMND_HM10,kHM10DeviceType[MIBLEsensors[HM10.state.sensor].type-1],_con); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write(_con); - HM10.mode.awaiting = none; - HM10.mode.connected = true; - break; - case TASK_HM10_DISCONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: disconnect"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT"); - break; - case TASK_HM10_RESET: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: Reset Device"),D_CMND_HM10); - HM10Serial->write("AT+RESET"); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - break; - case TASK_HM10_SUB_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); - HM10.current_task_delay = 25; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - HM10.mode.awaiting = tempHumLY; - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON0037"); - break; - case TASK_HM10_UN_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaiting = none; - HM10Serial->write("AT+NOTIFYOFF0037"); - break; - case TASK_HM10_SUB_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); - HM10.current_task_delay = 85; - HM10.mode.awaiting = tempHumLY; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_ON003C"); - else HM10Serial->write("AT+NOTIFY_ON004B"); - break; - case TASK_HM10_UN_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaiting = none; - if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+NOTIFY_OFF003C"); - else HM10Serial->write("AT+NOTIFY_OFF004B"); - break; - case TASK_HM10_TIME_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set time"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.time = Rtc.utc_time; - HM10Serial->write("AT+SEND_DATAWR002F"); - HM10Serial->write(HM10.timebuf,4); - HM10Serial->write(Rtc.time_timezone / 60); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); - break; -# 1079 "/workspace/Tasmota/tasmota/xsns_62_MI_HM10.ino" - case TASK_HM10_READ_BT_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0043"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - if(MIBLEsensors[HM10.state.sensor].type == LYWSD02) HM10Serial->write("AT+READDATA0043?"); - else HM10Serial->write("AT+READDATA0052?"); - HM10.mode.awaiting = bat; - break; - case TASK_HM10_READ_BF_FL: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0038"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0038?"); - HM10.mode.awaiting = bat; - break; - case TASK_HM10_CALL_TLMF_FL: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: write to handle 0033"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_READ_TLMF_FL,i); - runningTaskLoop = false; - HM10Serial->write("AT+SEND_DATAWR0033"); - HM10Serial->write(0xa0); - HM10Serial->write(0x1f); - HM10.mode.awaiting = none; - break; - case TASK_HM10_READ_TLMF_FL: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0035"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0035?"); - HM10.mode.awaiting = TLMF; - break; - case TASK_HM10_READ_B_CGD1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0011"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0011?"); - HM10.mode.awaiting = bat; - break; - case TASK_HM10_SUB_HT_CGD1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe 4b"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaiting = tempHumCGD1; - HM10Serial->write("AT+NOTIFY_ON004b"); - break; - case TASK_HM10_UN_HT_CGD1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe 4b"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaiting = none; - HM10Serial->write("AT+NOTIFYOFF004b"); - break; - case TASK_HM10_SCAN9: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: scan time to 9"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+SCAN9"); - break; - case TASK_HM10_READ_B_MJ: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0x18"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0018?"); - HM10.mode.awaiting = bat; - break; - case TASK_HM10_SUB_HT_MJ: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe to 0x0f"),D_CMND_HM10); - HM10.current_task_delay = 10; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON000F"); - HM10.mode.awaiting = tempHumMJ; - break; - case TASK_HM10_FEEDBACK: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: get response"),D_CMND_HM10); - HM10SerialHandleFeedback(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - runningTaskLoop = false; - break; - case TASK_HM10_STATUS_EVENT: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: show status"),D_CMND_HM10); - HM10StatusInfo(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - runningTaskLoop = false; - break; - case TASK_HM10_DONE: - - - if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { - DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); - for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); - HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; - HM10_TASK_LIST[j][1] = 0; - } - runningTaskLoop = false; - HM10.mode.pending_task = 0; - break; - } - } - i++; - } - } - else { - HM10.current_task_delay--; - } -} - -void HM10StatusInfo() { - - - - - - - Response_P(PSTR("{%s:{\"found\":%u}}"), D_CMND_HM10, MIBLEsensors.size()); - XdrvRulesProcess(); -} - - - - - - -void HM10EverySecond(bool restart){ - static uint32_t _counter = 0; - static uint32_t _nextSensorSlot = 0; - static uint32_t _lastDiscovery = 0; - - if(restart){ - _counter = 0; - _lastDiscovery = 0; - return; - } - - if(HM10.firmware == 0) return; - if(HM10.mode.pending_task == 1) return; - if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return; - - if((HM10.period-_counter)>15 && HM10.mode.autoScan) { - if(_counter-_lastDiscovery>HM10.autoScanInterval){ - HM10_Discovery_Scan(); - HM10.mode.pending_task = 1; - _counter+=12; - _lastDiscovery = _counter; - return; - } - } - - if(_counter==0) { - HM10.state.sensor = _nextSensorSlot; - _nextSensorSlot++; - HM10.mode.pending_task = 1; - switch(MIBLEsensors[HM10.state.sensor].type){ - case FLORA: - HM10_Read_Flora(); - break; - case MJ_HT_V1: case CGG1: - HM10_Read_MJ_HT_V1(); - break; - case LYWSD02: case MHOC303: - HM10_Read_LYWSD02(); - break; - case LYWSD03MMC: case MHOC401: - HM10_Read_LYWSD03(); - break; - case CGD1: - HM10_Read_CGD1(); - break; - default: - HM10.mode.pending_task = 0; - } - if (HM10.state.sensor==MIBLEsensors.size()-1) { - _nextSensorSlot= 0; - _counter++; - } - DEBUG_SENSOR_LOG(PSTR("%s: active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); - } - else _counter++; - if (_counter>HM10.period) { - _counter = 0; - _lastDiscovery = 0; - } -} - - - - - -bool HM10Cmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_HM10); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); - switch (command_code) { - case CMND_HM10_PERIOD: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload==1) { - HM10EverySecond(true); - XdrvMailbox.payload = HM10.period; - } - else { - HM10.period = XdrvMailbox.payload; - } - } - else { - XdrvMailbox.payload = HM10.period; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_AUTO: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload>0) { - HM10.mode.autoScan = 1; - HM10.autoScanInterval = XdrvMailbox.payload; - } - else { - HM10.mode.autoScan = 0; - HM10.autoScanInterval = 0; - } - } - else { - XdrvMailbox.payload = HM10.autoScanInterval; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_BAUD: - if (XdrvMailbox.data_len > 0) { - HM10.serialSpeed = XdrvMailbox.payload; - HM10Serial->begin(HM10.serialSpeed); - } - else { - XdrvMailbox.payload = HM10.serialSpeed; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_TIME: - if (XdrvMailbox.data_len > 0) { - if(MIBLEsensors.size()>XdrvMailbox.payload){ - if(MIBLEsensors[XdrvMailbox.payload].type == LYWSD02){ - HM10.state.sensor = XdrvMailbox.payload; - HM10_Time_LYWSD02(); - } - } - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_PAGE: - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload == 0) XdrvMailbox.payload = HM10.perPage; - HM10.perPage = XdrvMailbox.payload; - } - else XdrvMailbox.payload = HM10.perPage; - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_AT: - HM10Serial->write("AT"); - if (strlen(XdrvMailbox.data)!=0) { - HM10Serial->write("+"); - HM10Serial->write(XdrvMailbox.data); - Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); - } - else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); - break; - case CMND_HM10_DISC_SCAN: - HM10_Discovery_Scan(); - Response_P(S_JSON_HM10_COMMAND, command, ""); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - -void HM10triggerTele(void){ - HM10.mode.triggeredTele = 1; - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - #ifdef USE_RULES - RulesTeleperiod(); - #endif - } -} - - - - - -const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}"; -const char HTTP_HM10_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; -const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; -const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; - -void HM10Show(bool json) -{ - if (json) { - if(!HM10.mode.triggeredTele){ - if(HM10.option.noSummary) return; - } - - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(HM10.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; - if(HM10.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; - - ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), - kHM10DeviceType[MIBLEsensors[i].type-1], - MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); - - uint32_t _positionCurlyBracket = strlen(mqtt_data); - - if((!HM10.mode.triggeredTele && !HM10.option.minimalSummary)||HM10.mode.triggeredTele){ - bool tempHumSended = false; - if(MIBLEsensors[i].feature.tempHum){ - if(MIBLEsensors[i].eventType.tempHum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ - if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)) { - ResponseAppend_P(PSTR(",")); - ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum); - tempHumSended = true; - } - } - } - if(MIBLEsensors[i].feature.temp && !tempHumSended){ - if(MIBLEsensors[i].eventType.temp || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].temp)) { - char temperature[FLOATSZ]; - dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - } - } - if(MIBLEsensors[i].feature.hum && !tempHumSended){ - if(MIBLEsensors[i].eventType.hum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) { - if (!isnan(MIBLEsensors[i].hum)) { - char hum[FLOATSZ]; - dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum); - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum); - } - } - } - if (MIBLEsensors[i].feature.lux){ - if(MIBLEsensors[i].eventType.lux || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ - if (MIBLEsensors[i].lux!=0x0ffffff) { - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux); - } - } - } - if (MIBLEsensors[i].feature.moist){ - if(MIBLEsensors[i].eventType.moist || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ - if (MIBLEsensors[i].moisture!=0xff) { - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture); - } - } - } - if (MIBLEsensors[i].feature.fert){ - if(MIBLEsensors[i].eventType.fert || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ - if (MIBLEsensors[i].fertility!=0xffff) { - ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility); - } - } - } - if (MIBLEsensors[i].feature.Btn){ - if(MIBLEsensors[i].eventType.Btn){ - ResponseAppend_P(PSTR(",\"Btn\":%u"),MIBLEsensors[i].Btn); - } - } - } - if (MIBLEsensors[i].feature.PIR){ - if(MIBLEsensors[i].eventType.motion || !HM10.mode.triggeredTele){ - if(HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"PIR\":1")); - ResponseAppend_P(PSTR(",\"Events\":%u"),MIBLEsensors[i].events); - } - else if(MIBLEsensors[i].eventType.noMotion && HM10.mode.triggeredTele){ - ResponseAppend_P(PSTR(",\"PIR\":0")); - } - } - - if (MIBLEsensors[i].type == FLORA && !HM10.mode.triggeredTele) { - if (MIBLEsensors[i].firmware[0] != '\0') { - ResponseAppend_P(PSTR(",\"Firmware\":\"%s\""), MIBLEsensors[i].firmware); - } - } - - if (MIBLEsensors[i].feature.NMT || !HM10.mode.triggeredTele){ - if(MIBLEsensors[i].eventType.NMT){ - ResponseAppend_P(PSTR(",\"NMT\":%u"), MIBLEsensors[i].NMT); - } - } - if (MIBLEsensors[i].feature.bat){ - if(MIBLEsensors[i].eventType.bat || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){ - if (MIBLEsensors[i].bat != 0x00) { - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat); - } - } - } - if (HM10.option.showRSSI && HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi); - - - if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); - ResponseAppend_P(PSTR("}")); - mqtt_data[_positionCurlyBracket] = '{'; - MIBLEsensors[i].eventType.raw = 0; - if(MIBLEsensors[i].shallSendMQTT==1){ - MIBLEsensors[i].shallSendMQTT = 0; - continue; - } - } - HM10.mode.triggeredTele = 0; - -#ifdef USE_WEBSERVER - } else { - static uint16_t _page = 0; - static uint16_t _counter = 0; - int32_t i = _page * HM10.perPage; - uint32_t j = i + HM10.perPage; - if (j+1>MIBLEsensors.size()){ - j = MIBLEsensors.size(); - } - char stemp[5] ={0}; - if (MIBLEsensors.size()-(_page*HM10.perPage)>1 && HM10.perPage!=1) { - sprintf_P(stemp,"-%u",j); - } - if (MIBLEsensors.size()==0) i=-1; - - WSContentSend_PD(HTTP_HM10, HM10.firmware, i+1,stemp,MIBLEsensors.size()); - for (i; iFLORA){ - if(!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)){ - WSContentSend_THD(kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum); - } - } - if(MIBLEsensors[i].bat!=0x00){ - WSContentSend_PD(HTTP_BATTERY, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat); - } - WSContentSend_PD(HTTP_RSSI, kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].rssi); - } - _counter++; - if(_counter>3) { - _page++; - _counter=0; - } - if(MIBLEsensors.size()%HM10.perPage==0 && _page==MIBLEsensors.size()/HM10.perPage) _page=0; - if(_page>MIBLEsensors.size()/HM10.perPage) _page=0; -#endif - } -} - - - - - -bool Xsns62(uint8_t function) -{ - bool result = false; - - if (PinUsed(GPIO_HM10_RX) && PinUsed(GPIO_HM10_TX)) { - switch (function) { - case FUNC_INIT: - HM10SerialInit(); - break; - case FUNC_EVERY_50_MSECOND: - HM10SerialHandleFeedback(); - break; - case FUNC_EVERY_100_MSECOND: - if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { - HM10_TaskEvery100ms(); - } - break; - case FUNC_EVERY_SECOND: - HM10EverySecond(false); - break; - case FUNC_COMMAND: - result = HM10Cmd(); - break; - case FUNC_JSON_APPEND: - HM10Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HM10Show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" -# 21 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" -#ifdef USE_I2C -#ifdef USE_AHT1x -# 45 "/workspace/Tasmota/tasmota/xsns_63_aht1x.ino" -#define XSNS_63 63 -#define XI2C_43 43 - -#define AHT1X_ADDR1 0x38 -#define AHT1X_ADDR2 0x39 - -#define AHT1X_MAX_SENSORS 2 - -#define AHT_HUMIDITY_CONST 100 -#define AHT_TEMPERATURE_CONST 200 -#define AHT_TEMPERATURE_OFFSET 50 -#define KILOBYTE_CONST 1048576.0f - -#define AHT1X_CMD_DELAY 40 -#define AHT1X_RST_DELAY 30 -#define AHT1X_MEAS_DELAY 80 - -#ifdef USE_AHT2x - #define AHTX_CMD 0xB1 - const char ahtTypes[] PROGMEM = "AHT2X|AHT2X"; -#else - #define AHTX_CMD 0xE1 - const char ahtTypes[] PROGMEM = "AHT1X|AHT1X"; -#endif - -uint8_t AHTSetCalCmd[3] = { AHTX_CMD, 0x08, 0x00 }; -uint8_t AHTSetCycleCmd[3] = { AHTX_CMD, 0x28, 0x00 }; -uint8_t AHTMeasureCmd[3] = { 0xAC, 0x33, 0x00 }; -uint8_t AHTResetCmd = 0xBA; - -struct { - bool write_ok = false; - uint8_t addresses[2] = { AHT1X_ADDR1, AHT1X_ADDR2 }; - uint8_t count = 0; - uint8_t Pcount = 0; -} aht1x; - -struct { - float humidity = NAN; - float temperature = NAN; - uint8_t address; - char types[6]; -} aht1x_sensors[AHT1X_MAX_SENSORS]; - -bool AHT1XWrite(uint8_t aht1x_idx) { - Wire.beginTransmission(aht1x_sensors[aht1x_idx].address); - Wire.write(AHTMeasureCmd, 3); - if (Wire.endTransmission() != 0) - return false; - return true; -} - -bool AHT1XRead(uint8_t aht1x_idx) { - uint8_t data[6]; - Wire.requestFrom(aht1x_sensors[aht1x_idx].address, (uint8_t) 6); - - for(uint8_t i = 0; Wire.available() > 0; i++) { - data[i] = Wire.read(); - } - if (data[0] & 0x80) - return false; - - aht1x_sensors[aht1x_idx].humidity = (((data[1] << 12)| (data[2] << 4) | data[3] >> 4) * AHT_HUMIDITY_CONST / KILOBYTE_CONST); - aht1x_sensors[aht1x_idx].temperature = ((AHT_TEMPERATURE_CONST * (((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]) / KILOBYTE_CONST) - AHT_TEMPERATURE_OFFSET); - - return (!isnan(aht1x_sensors[aht1x_idx].temperature) && !isnan(aht1x_sensors[aht1x_idx].humidity) && (aht1x_sensors[aht1x_idx].humidity != 0)); -} - - - - - -void AHT1XPoll(void) { - aht1x.Pcount++; - switch (aht1x.Pcount) { - case 10: - aht1x.write_ok = AHT1XWrite(0); - break; - case 11: - if (aht1x.write_ok) AHT1XRead(0); - aht1x.Pcount = 0; - break; - } -} - -unsigned char AHT1XReadStatus(uint8_t aht1x_address) { - uint8_t result = 0; - - - - - Wire.requestFrom(aht1x_address, (uint8_t) 1); - result = Wire.read(); - return result; -} - -void AHT1XReset(uint8_t aht1x_address) { - Wire.beginTransmission(aht1x_address); - Wire.write(AHTResetCmd); - Wire.endTransmission(); - delay(AHT1X_RST_DELAY); -} - - -bool AHT1XInit(uint8_t aht1x_address) { - Wire.beginTransmission(aht1x_address); - Wire.write(AHTSetCalCmd, 3); - if (Wire.endTransmission() != 0) - return false; - delay(AHT1X_CMD_DELAY); - if(AHT1XReadStatus(aht1x_address) & 0x08) - return true; - return false; -} - -void AHT1XDetect(void) { - for (uint8_t i = 0; i < AHT1X_MAX_SENSORS; i++) { - if (!I2cSetDevice(aht1x.addresses[i])) {continue;} - if (AHT1XInit(aht1x.addresses[i])) { - aht1x_sensors[aht1x.count].address = aht1x.addresses[i]; - GetTextIndexed(aht1x_sensors[aht1x.count].types, sizeof(aht1x_sensors[aht1x.count].types), i, ahtTypes); - I2cSetActiveFound(aht1x_sensors[aht1x.count].address, aht1x_sensors[aht1x.count].types); - aht1x.count++; - break; - } - } -} - -void AHT1XShow(bool json) { - for (uint32_t i = 0; i < aht1x.count; i++) { - float tem = ConvertTemp(aht1x_sensors[i].temperature); - float hum = ConvertHumidity(aht1x_sensors[i].humidity); - char types[11]; - snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), aht1x_sensors[i].types, IndexSeparator(), aht1x_sensors[i].address); - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, tem, hum); - } -} - - - - - -bool Xsns63(uint8_t function) -{ - if (!I2cEnabled(XI2C_43)) { return false; } - bool result = false; - - if (FUNC_INIT == function) { - AHT1XDetect(); - } - else if (aht1x.count) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - AHT1XPoll(); - break; - case FUNC_JSON_APPEND: - AHT1XShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AHT1XShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_64_hrxl.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_64_hrxl.ino" -#ifdef USE_HRXL - - - - - - - -#define XSNS_64 64 - -#include - -#define HRXL_READ_TIMEOUT 400 - -TasmotaSerial *HRXLSerial = nullptr; - -uint32_t hrxl_distance_mm = 0; -bool hrxl_found = false; - - - -void HRXLInit(void) -{ - hrxl_found = false; - if (PinUsed(GPIO_HRXL_RX)) - { - HRXLSerial = new TasmotaSerial(Pin(GPIO_HRXL_RX), -1, 1); - if (HRXLSerial->begin(9600)) - { - if (HRXLSerial->hardwareSerial()) - ClaimSerial(); - hrxl_found = true; - HRXLSerial->setTimeout(HRXL_READ_TIMEOUT); - } - } -} - -void HRXLEverySecond(void) -{ - if (!hrxl_found) - return; - - int num_read=0; - int sum=0; - while (HRXLSerial->available()>5) - { - if (HRXLSerial->read() != 'R') - continue; - - int d = HRXLSerial->parseInt(); - if (d >= 30 && d<=5000) - { - sum += d; - num_read++; - } - } - if (num_read>1) - hrxl_distance_mm = int(sum / num_read); - -} - - -void HRXLShow(bool json) -{ - char types[5] = "HRXL"; - if (json) - { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_DISTANCE "\":%d}"), types, hrxl_distance_mm); -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_RANGE, types, hrxl_distance_mm); -#endif - } -} - - - - - -bool Xsns64(uint8_t function) -{ - if (!PinUsed(GPIO_HRXL_RX)) { return false; } - - switch (function) - { - case FUNC_INIT: - HRXLInit(); - break; - case FUNC_EVERY_SECOND: - HRXLEverySecond(); - break; - case FUNC_JSON_APPEND: - HRXLShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HRXLShow(0); - break; -#endif - } - return false; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -#ifdef USE_I2C -#ifdef USE_HDC1080 -# 31 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -#define XSNS_65 65 -#define XI2C_45 45 - -#define HDC1080_ADDR 0x40 - - - -#define HDC_REG_TEMP 0x00 -#define HDC_REG_RH 0x01 -#define HDC_REG_CONFIG 0x02 -#define HDC_REG_SERIAL1 0xFB -#define HDC_REG_SERIAL2 0xFC -#define HDC_REG_SERIAL3 0xFD -#define HDC_REG_MAN_ID 0xFE -#define HDC_REG_DEV_ID 0xFF - - - -#define HDC1080_MAN_ID 0x5449 -#define HDC1080_DEV_ID 0x1050 - - - -#define HDC1080_RST_ON 0x8000 -#define HDC1080_HEAT_ON 0x2000 -#define HDC1080_MODE_ON 0x1000 -#define HDC1080_TRES_11 0x400 -#define HDC1080_HRES_11 0x100 -#define HDC1080_HRES_8 0x80 - - - -#define HDC1080_CONV_TIME 15 -#define HDC1080_TEMP_MULT 0.0025177 -#define HDC1080_RH_MULT 0.0015258 -#define HDC1080_TEMP_OFFSET 40.0 - -const char* hdc_type_name = "HDC1080"; -uint16_t hdc_manufacturer_id = 0; -uint16_t hdc_device_id = 0; - -float hdc_temperature = 0.0; -float hdc_humidity = 0.0; - -uint8_t hdc_valid = 0; - -bool is_reading = false; -uint32_t hdc_next_read; - - - - - -uint16_t HdcReadDeviceId(void) { - return I2cRead16(HDC1080_ADDR, HDC_REG_DEV_ID); -} - - - - - -uint16_t HdcReadManufacturerId(void) { - return I2cRead16(HDC1080_ADDR, HDC_REG_MAN_ID); -} - - - - -void HdcConfig(uint16_t config) { - I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, config); -} - - - - - - - -void HdcReset(void) { - uint16_t current = I2cRead16(HDC1080_ADDR, HDC_REG_CONFIG); - - - - - current |= 0x8000; - - I2cWrite16(HDC1080_ADDR, HDC_REG_CONFIG, current); - - delay(HDC1080_CONV_TIME); -} -# 132 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -int8_t HdcTransactionOpen(uint8_t addr, uint8_t reg) { - Wire.beginTransmission((uint8_t) addr); - Wire.write((uint8_t) reg); - return Wire.endTransmission(); -} -# 147 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -int8_t HdcTransactionClose(uint8_t addr, uint8_t *reg_data, uint16_t len) { - if (len != Wire.requestFrom((uint8_t) addr, (uint8_t) len)) { - return 1; - } - - while (len--) { - *reg_data = (uint8_t)Wire.read(); - reg_data++; - } - - return 0; -} - - - - - -void HdcInit(void) { - HdcReset(); - HdcConfig(HDC1080_MODE_ON); -} - - - - - -bool HdcTriggerRead(void) { - int8_t status = HdcTransactionOpen(HDC1080_ADDR, HDC_REG_TEMP); - - hdc_next_read = millis() + HDC1080_CONV_TIME; - - if(status) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcTriggerRead: failed to open the transaction for HDC_REG_TEMP. Status = %d"), status); - - return false; - } - - is_reading = true; - - return true; -} -# 197 "/workspace/Tasmota/tasmota/xsns_65_hdc1080.ino" -bool HdcRead(void) { - int8_t status = 0; - uint8_t sensor_data[4]; - uint16_t temp_data = 0; - uint16_t rh_data = 0; - - is_reading = false; - - status = HdcTransactionClose(HDC1080_ADDR, sensor_data, 4); - - if(status) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: failed to read HDC_REG_TEMP. Status = %d"), status); - - return false; - } - - temp_data = (uint16_t) ((sensor_data[0] << 8) | sensor_data[1]); - rh_data = (uint16_t) ((sensor_data[2] << 8) | sensor_data[3]); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcRead: temperature raw data: 0x%04x; humidity raw data: 0x%04x"), temp_data, rh_data); - - - - hdc_temperature = ConvertTemp(HDC1080_TEMP_MULT * (float) (temp_data) - HDC1080_TEMP_OFFSET); - - hdc_humidity = HDC1080_RH_MULT * (float) (rh_data); - - if (hdc_humidity > 100) { hdc_humidity = 100.0; } - if (hdc_humidity < 0) { hdc_humidity = 0.01; } - hdc_humidity = ConvertHumidity(hdc_humidity); - - hdc_valid = SENSOR_MAX_MISS; - - return true; -} - - - - - - -void HdcDetect(void) { - if (I2cActive(HDC1080_ADDR)) { - - - return; - } - - hdc_manufacturer_id = HdcReadManufacturerId(); - hdc_device_id = HdcReadDeviceId(); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HdcDetect: detected device with manufacturerId = 0x%04X and deviceId = 0x%04X"), hdc_manufacturer_id, hdc_device_id); - - if (hdc_device_id == HDC1080_DEV_ID) { - HdcInit(); - I2cSetActiveFound(HDC1080_ADDR, hdc_type_name); - } -} - - - - - - -void HdcEverySecond(void) { - if (uptime &1) { - if (!HdcTriggerRead()) { - AddLogMissed((char*) hdc_type_name, hdc_valid); - } - } -} - - - - - - -void HdcShow(bool json) { - if (hdc_valid) { - TempHumDewShow(json, (0 == tele_period), hdc_type_name, hdc_temperature, hdc_humidity); - } -} - - - - - -bool Xsns65(uint8_t function) -{ - if (!I2cEnabled(XI2C_45)) { - - - return false; - } - - bool result = false; - - if (FUNC_INIT == function) { - HdcDetect(); - } - else if (hdc_device_id) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if(is_reading && TimeReached(hdc_next_read)) { - if(!HdcRead()) { - AddLogMissed((char*) hdc_type_name, hdc_valid); - } - } - break; - case FUNC_EVERY_SECOND: - HdcEverySecond(); - break; - case FUNC_JSON_APPEND: - HdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HdcShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_66_iAQ.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_66_iAQ.ino" -#ifdef USE_I2C -#ifdef USE_IAQ - -#define XSNS_66 66 -#define XI2C_46 46 - -#define I2_ADR_IAQ 0x5a - -#define IAQ_STATUS_OK 0x00 -#define IAQ_STATUS_BUSY 0x01 -#define IAQ_STATUS_WARM 0x10 -#define IAQ_STATUS_ERR 0x80 -#define IAQ_STATUS_I2C_ERR 0xFF - -struct { - int32_t resistance; - uint16_t pred; - uint16_t Tvoc; - uint8_t status; - bool ready; -} iAQ; - -void IAQ_Init(void) -{ - if (!I2cSetDevice(I2_ADR_IAQ)) { return; } - I2cSetActiveFound(I2_ADR_IAQ, "IAQ"); - iAQ.ready = true; -} - -void IAQ_Read(void) -{ - uint8_t buf[9]; - buf[2] = IAQ_STATUS_I2C_ERR; - Wire.requestFrom((uint8_t)I2_ADR_IAQ,sizeof(buf)); - for( uint32_t i=0; i<9; i++ ) { - buf[i]= Wire.read(); - } - - iAQ.pred = (buf[0]<<8) + buf[1]; - iAQ.status = buf[2]; - iAQ.resistance = ((uint32_t)buf[3]<<24) + ((uint32_t)buf[4]<<16) + ((uint32_t)buf[5]<<8) + (uint32_t)buf[6]; - iAQ.Tvoc = (buf[7]<<8) + buf[8]; -} - - - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_IAQ[] PROGMEM = - "{s}iAQ-Core " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}iAQ-Core " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; - -const char HTTP_SNS_IAQ_ERROR[] PROGMEM = - "{s}iAQ-Core {m} %s {e}"; -#endif - -void IAQ_Show(uint8_t json) -{ - IAQ_Read(); - - if (json) { - if (iAQ.status!=IAQ_STATUS_OK){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("iAQ: " D_ERROR " %x" ),iAQ.status); - return; - } - else { - ResponseAppend_P(PSTR(",\"IAQ\":{\"" D_JSON_ECO2 "\":%u,\"" D_JSON_TVOC "\":%u,\"" D_JSON_RESISTANCE "\":%u}"), iAQ.pred, iAQ.Tvoc, iAQ.resistance); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, iAQ.pred); -#endif - } -#ifdef USE_WEBSERVER - } else { - switch(iAQ.status){ - case IAQ_STATUS_OK: - WSContentSend_PD(HTTP_SNS_IAQ, iAQ.pred, iAQ.Tvoc); - break; - case IAQ_STATUS_WARM: - WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_START); - break; - default: - WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_ERROR); - } -#endif - } -} - - - - - -bool Xsns66(byte function) -{ - if (!I2cEnabled(XI2C_46)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - IAQ_Init(); - } - else if (iAQ.ready) { - switch (function) { - case FUNC_JSON_APPEND: - IAQ_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - IAQ_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_67_as3935.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_67_as3935.ino" -#ifdef USE_I2C -#ifdef USE_AS3935 - - - - - - -#define XSNS_67 67 -#define XI2C_48 48 - -#define D_NAME_AS3935 "AS3935" -#define AS3935_ADDR 0x03 - - -#define PWR_REG 0x00, 0x01, 0 -#define AFE_GB 0x00, 0x3E, 0 -#define WDTH 0x01, 0x0F, 0 -#define NF_LEVEL 0x01, 0x70, 4 -#define SPIKE_REJECT 0x02, 0x0F, 0 -#define MIN_NUM_LIGH 0x02, 0x30, 4 -#define DISTURBER 0x03, 0x20, 5 -#define LCO_FDIV 0x03, 0xC0, 6 -#define IRQ_TBL 0x03, 0x0F, 0 -#define ENERGY_RAW_1 0x04, 0xFF, 0 -#define ENERGY_RAW_2 0x05, 0xFF, 0 -#define ENERGY_RAW_3 0x06, 0x1F, 0 -#define LGHT_DIST 0x07, 0x3F, 0 -#define DISP_TRCO 0x08, 0x20, 5 -#define DISP_SRCO 0x08, 0x40, 6 -#define DISP_LCO 0x08, 0x80, 7 -#define TUNE_CAPS 0x08, 0x0F, 0 -#define CAL_TRCO_NOK 0x3A, 0x40, 6 -#define CAL_TRCO_DONE 0x3A, 0x80, 7 -#define CAL_SRCO_NOK 0x3B, 0x40, 6 -#define CAL_SRCO_DONE 0x3B, 0x80, 7 - - -#define RESET_DEFAULT 0x3C, 0x96 -#define CALIBATE_RCO 0x3D, 0x96 - - -#define INDOORS 0x24 -#define OUTDOORS 0x1C - - -#define SETREG00MASK 0x3E -#define SETREG03MASK 0xF0 - - -const char HTTP_SNS_AS3935_ENERGY[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_ENERGY " {m}%d{e}"; -const char HTTP_SNS_AS3935_DISTANZ[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_DISTANCE " {m}%u " D_UNIT_KILOMETER "{e}"; -const char HTTP_SNS_AS3935_VRMS[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_VRMS "{m}%#4u (%d){e}"; - -const char HTTP_SNS_AS3935_OUTDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_OUTDOORS " {e}"; -const char HTTP_SNS_AS3935_INDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_INDOORS " {e}"; -const char* const HTTP_SNS_AS3935_GAIN[] PROGMEM = {HTTP_SNS_AS3935_INDOORS, HTTP_SNS_AS3935_OUTDOORS}; - -const char HTTP_SNS_AS3935_DIST_ON[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_ON " {e}"; -const char HTTP_SNS_AS3935_DIST_OFF[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_OFF " {e}"; -const char* const HTTP_SNS_AS3935_DISTURBER[] PROGMEM = {HTTP_SNS_AS3935_DIST_OFF, HTTP_SNS_AS3935_DIST_ON}; - -const char HTTP_SNS_AS3935_EMPTY[] PROGMEM = "{s}%s " D_AS3935_NOMESS "{e}"; -const char HTTP_SNS_AS3935_OUT[] PROGMEM = "{s}%s " D_AS3935_OUT "{e}"; -const char HTTP_SNS_AS3935_NOT[] PROGMEM = "{s}%s " D_AS3935_NOT "{e}"; -const char HTTP_SNS_AS3935_ABOVE[] PROGMEM = "{s}%s " D_AS3935_ABOVE "{e}"; -const char HTTP_SNS_AS3935_NOISE[] PROGMEM = "{s}%s " D_AS3935_NOISE "{e}"; -const char HTTP_SNS_AS3935_DISTURB[] PROGMEM = "{s}%s " D_AS3935_DISTDET "{e}"; -const char HTTP_SNS_AS3935_INTNOEV[] PROGMEM = "{s}%s " D_AS3935_INTNOEV "{e}"; -const char HTTP_SNS_AS3935_FLICKER[] PROGMEM = "{s}%s " D_AS3935_FLICKER "{e}"; -const char HTTP_SNS_AS3935_POWEROFF[] PROGMEM = "{s}%s " D_AS3935_POWEROFF "{e}"; - -const char HTTP_SNS_AS3935_MSG[] PROGMEM = "{s}%s " D_AS3935_LIGHT " " D_AS3935_APRX " %d " D_UNIT_KILOMETER " " D_AS3935_AWAY "{e}"; -const char* const HTTP_SNS_AS3935_TABLE_1[] PROGMEM = { HTTP_SNS_AS3935_EMPTY, HTTP_SNS_AS3935_MSG, HTTP_SNS_AS3935_OUT, HTTP_SNS_AS3935_NOT, HTTP_SNS_AS3935_ABOVE, HTTP_SNS_AS3935_NOISE, HTTP_SNS_AS3935_DISTURB, HTTP_SNS_AS3935_INTNOEV, HTTP_SNS_AS3935_FLICKER, HTTP_SNS_AS3935_POWEROFF }; - -const char JSON_SNS_AS3935_EVENTS[] PROGMEM = ",\"%s\":{\"" D_JSON_EVENT "\":%d,\"" D_JSON_DISTANCE "\":%d,\"" D_JSON_ENERGY "\":%u,\"" D_JSON_STAGE "\":%d}"; - -const char* const S_JSON_AS3935_COMMAND_ONOFF[] PROGMEM = {"\"" D_AS3935_OFF "\"","\"" D_AS3935_ON"\""}; -const char* const S_JSON_AS3935_COMMAND_GAIN[] PROGMEM = {"\"" D_AS3935_INDOORS "\"", "\"" D_AS3935_OUTDOORS "\""}; -const char* const S_JSON_AS3935_COMMAND_CAL[] PROGMEM = {"" D_AS3935_CAL_FAIL "","" D_AS3935_CAL_OK ""}; - -const char S_JSON_AS3935_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%s}}"; -const char S_JSON_AS3935_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%d}}"; -const char S_JSON_AS3935_COMMAND_SETTINGS[] PROGMEM = "{\"AS3935_Settings\":{\"Gain\":%s,\"NFfloor\":%d,\"uVrms\":%d,\"Tunecaps\":%d,\"MinNumLight\":%d,\"Rejektion\":%d,\"Wdthreshold\":%d,\"MinNFstage\":%d,\"NFAutoTime\":%d,\"DisturberAutoTime\":%d,\"Disturber\":%s,\"NFauto\":%s,\"Disturberauto\":%s,\"NFautomax\":%s,\"Mqttlightevent\":%s,\"Mqttnoirqevent\":%s}}"; - -const char kAS3935_Commands[] PROGMEM = "power|setnf|setminstage|setml|default|setgain|settunecaps|setrej|setwdth|disttime|nftime|disturber|autonf|autodisturber|autonfmax|lightevent|noirqevent|settings|calibrate"; - -const uint8_t AS3935_VrmsIndoor[] PROGMEM = { 28, 45, 62, 78, 95, 112, 130, 146 }; -const uint16_t AS3935_VrmsOutdoor[] PROGMEM = { 390, 630, 860, 1100, 1140, 1570, 1800, 2000 }; - -enum AS3935_Commands { - CMND_AS3935_POWER, - CMND_AS3935_SET_NF, - CMND_AS3935_SET_MINNF, - CMND_AS3935_SET_MINLIGHT, - CMND_AS3935_SET_DEF, - CMND_AS3935_SET_GAIN, - CMND_AS3935_SET_TUNE, - CMND_AS3935_SET_REJ, - CMND_AS3935_SET_WDTH, - CMND_AS3935_DISTTIME, - CMND_AS3935_NFTIME, - CMND_AS3935_SET_DISTURBER, - CMND_AS3935_NF_AUTOTUNE, - CMND_AS3935_DIST_AUTOTUNE, - CMND_AS3935_NF_ATUNE_BOTH, - CMND_AS3935_MQTT_LIGHT_EVT, - CMND_AS3935_MQTT_NO_IRQ_EVT, - CMND_AS3935_SETTINGS, - CMND_AS3935_CALIBRATE -}; - -struct { - bool active = false; - bool http_count_start = false; - bool poweroff = false; - volatile bool detected = false; - volatile bool dispLCO = false; - volatile uint8_t icount = 0; - uint8_t irq = 0; - uint8_t mqtt_event = 0; - uint8_t http_event = 0; - uint8_t http_time = 0; - uint8_t http_count = 0; - int16_t http_distance = 0; - int16_t distance = 0; - uint16_t nftimer = 0; - uint16_t disttimer = 0; - uint32_t intensity = 0; - uint32_t http_intensity = 0; - volatile uint32_t pulse = 0; -} as3935_sensor; - -void ICACHE_RAM_ATTR AS3935Isr(void) { - as3935_sensor.detected = true; - as3935_sensor.icount++; -} - - -uint8_t AS3935ReadRegister(uint8_t reg, uint8_t mask, uint8_t shift) { - uint8_t data = I2cRead8(AS3935_ADDR, reg); - if (reg == 0x08) Settings.as3935_sensor_cfg[4] = data; - if (reg <= 0x03) Settings.as3935_sensor_cfg[reg] = data; - return ((data & mask) >> shift); -} - -void AS3935WriteRegister(uint8_t reg, uint8_t mask, uint8_t shift, uint8_t data) { - uint8_t currentReg = I2cRead8(AS3935_ADDR, reg); - currentReg &= (~mask); - data <<= shift; - data &= mask; - data |= currentReg; - I2cWrite8(AS3935_ADDR, reg, data); - if (reg == 0x08) Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, reg); - if (reg <= 0x03) Settings.as3935_sensor_cfg[reg] = I2cRead8(AS3935_ADDR, reg); -} - - - -void ICACHE_RAM_ATTR AS3935CountFreq(void) { - if (as3935_sensor.dispLCO) - as3935_sensor.pulse++; -} - -bool AS3935AutoTuneCaps(uint8_t irqpin) { - int32_t maxtune = 17500; - uint8_t besttune; - uint8_t oldvalue = AS3935GetTuneCaps(); - AS3935WriteRegister(LCO_FDIV, 0); - delay(2); - for (uint8_t tune = 0; tune < 16; tune++) { - AS3935WriteRegister(TUNE_CAPS, tune); - delay(2); - AS3935WriteRegister(DISP_LCO, 1); - delay(1); - as3935_sensor.dispLCO = true; - as3935_sensor.pulse = 0; - attachInterrupt(digitalPinToInterrupt(irqpin), AS3935CountFreq, RISING); - delay(50); - as3935_sensor.dispLCO = false; - detachInterrupt(irqpin); - AS3935WriteRegister(DISP_LCO, 0); - int32_t currentfreq = 500000 - ((as3935_sensor.pulse * 20) * 16); - if(currentfreq < 0) currentfreq = -currentfreq; - if(maxtune > currentfreq) { - maxtune = currentfreq; - besttune = tune; - } - } - if (maxtune >= 17500) { - AS3935SetTuneCaps(oldvalue); - return false; - } - AS3935SetTuneCaps(besttune); - return true; -} - - - -bool AS3935CalRCOResult(void) { - if(AS3935ReadRegister(CAL_SRCO_NOK) || AS3935ReadRegister(CAL_TRCO_NOK)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: AS3935 Fatal Failure of TRCO or SRCO calibration")); - return false; - } - return true; -} - -bool AS3935CalibrateRCO(void) { - detachInterrupt(Pin(GPIO_AS3935)); - I2cWrite8(AS3935_ADDR, CALIBATE_RCO); - AS3935WriteRegister(DISP_TRCO, 1); - delay(2); - AS3935WriteRegister(DISP_TRCO, 0); - if(!AS3935CalRCOResult()) - return false; - attachInterrupt(digitalPinToInterrupt(Pin(GPIO_AS3935)), AS3935Isr, RISING); - return true; -} - -void AS3935Reset(void) { - I2cWrite8(AS3935_ADDR, RESET_DEFAULT); - delay(2); -} - -void AS3935PwrDown(void) { - AS3935WriteRegister(PWR_REG ,1); - detachInterrupt(Pin(GPIO_AS3935)); - as3935_sensor.poweroff = true; - as3935_sensor.mqtt_event = 9; - as3935_sensor.http_event = 9; - as3935_sensor.intensity = 0; - as3935_sensor.distance = 0; -} - -void AS3935PwrUp(void) { - AS3935WriteRegister(PWR_REG ,0); - AS3935CalibrateRCO(); - as3935_sensor.poweroff = false; - as3935_sensor.mqtt_event = 0; - as3935_sensor.http_event = 0; -} - -uint8_t AS3935GetPwrStat(void) { - if (AS3935ReadRegister(PWR_REG)) - return 0; - return 1; -} - -uint8_t AS3935GetIRQ(void) { - delay(2); - return AS3935ReadRegister(IRQ_TBL); -} - -uint8_t AS3935TranslIrq(uint8_t irq, uint8_t distance) { - switch(irq) { - case 0: return 7; - case 1: return 5; - case 4: return 6; - case 8: - if (distance == -1) return 2; - else if (distance == 0) return 3; - else if (distance == 1) return 4; - else return 1; - } - return 0; -} - -uint8_t AS3935GetDistance(void) { - return AS3935ReadRegister(LGHT_DIST); -} - -int16_t AS3935CalcDistance(void) { - uint8_t dist = AS3935GetDistance(); - switch (dist) { - case 0x3F: return -1; - case 0x00: return 0; - case 0x01: return 1; - default: - if (40 < dist) return 40; - return dist; - } -} - -uint32_t AS3935GetIntensity(void) { - uint32_t energy_raw = (AS3935ReadRegister(ENERGY_RAW_3) << 8); - energy_raw |= AS3935ReadRegister(ENERGY_RAW_2); - energy_raw <<= 8; - energy_raw |= AS3935ReadRegister(ENERGY_RAW_1); - return energy_raw; -} - -uint8_t AS3935GetTuneCaps(void) { - return AS3935ReadRegister(TUNE_CAPS); -} - -void AS3935SetTuneCaps(uint8_t tune) { - AS3935WriteRegister(TUNE_CAPS, tune); - delay(2); - AS3935CalibrateRCO(); -} - -uint8_t AS3935GetDisturber(void) { - return AS3935ReadRegister(DISTURBER); -} - -void AS3935SetDisturber(uint8_t stat) { - AS3935WriteRegister(DISTURBER, stat); -} - -uint8_t AS3935GetMinLights(void) { - return AS3935ReadRegister(MIN_NUM_LIGH); -} - -void AS3935SetMinLights(uint8_t stat) { - AS3935WriteRegister(MIN_NUM_LIGH, stat); -} - -uint8_t AS3935TransMinLights(uint8_t min_lights) { - if (5 > min_lights) return 0; - else if (9 > min_lights) return 1; - else if (16 > min_lights) return 2; - else return 3; -} - -uint8_t AS3935TranslMinLightsInt(uint8_t min_lights) { - switch (min_lights) { - case 0: return 1; - case 1: return 5; - case 2: return 9; - case 3: return 16; - } - return 0; -} - -uint8_t AS3935GetNoiseFloor(void) { - return AS3935ReadRegister(NF_LEVEL); -} - -void AS3935SetNoiseFloor(uint8_t noise) { - AS3935WriteRegister(NF_LEVEL , noise); -} - -uint8_t AS3935GetGain(void) { - if (AS3935ReadRegister(AFE_GB) == OUTDOORS) - return OUTDOORS; - return INDOORS; -} - -void AS3935SetGain(uint8_t room) { - AS3935WriteRegister(AFE_GB, room); -} - -uint8_t AS3935GetGainInt(void) { - if (AS3935ReadRegister(AFE_GB) == OUTDOORS) - return 1; - return 0; -} - -void AS3935CalcVrmsLevel(uint16_t &vrms, uint8_t &stage) { - uint8_t room = AS3935GetGain(); - uint8_t nflev = AS3935GetNoiseFloor(); - if (room == INDOORS) { - vrms = pgm_read_byte(AS3935_VrmsIndoor + nflev); - stage = nflev; - } else { - vrms = pgm_read_word(AS3935_VrmsOutdoor + nflev); - stage = nflev + 8; - } -} - -uint8_t AS3935GetSpikeRejection(void) { - return AS3935ReadRegister(SPIKE_REJECT); -} - -void AS3935SetSpikeRejection(uint8_t rej) { - AS3935WriteRegister(SPIKE_REJECT, rej); -} - -uint8_t AS3935GetWdth(void) { - return AS3935ReadRegister(WDTH); -} - -void AS3935SetWdth(uint8_t wdth) { - AS3935WriteRegister(WDTH, wdth); -} - -bool AS3935AutoTune(void) { - detachInterrupt(Pin(GPIO_AS3935)); - bool result = AS3935AutoTuneCaps(Pin(GPIO_AS3935)); - return result; -} - - - -bool AS3935LowerNoiseFloor(void) { - uint16_t vrms; - uint8_t stage; - AS3935CalcVrmsLevel(vrms, stage); - if (Settings.as3935_functions.nf_autotune_both) { - if (stage == 8 && stage > Settings.as3935_parameter.nf_autotune_min) { - AS3935SetGain(INDOORS); - AS3935SetNoiseFloor(7); - return true; - } - } - uint8_t noise = AS3935GetNoiseFloor(); - if (0 < noise && stage > Settings.as3935_parameter.nf_autotune_min) { - noise--; - AS3935SetNoiseFloor(noise); - return true; - } - return false; -} - -bool AS3935RaiseNoiseFloor(void) { - uint8_t noise = AS3935GetNoiseFloor(); - uint8_t room = AS3935GetGain(); - if (Settings.as3935_functions.nf_autotune_both) { - if (7 == noise && room == INDOORS) { - AS3935SetGain(OUTDOORS); - AS3935SetNoiseFloor(0); - return true; - } - } - if (7 > noise) { - noise++; - AS3935SetNoiseFloor(noise); - return true; - } - return false; -} - - - -bool AS3935SetDefault(void) { - AS3935Reset(); - AS3935SetDisturber(1); - AS3935SetNoiseFloor(7); - Settings.as3935_sensor_cfg[0] = I2cRead8(AS3935_ADDR, 0x00); - Settings.as3935_sensor_cfg[1] = I2cRead8(AS3935_ADDR, 0x01); - Settings.as3935_sensor_cfg[2] = I2cRead8(AS3935_ADDR, 0x02); - Settings.as3935_sensor_cfg[3] = I2cRead8(AS3935_ADDR, 0x03); - Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, 0x08); - - Settings.as3935_functions.data = 0x00; - Settings.as3935_parameter.nf_autotune_min = 0x00; - Settings.as3935_parameter.nf_autotune_time = 4; - Settings.as3935_parameter.dist_autotune_time = 1; - return true; -} - -void AS3935InitSettings(void) { - if(Settings.as3935_functions.nf_autotune) { - if(Settings.as3935_parameter.nf_autotune_min) { - if (Settings.as3935_parameter.nf_autotune_min > 7) { - AS3935SetGain(OUTDOORS); - AS3935SetNoiseFloor(Settings.as3935_parameter.nf_autotune_min - 8); - } else { - AS3935SetGain(INDOORS); - AS3935SetNoiseFloor(Settings.as3935_parameter.nf_autotune_min); - } - } - } - I2cWrite8(AS3935_ADDR, 0x00, Settings.as3935_sensor_cfg[0] & SETREG00MASK); - I2cWrite8(AS3935_ADDR, 0x01, Settings.as3935_sensor_cfg[1]); - I2cWrite8(AS3935_ADDR, 0x02, Settings.as3935_sensor_cfg[2]); - I2cWrite8(AS3935_ADDR, 0x03, Settings.as3935_sensor_cfg[3] & SETREG03MASK); - I2cWrite8(AS3935_ADDR, 0x08, Settings.as3935_sensor_cfg[4]); - delay(2); -} - -bool AS3935Setup(void) { - if (Settings.as3935_sensor_cfg[0] == 0x00) { - AS3935SetDefault(); - } else { - AS3935InitSettings(); - } - return AS3935CalibrateRCO(); -} - -bool AS3935init(void) { - AS3935Reset(); - uint8_t afe_gb = I2cRead8(AS3935_ADDR, 0x00) & SETREG00MASK; - if(INDOORS == afe_gb) - return true; - return false; -} - -void AS3935Detect(void) { - if (!I2cSetDevice(AS3935_ADDR)) return; - if (AS3935init()) { - I2cSetActiveFound(AS3935_ADDR, D_NAME_AS3935); - if (PinUsed(GPIO_AS3935)) { - pinMode(Pin(GPIO_AS3935), INPUT); - if (!AS3935Setup()) return; - as3935_sensor.active = true; - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: AS3935 GPIO Pin not defined!")); - } - } -} - -void AS3935EverySecond(void) { - if (!as3935_sensor.poweroff) { - if (as3935_sensor.detected) { - as3935_sensor.detected = false; - as3935_sensor.irq = AS3935GetIRQ(); - - if (10 > as3935_sensor.icount) { - switch (as3935_sensor.irq) { - case 1: - if (Settings.as3935_functions.nf_autotune) { - if (AS3935RaiseNoiseFloor()) - as3935_sensor.nftimer = 0; - } - break; - case 4: - if (Settings.as3935_functions.dist_autotune) { - AS3935SetDisturber(1); - } - break; - case 8: - as3935_sensor.intensity = AS3935GetIntensity(); - as3935_sensor.distance = AS3935CalcDistance(); - as3935_sensor.http_intensity = as3935_sensor.intensity; - as3935_sensor.http_distance = as3935_sensor.distance; - break; - } - - as3935_sensor.http_event = AS3935TranslIrq(as3935_sensor.irq, as3935_sensor.distance); - } else { - as3935_sensor.http_event = 8; - } - - - as3935_sensor.mqtt_event = as3935_sensor.http_event; - - switch (as3935_sensor.mqtt_event) { - case 5: - case 6: - if (!Settings.as3935_functions.mqtt_only_Light_Event) { - MqttPublishSensor(); - as3935_sensor.http_time = 10; - } - break; - case 7: - if (!Settings.as3935_functions.suppress_irq_no_Event) { - MqttPublishSensor(); - as3935_sensor.http_time = 10; - } - break; - default: - as3935_sensor.http_time = 30; - MqttPublishSensor(); - } - - as3935_sensor.irq = 0; - - as3935_sensor.intensity = 0; - as3935_sensor.distance = 0; - as3935_sensor.mqtt_event = 0; - - as3935_sensor.http_count_start = true; - as3935_sensor.http_count = 0; - } - as3935_sensor.icount = 0; - - - if (as3935_sensor.http_count_start) - as3935_sensor.http_count++; - - if (as3935_sensor.http_count > as3935_sensor.http_time) { - as3935_sensor.http_count_start = false; - as3935_sensor.http_intensity = 0; - as3935_sensor.http_distance = 0; - as3935_sensor.http_event = 0; - } - - if (Settings.as3935_functions.nf_autotune) { - as3935_sensor.nftimer++; - if (as3935_sensor.nftimer > Settings.as3935_parameter.nf_autotune_time * 60) { - AS3935LowerNoiseFloor(); - as3935_sensor.nftimer = 0; - } - } - - if (Settings.as3935_functions.dist_autotune) { - if (AS3935GetDisturber()) { - as3935_sensor.disttimer++; - } - if (as3935_sensor.disttimer >= Settings.as3935_parameter.dist_autotune_time * 60) { - AS3935SetDisturber(0); - as3935_sensor.disttimer = 0; - } - } - } -} - -bool AS3935Cmd(void) { - char command[CMDSZ]; - uint8_t name_len = strlen(D_NAME_AS3935); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_AS3935), name_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kAS3935_Commands); - switch (command_code) { - case CMND_AS3935_POWER: - if (XdrvMailbox.data_len) { - if (!XdrvMailbox.payload) { - AS3935PwrDown(); - } else { - AS3935PwrUp(); - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[AS3935GetPwrStat()]); - break; - case CMND_AS3935_SET_NF: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - AS3935SetNoiseFloor(XdrvMailbox.payload); - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetNoiseFloor()); - break; - case CMND_AS3935_SET_MINNF: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - Settings.as3935_parameter.nf_autotune_min = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_min); - break; - case CMND_AS3935_SET_MINLIGHT: - if (XdrvMailbox.data_len) { - AS3935SetMinLights(AS3935TransMinLights(XdrvMailbox.payload)); - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935TranslMinLightsInt(AS3935GetMinLights())); - break; - case CMND_AS3935_SET_DEF: - if (!XdrvMailbox.data_len) { - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935SetDefault()); - } - break; - case CMND_AS3935_SET_GAIN: - if (XdrvMailbox.data_len > 6) { - uint8_t data_len = strlen(D_AS3935_OUTDOORS); - if (!strncasecmp_P(XdrvMailbox.data, PSTR(D_AS3935_OUTDOORS), data_len)) { - AS3935SetGain(OUTDOORS); - } else { - AS3935SetGain(INDOORS); - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_GAIN[AS3935GetGainInt()]); - break; - case CMND_AS3935_SET_TUNE: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - AS3935SetTuneCaps(XdrvMailbox.payload); - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetTuneCaps()); - break; - case CMND_AS3935_SET_REJ: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - AS3935SetSpikeRejection(XdrvMailbox.payload); - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetSpikeRejection()); - break; - case CMND_AS3935_SET_WDTH: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - AS3935SetWdth(XdrvMailbox.payload); - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetWdth()); - break; - case CMND_AS3935_DISTTIME: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - Settings.as3935_parameter.dist_autotune_time = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.dist_autotune_time); - break; - case CMND_AS3935_NFTIME: - if (XdrvMailbox.data_len) { - if (15 >= XdrvMailbox.payload) { - Settings.as3935_parameter.nf_autotune_time = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_time); - break; - case CMND_AS3935_SET_DISTURBER: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - AS3935SetDisturber(XdrvMailbox.payload); - if (!XdrvMailbox.payload) Settings.as3935_functions.dist_autotune = 0; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[AS3935GetDisturber()]); - break; - case CMND_AS3935_NF_AUTOTUNE: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - Settings.as3935_functions.nf_autotune = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune]); - break; - case CMND_AS3935_DIST_AUTOTUNE: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - Settings.as3935_functions.dist_autotune = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.dist_autotune]); - break; - case CMND_AS3935_NF_ATUNE_BOTH: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - Settings.as3935_functions.nf_autotune_both = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune_both]); - break; - case CMND_AS3935_MQTT_LIGHT_EVT: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - Settings.as3935_functions.mqtt_only_Light_Event = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.mqtt_only_Light_Event]); - break; - case CMND_AS3935_MQTT_NO_IRQ_EVT: - if (XdrvMailbox.data_len) { - if (2 > XdrvMailbox.payload) { - Settings.as3935_functions.suppress_irq_no_Event = XdrvMailbox.payload; - } - } - Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.suppress_irq_no_Event]); - break; - case CMND_AS3935_SETTINGS: { - if (!XdrvMailbox.data_len) { - uint8_t gain = AS3935GetGainInt(); - uint16_t vrms; - uint8_t stage; - AS3935CalcVrmsLevel(vrms, stage); - uint8_t nf_floor = AS3935GetNoiseFloor(); - uint8_t tunecaps = AS3935GetTuneCaps(); - uint8_t minnumlight = AS3935TranslMinLightsInt(AS3935GetMinLights()); - uint8_t disturber = AS3935GetDisturber(); - uint8_t reinj = AS3935GetSpikeRejection(); - uint8_t wdth = AS3935GetWdth(); - uint8_t min_nf = Settings.as3935_parameter.nf_autotune_min; - uint8_t nf_time = Settings.as3935_parameter.nf_autotune_time; - uint8_t nfauto = Settings.as3935_functions.nf_autotune; - uint8_t nfautomax = Settings.as3935_functions.nf_autotune_both; - uint8_t distauto = Settings.as3935_functions.dist_autotune; - uint8_t jsonlight = Settings.as3935_functions.mqtt_only_Light_Event; - uint8_t jsonirq = Settings.as3935_functions.suppress_irq_no_Event; - uint8_t dist_time = Settings.as3935_parameter.dist_autotune_time; - Response_P(S_JSON_AS3935_COMMAND_SETTINGS, S_JSON_AS3935_COMMAND_GAIN[gain], nf_floor, vrms, tunecaps, minnumlight, reinj, wdth, min_nf, nf_time, dist_time, S_JSON_AS3935_COMMAND_ONOFF[disturber], S_JSON_AS3935_COMMAND_ONOFF[nfauto], S_JSON_AS3935_COMMAND_ONOFF[distauto], S_JSON_AS3935_COMMAND_ONOFF[nfautomax], S_JSON_AS3935_COMMAND_ONOFF[jsonlight], S_JSON_AS3935_COMMAND_ONOFF[jsonirq]); - } - } - break; - case CMND_AS3935_CALIBRATE: { - bool calreslt; - if (!XdrvMailbox.data_len) calreslt = AS3935AutoTune(); - Response_P(S_JSON_AS3935_COMMAND_NVALUE, S_JSON_AS3935_COMMAND_CAL[calreslt], AS3935GetTuneCaps()); - } - break; - default: - return false; - } - return true; - } else { - return false; - } -} - -void AH3935Show(bool json) { - if (json) { - uint16_t vrms; - uint8_t stage; - AS3935CalcVrmsLevel(vrms, stage); - ResponseAppend_P(JSON_SNS_AS3935_EVENTS, D_SENSOR_AS3935, as3935_sensor.mqtt_event, as3935_sensor.distance, as3935_sensor.intensity, stage); -#ifdef USE_WEBSERVER - } else { - uint8_t gain = AS3935GetGainInt(); - uint8_t disturber = AS3935GetDisturber(); - uint16_t vrms; - uint8_t stage; - AS3935CalcVrmsLevel(vrms, stage); - - WSContentSend_PD(HTTP_SNS_AS3935_TABLE_1[as3935_sensor.http_event], D_NAME_AS3935, as3935_sensor.http_distance); - WSContentSend_PD(HTTP_SNS_AS3935_DISTANZ, as3935_sensor.http_distance); - WSContentSend_PD(HTTP_SNS_AS3935_ENERGY, as3935_sensor.http_intensity); - WSContentSend_PD(HTTP_SNS_AS3935_GAIN[gain], D_NAME_AS3935); - WSContentSend_PD(HTTP_SNS_AS3935_DISTURBER[disturber], D_NAME_AS3935); - WSContentSend_PD(HTTP_SNS_AS3935_VRMS, vrms, stage); - -#endif - } -} - - - - - -bool Xsns67(uint8_t function) { - if (!I2cEnabled(XI2C_48)) { return false; } - bool result = false; - if (FUNC_INIT == function) { - AS3935Detect(); - } - else if (as3935_sensor.active) { - switch (function) { - case FUNC_EVERY_SECOND: - AS3935EverySecond(); - break; - case FUNC_COMMAND: - result = AS3935Cmd(); - break; - case FUNC_JSON_APPEND: - AH3935Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AH3935Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" -# 21 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" -#ifdef USE_WINDMETER - - - - -#define XSNS_68 68 - -#define D_WINDMETER_NAME "WindMeter" - -#define WINDMETER_DEF_RADIUS 61 -#define WINDMETER_DEF_PULSES_X_ROT 1 -#define WINDMETER_DEF_PULSE_DEBOUNCE 10 -#define WINDMETER_DEF_COMP_FACTOR 1.18 -#define WINDMETER_DEF_TELE_PCHANGE 255 -#define WINDMETER_WEIGHT_AVG_SAMPLE 150 - -#ifdef USE_WEBSERVER -#define D_WINDMETER_WIND_AVG "∅" -#define D_WINDMETER_WIND_ANGLE "∠" -#define D_WINDMETER_WIND_DEGREE "°" -const char HTTP_SNS_WINDMETER[] PROGMEM = - "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}" -#ifndef USE_WINDMETER_NOSTATISTICS - "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED " " D_WINDMETER_WIND_AVG "{m}%s %s{e}" - "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}" - "{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}" -#endif - - - - - - ; -#endif - - -float const windmeter_pi = 3.1415926535897932384626433; -float const windmeter_2pi = windmeter_pi * 2; - -struct WINDMETER { - volatile uint32_t counter_time; - volatile unsigned long counter = 0; - - float speed = 0; - float last_tele_speed = 0; -#ifndef USE_WINDMETER_NOSTATISTICS - float speed_min = 0; - float speed_max = 0; - float speed_avg = 0; - uint32_t samples_count = 0; - uint32_t avg_samples_no; -#endif -} WindMeter; - -void ICACHE_RAM_ATTR WindMeterUpdateSpeed(void) -{ - uint32_t time = micros(); - uint32_t time_diff = time - WindMeter.counter_time; - if (time_diff > Settings.windmeter_pulse_debounce * 1000) { - WindMeter.counter_time = time; - WindMeter.counter++; - - } -} - - - -void WindMeterInit(void) -{ - if (!Settings.flag2.speed_conversion) { - Settings.flag2.speed_conversion = 2; - } - if (!Settings.windmeter_radius) { - Settings.windmeter_radius = WINDMETER_DEF_RADIUS; - } - if (!Settings.windmeter_pulses_x_rot) { - Settings.windmeter_pulses_x_rot = WINDMETER_DEF_PULSES_X_ROT; - } - if (!Settings.windmeter_pulse_debounce) { - Settings.windmeter_pulse_debounce = WINDMETER_DEF_PULSE_DEBOUNCE; - } - if (!Settings.windmeter_speed_factor) { - Settings.windmeter_speed_factor = (int16_t)(WINDMETER_DEF_COMP_FACTOR * 1000); - } - if (!Settings.windmeter_tele_pchange) { - Settings.windmeter_tele_pchange = WINDMETER_DEF_TELE_PCHANGE; - } - -#ifndef USE_WINDMETER_NOSTATISTICS - WindMeterResetStatData(); - WindMeterCheckSampleCount(); -#endif - - pinMode(Pin(GPIO_WINDMETER_SPEED), INPUT_PULLUP); - attachInterrupt(Pin(GPIO_WINDMETER_SPEED), WindMeterUpdateSpeed, FALLING); -} - -void WindMeterEverySecond(void) -{ - - - - - - WindMeter.speed = ((WindMeter.counter / Settings.windmeter_pulses_x_rot) * (windmeter_2pi * ((float)Settings.windmeter_radius / 1000))) * ((float)Settings.windmeter_speed_factor / 1000); - - WindMeter.counter = 0; -# 136 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" -#ifndef USE_WINDMETER_NOSTATISTICS - if (WindMeter.speed < WindMeter.speed_min) { - WindMeter.speed_min = WindMeter.speed; - } - if (WindMeter.speed > WindMeter.speed_max) { - WindMeter.speed_max = WindMeter.speed; - } - - - - - if (WindMeter.samples_count <= WindMeter.avg_samples_no) { - WindMeter.samples_count++; - } - WindMeter.speed_avg -= WindMeter.speed_avg / WindMeter.samples_count; - WindMeter.speed_avg += float(WindMeter.speed) / WindMeter.samples_count; - - WindMeterCheckSampleCount(); - if (0==Settings.tele_period) { - WindMeterResetStatData(); - } -#endif - - if (WindMeterShouldTriggerTele()) { - WindMeterTriggerTele(); - } -} - -bool WindMeterShouldTriggerTele() -{ - if (Settings.windmeter_tele_pchange > 100) { - return false; - } else if (WindMeter.last_tele_speed == 0) { - return WindMeter.speed > 0; - } else { - float perc_change = (WindMeter.speed / WindMeter.last_tele_speed) -1; - return (perc_change * ((perc_change < 0) ? -100 : 100)) >= Settings.windmeter_tele_pchange; - } -} - -void WindMeterResetStatData(void) -{ - WindMeter.speed_min = WindMeter.speed; - WindMeter.speed_max = WindMeter.speed; - - -} - -void WindMeterCheckSampleCount(void) -{ - uint32_t prev_avg_samples_no = WindMeter.avg_samples_no; - if (Settings.tele_period) { - - WindMeter.avg_samples_no = Settings.tele_period; - } else { - - WindMeter.avg_samples_no = WINDMETER_WEIGHT_AVG_SAMPLE; - } - if (prev_avg_samples_no != WindMeter.avg_samples_no) { - WindMeter.speed_avg = WindMeter.speed; - WindMeter.samples_count = 0; - } -} - -void WindMeterShow(bool json) -{ - char speed_string[FLOATSZ]; - dtostrfd(ConvertSpeed(WindMeter.speed), 2, speed_string); -#ifndef USE_WINDMETER_NOSTATISTICS - char speed_min_string[FLOATSZ]; - dtostrfd(ConvertSpeed(WindMeter.speed_min), 2, speed_min_string); - char speed_max_string[FLOATSZ]; - dtostrfd(ConvertSpeed(WindMeter.speed_max), 2, speed_max_string); - char speed_avg_string[FLOATSZ]; - dtostrfd(ConvertSpeed(WindMeter.speed_avg), 2, speed_avg_string); -# 221 "/workspace/Tasmota/tasmota/xsns_68_windmeter.ino" -#endif - - if (json) { - WindMeter.last_tele_speed = WindMeter.speed; -#ifndef USE_WINDMETER_NOSTATISTICS - - ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s}}"), - speed_string, - speed_avg_string, - speed_min_string, - speed_max_string - - - - - - - - ); -#else - - ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s}}"), - speed_string - - - ); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_WINDMETER, - speed_string, - SpeedUnit().c_str(), -#ifndef USE_WINDMETER_NOSTATISTICS - speed_avg_string, - SpeedUnit().c_str(), - speed_min_string, - SpeedUnit().c_str(), - speed_max_string, - SpeedUnit().c_str(), -#endif - "n/a", - "n/a" -#ifndef USE_WINDMETER_NOSTATISTICS - ,"n/a", - "n/a", - "n/a", - "n/a", - "n/a" -#endif - ); -#endif - } -} - -void WindMeterTriggerTele(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } -} - - - - - -bool Xsns68Cmnd(void) -{ - bool serviced = true; - bool show_parms = true; - char sub_string[XdrvMailbox.data_len +1]; - switch (XdrvMailbox.payload) { - case 1: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.windmeter_radius = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - break; - case 2: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.windmeter_pulses_x_rot = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - break; - case 3: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.windmeter_pulse_debounce = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - break; - case 4: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.windmeter_speed_factor = (int16_t)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 1000); - } - break; - case 5: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.windmeter_tele_pchange = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - break; - } - - if (show_parms) { - char speed_factor_string[FLOATSZ]; - dtostrfd((float)Settings.windmeter_speed_factor / 1000, 3, speed_factor_string); - char tele_pchange_string[4] = "off"; - if (Settings.windmeter_tele_pchange <= 100) { - itoa(Settings.windmeter_tele_pchange, tele_pchange_string, 10); - } - Response_P(PSTR("{\"" D_WINDMETER_NAME "\":{\"Radius\":%d,\"PulsesPerRot\":%d,\"PulseDebounce\":%d,\"SpeedFactor\":%s,\"TeleTriggerMin%Change\":%s}}"), - Settings.windmeter_radius, Settings.windmeter_pulses_x_rot, Settings.windmeter_pulse_debounce, speed_factor_string, tele_pchange_string); - } - return serviced; -} - - - - - -bool Xsns68(uint8_t function) -{ - bool result = false; - if (PinUsed(GPIO_WINDMETER_SPEED)) { - switch (function) { - case FUNC_INIT: - WindMeterInit(); - break; - case FUNC_EVERY_SECOND: - WindMeterEverySecond(); - break; -#ifndef USE_WINDMETER_NOSTATISTICS - case FUNC_AFTER_TELEPERIOD: - WindMeterResetStatData(); - break; -#endif - case FUNC_JSON_APPEND: - WindMeterShow(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - WindMeterShow(false); - break; -#endif - case FUNC_COMMAND_SENSOR: - if (XSNS_68 == XdrvMailbox.index) { - result = Xsns68Cmnd(); - } - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" -#ifdef USE_OPENTHERM - -#define XSNS_69 69 - -#include - - -#define OT_HOT_WATER_MIN 23 -#define OT_HOT_WATER_MAX 55 -#define OT_BOILER_MIN 40 -#define OT_BOILER_MAX 85 - -#define OT_HOT_WATER_DEFAULT 36; -#define OT_BOILER_DEFAULT 85; - - -#define SNS_OT_DISCONNECT_COOLDOWN_SECONDS 10 - - -#define OT_FLAGS_COUNT 6 -enum OpenThermSettingsFlags -{ - - - EnableCentralHeatingOnDiagnostics = 0x01, - - EnableHotWater = 0x02, - - EnableCentralHeating = 0x04, - EnableCooling = 0x08, - EnableTemperatureCompensation = 0x10, - EnableCentralHeating2 = 0x20, -}; - -enum OpenThermConnectionStatus -{ - OTC_NONE, - OTC_DISCONNECTED, - OTC_CONNECTING, - OTC_HANDSHAKE, - OTC_READY, - OTC_INFLIGHT -}; - -OpenThermConnectionStatus sns_ot_connection_status = OpenThermConnectionStatus::OTC_NONE; -uint8_t sns_ot_disconnect_cooldown = 0; - -OpenTherm *sns_ot_master = NULL; - - -typedef struct OT_BOILER_STATUS_T -{ - - uint8_t m_fault_code; - - uint8_t m_oem_fault_code; - - uint16_t m_oem_diag_code; - - uint8_t m_slave_flags; - - unsigned long m_slave_raw_status; - - bool m_enableCentralHeating; - bool m_enableHotWater; - bool m_enableCooling; - bool m_enableOutsideTemperatureCompensation; - bool m_enableCentralHeating2; - - - - - - - - bool m_useDiagnosticIndicationAsHeatRequest; - - - float m_hotWaterSetpoint_read; - - float m_flame_modulation_read; - - float m_boiler_temperature_read; - - - float m_boilerSetpoint; - float m_hotWaterSetpoint; - -} OT_BOILER_STATUS; - -OT_BOILER_STATUS sns_ot_boiler_status; - -const char *sns_opentherm_connection_stat_to_str(int status) -{ - switch (status) - { - case OpenThermConnectionStatus::OTC_NONE: - return "NONE"; - case OpenThermConnectionStatus::OTC_DISCONNECTED: - return "FAULT"; - case OpenThermConnectionStatus::OTC_CONNECTING: - return "CONNECTING"; - case OpenThermConnectionStatus::OTC_HANDSHAKE: - return "HANDSHAKE"; - case OpenThermConnectionStatus::OTC_READY: - return "READY"; - case OpenThermConnectionStatus::OTC_INFLIGHT: - return "BUSY"; - default: - return "UNKNOWN"; - } -} - -void sns_opentherm_init_boiler_status() -{ - memset(&sns_ot_boiler_status, 0, sizeof(OT_BOILER_STATUS)); - - - sns_ot_boiler_status.m_useDiagnosticIndicationAsHeatRequest = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics; - sns_ot_boiler_status.m_enableHotWater = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableHotWater; - sns_ot_boiler_status.m_enableCentralHeating = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeating; - sns_ot_boiler_status.m_enableCooling = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCooling; - sns_ot_boiler_status.m_enableOutsideTemperatureCompensation = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableTemperatureCompensation; - sns_ot_boiler_status.m_enableCentralHeating2 = Settings.ot_flags & (uint8_t)OpenThermSettingsFlags::EnableCentralHeating2; - - sns_ot_boiler_status.m_boilerSetpoint = (float)Settings.ot_boiler_setpoint; - sns_ot_boiler_status.m_hotWaterSetpoint = (float)Settings.ot_hot_water_setpoint; - - sns_ot_boiler_status.m_fault_code = 0; - sns_ot_boiler_status.m_oem_fault_code = 0; - sns_ot_boiler_status.m_oem_diag_code = 0; - sns_ot_boiler_status.m_hotWaterSetpoint_read = 0; - sns_ot_boiler_status.m_flame_modulation_read = 0; - sns_ot_boiler_status.m_boiler_temperature_read = 0; -} - -void ICACHE_RAM_ATTR sns_opentherm_handleInterrupt() -{ - sns_ot_master->handleInterrupt(); -} - -void sns_opentherm_processResponseCallback(unsigned long response, int st) -{ - OpenThermResponseStatus status = (OpenThermResponseStatus)st; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, - PSTR("[OTH]: Processing response. Status=%s, Response=0x%lX"), - sns_ot_master->statusToString(status), response); - - if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_HANDSHAKE) - { - return sns_ot_process_handshake(response, st); - } - - switch (status) - { - case OpenThermResponseStatus::SUCCESS: - if (sns_ot_master->isValidResponse(response)) - { - sns_opentherm_process_success_response(&sns_ot_boiler_status, response); - } - sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; - break; - - case OpenThermResponseStatus::INVALID: - sns_opentherm_check_retry_request(); - sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; - break; - - - - - - case OpenThermResponseStatus::TIMEOUT: - sns_opentherm_check_retry_request(); - sns_ot_connection_status = OpenThermConnectionStatus::OTC_DISCONNECTED; - break; - } -} - -bool sns_opentherm_Init() -{ - if (PinUsed(GPIO_BOILER_OT_RX) && PinUsed(GPIO_BOILER_OT_TX)) - { - sns_ot_master = new OpenTherm(Pin(GPIO_BOILER_OT_RX), Pin(GPIO_BOILER_OT_TX)); - sns_ot_master->begin(sns_opentherm_handleInterrupt, sns_opentherm_processResponseCallback); - sns_ot_connection_status = OpenThermConnectionStatus::OTC_CONNECTING; - - sns_opentherm_init_boiler_status(); - return true; - } - return false; - -} - -void sns_opentherm_stat(bool json) -{ - if (!sns_ot_master) - { - return; - } - const char *statusStr = sns_opentherm_connection_stat_to_str(sns_ot_connection_status); - - if (json) - { - ResponseAppend_P(PSTR(",\"OPENTHERM\":{")); - ResponseAppend_P(PSTR("\"conn\":\"%s\","), statusStr); - ResponseAppend_P(PSTR("\"settings\":%d,"), Settings.ot_flags); - sns_opentherm_dump_telemetry(); - ResponseJsonEnd(); -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_P(PSTR("{s}OpenTherm status{m}%s (0x%X){e}"), statusStr, (int)sns_ot_boiler_status.m_slave_flags); - if (sns_ot_connection_status < OpenThermConnectionStatus::OTC_READY) - { - return; - } - WSContentSend_P(PSTR("{s}Std/OEM Fault Codes{m}%d / %d{e}"), - (int)sns_ot_boiler_status.m_fault_code, - (int)sns_ot_boiler_status.m_oem_fault_code); - - WSContentSend_P(PSTR("{s}OEM Diagnostic Code{m}%d{e}"), - (int)sns_ot_boiler_status.m_oem_diag_code); - - WSContentSend_P(PSTR("{s}Hot Water Setpoint{m}%d{e}"), - (int)sns_ot_boiler_status.m_hotWaterSetpoint_read); - - WSContentSend_P(PSTR("{s}Flame Modulation{m}%d{e}"), - (int)sns_ot_boiler_status.m_flame_modulation_read); - - WSContentSend_P(PSTR("{s}Boiler Temp/Setpnt{m}%d / %d{e}"), - (int)sns_ot_boiler_status.m_boiler_temperature_read, - (int)sns_ot_boiler_status.m_boilerSetpoint); - - if (OpenTherm::isCentralHeatingActive(sns_ot_boiler_status.m_slave_raw_status)) - { - WSContentSend_P(PSTR("{s}Central Heating is ACTIVE{m}{e}")); - } - - if (sns_ot_boiler_status.m_enableHotWater) - { - WSContentSend_P(PSTR("{s}Hot Water is Enabled{m}{e}")); - } - - if (OpenTherm::isHotWaterActive(sns_ot_boiler_status.m_slave_raw_status)) - { - WSContentSend_P(PSTR("{s}Hot Water is ACTIVE{m}{e}")); - } - - if (OpenTherm::isFlameOn(sns_ot_boiler_status.m_slave_raw_status)) - { - WSContentSend_P(PSTR("{s}Flame is ACTIVE{m}{e}")); - } - - if (sns_ot_boiler_status.m_enableCooling) - { - WSContentSend_P(PSTR("{s}Cooling is Enabled{m}{e}")); - } - - if (OpenTherm::isCoolingActive(sns_ot_boiler_status.m_slave_raw_status)) - { - WSContentSend_P(PSTR("{s}Cooling is ACTIVE{m}{e}")); - } - - if (OpenTherm::isDiagnostic(sns_ot_boiler_status.m_slave_raw_status)) - { - WSContentSend_P(PSTR("{s}Diagnostic Indication{m}{e}")); - } - -#endif - } -} - -void sns_ot_start_handshake() -{ - if (!sns_ot_master) - { - return; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("[OTH]: perform handshake")); - - sns_ot_master->sendRequestAync( - OpenTherm::buildRequest(OpenThermMessageType::READ_DATA, OpenThermMessageID::SConfigSMemberIDcode, 0)); - - sns_ot_connection_status = OpenThermConnectionStatus::OTC_HANDSHAKE; -} - -void sns_ot_process_handshake(unsigned long response, int st) -{ - OpenThermResponseStatus status = (OpenThermResponseStatus)st; - - if (status != OpenThermResponseStatus::SUCCESS || !sns_ot_master->isValidResponse(response)) - { - AddLog_P2(LOG_LEVEL_ERROR, - PSTR("[OTH]: getSlaveConfiguration failed. Status=%s"), - sns_ot_master->statusToString(status)); - sns_ot_connection_status = OpenThermConnectionStatus::OTC_DISCONNECTED; - return; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("[OTH]: getLastResponseStatus SUCCESS. Slave Cfg: %lX"), response); - - sns_ot_boiler_status.m_slave_flags = (response & 0xFF00) >> 8; - - sns_ot_connection_status = OpenThermConnectionStatus::OTC_READY; -} - -void sns_opentherm_CheckSettings(void) -{ - bool settingsValid = true; - - settingsValid &= Settings.ot_hot_water_setpoint >= OT_HOT_WATER_MIN; - settingsValid &= Settings.ot_hot_water_setpoint <= OT_HOT_WATER_MAX; - settingsValid &= Settings.ot_boiler_setpoint >= OT_BOILER_MIN; - settingsValid &= Settings.ot_boiler_setpoint <= OT_BOILER_MAX; - - if (!settingsValid) - { - Settings.ot_hot_water_setpoint = OT_HOT_WATER_DEFAULT; - Settings.ot_boiler_setpoint = OT_BOILER_DEFAULT; - Settings.ot_flags = - OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics | - OpenThermSettingsFlags::EnableHotWater; - } -} - - - -const char *sns_opentherm_flag_text(uint8_t mode) -{ - switch ((OpenThermSettingsFlags)mode) - { - case OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics: - return "CHOD"; - case OpenThermSettingsFlags::EnableHotWater: - return "DHW"; - case OpenThermSettingsFlags::EnableCentralHeating: - return "CH"; - case OpenThermSettingsFlags::EnableCooling: - return "COOL"; - case OpenThermSettingsFlags::EnableTemperatureCompensation: - return "OTC"; - case OpenThermSettingsFlags::EnableCentralHeating2: - return "CH2"; - default: - return "?"; - } -} - -uint8_t sns_opentherm_parse_flag(char *flag) -{ - if (!strncmp(flag, "CHOD", 4)) - { - return OpenThermSettingsFlags::EnableCentralHeatingOnDiagnostics; - } - else if (!strncmp(flag, "COOL", 4)) - { - return OpenThermSettingsFlags::EnableCooling; - } - else if (!strncmp(flag, "DHW", 3)) - { - return OpenThermSettingsFlags::EnableHotWater; - } - else if (!strncmp(flag, "OTC", 3)) - { - return OpenThermSettingsFlags::EnableTemperatureCompensation; - } - else if (!strncmp(flag, "CH2", 3)) - { - return OpenThermSettingsFlags::EnableCentralHeating2; - } - else if (!strncmp(flag, "CH", 2)) - { - return OpenThermSettingsFlags::EnableCentralHeating; - } - return 0; -} - -uint8_t sns_opentherm_read_flags(char *data, uint32_t len) -{ - uint8_t tokens = 1; - for (int i = 0; i < len; ++i) - { - if (data[i] == ',') - { - ++tokens; - } - } - uint8_t result = 0; - char sub_string[XdrvMailbox.data_len + 1]; - for (int i = 1; i <= tokens; ++i) - { - char *flag = subStr(sub_string, data, ",", i); - if (!flag) - { - break; - } - result |= sns_opentherm_parse_flag(flag); - } - return result; -} -#define D_PRFX_OTHERM "ot_" - - -#define D_CMND_OTHERM_BOILER_SETPOINT "tboiler" - - -#define D_CMND_OTHERM_DHW_SETPOINT "twater" - - - -#define D_CMND_OTHERM_SAVE_SETTINGS "save_setpoints" -# 442 "/workspace/Tasmota/tasmota/xsns_69_opentherm.ino" -#define D_CMND_OTHERM_FLAGS "flags" - - - - - - - -#define D_CMND_SET_CENTRAL_HEATING_ENABLED "ch" - -const char kOpenThermCommands[] PROGMEM = D_PRFX_OTHERM "|" D_CMND_OTHERM_BOILER_SETPOINT "|" D_CMND_OTHERM_DHW_SETPOINT - "|" D_CMND_OTHERM_SAVE_SETTINGS "|" D_CMND_OTHERM_FLAGS "|" D_CMND_SET_CENTRAL_HEATING_ENABLED; - -void (*const OpenThermCommands[])(void) PROGMEM = { - &sns_opentherm_boiler_setpoint_cmd, - &sns_opentherm_hot_water_setpoint_cmd, - &sns_opentherm_save_settings_cmd, - &sns_opentherm_flags_cmd, - &sns_opentherm_set_central_heating_cmd}; - -void sns_opentherm_cmd(void) { } -void sns_opentherm_boiler_setpoint_cmd(void) -{ - bool query = strlen(XdrvMailbox.data) == 0; - if (!query) - { - sns_ot_boiler_status.m_boilerSetpoint = atof(XdrvMailbox.data); - } - ResponseCmndFloat(sns_ot_boiler_status.m_boilerSetpoint, Settings.flag2.temperature_resolution); -} - -void sns_opentherm_hot_water_setpoint_cmd(void) -{ - bool query = strlen(XdrvMailbox.data) == 0; - if (!query) - { - sns_ot_boiler_status.m_hotWaterSetpoint = atof(XdrvMailbox.data); - } - ResponseCmndFloat(sns_ot_boiler_status.m_hotWaterSetpoint, Settings.flag2.temperature_resolution); -} - -void sns_opentherm_save_settings_cmd(void) -{ - Settings.ot_hot_water_setpoint = (uint8_t)sns_ot_boiler_status.m_hotWaterSetpoint; - Settings.ot_boiler_setpoint = (uint8_t)sns_ot_boiler_status.m_boilerSetpoint; - ResponseCmndDone(); -} - -void sns_opentherm_flags_cmd(void) -{ - bool query = strlen(XdrvMailbox.data) == 0; - if (!query) - { - - Settings.ot_flags = sns_opentherm_read_flags(XdrvMailbox.data, XdrvMailbox.data_len); - - sns_opentherm_init_boiler_status(); - } - bool addComma = false; - mqtt_data[0] = 0; - for (int pos = 0; pos < OT_FLAGS_COUNT; ++pos) - { - int mask = 1 << pos; - int mode = Settings.ot_flags & (uint8_t)mask; - if (mode > 0) - { - if (addComma) - { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, sns_opentherm_flag_text(mode)); - addComma = true; - } - } -} - -void sns_opentherm_set_central_heating_cmd(void) -{ - bool query = strlen(XdrvMailbox.data) == 0; - if (!query) - { - sns_ot_boiler_status.m_enableCentralHeating = atoi(XdrvMailbox.data); - } - ResponseCmndNumber(sns_ot_boiler_status.m_enableCentralHeating ? 1 : 0); -} - - - - - -bool Xsns69(uint8_t function) -{ - bool result = false; - if (FUNC_INIT == function) - { - if (sns_opentherm_Init()) - { - sns_opentherm_CheckSettings(); - } - } - - if (!sns_ot_master) - { - return result; - } - - switch (function) - { - case FUNC_LOOP: - sns_ot_master->process(); - break; - case FUNC_EVERY_100_MSECOND: - if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_READY && sns_ot_master->isReady()) - { - unsigned long request = sns_opentherm_get_next_request(&sns_ot_boiler_status); - if (-1 != request) - { - sns_ot_master->sendRequestAync(request); - sns_ot_connection_status = OpenThermConnectionStatus::OTC_INFLIGHT; - } - } - break; - case FUNC_EVERY_SECOND: - if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_DISCONNECTED) - { - - if (sns_ot_disconnect_cooldown == 0) - { - sns_ot_disconnect_cooldown = SNS_OT_DISCONNECT_COOLDOWN_SECONDS; - } - else if (--sns_ot_disconnect_cooldown == 0) - { - sns_ot_connection_status = OpenThermConnectionStatus::OTC_CONNECTING; - } - } - else if (sns_ot_connection_status == OpenThermConnectionStatus::OTC_CONNECTING) - { - sns_ot_start_handshake(); - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kOpenThermCommands, OpenThermCommands); - break; - case FUNC_JSON_APPEND: - sns_opentherm_stat(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - sns_opentherm_stat(0); - break; -#endif - } - - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_69_opentherm_protocol.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_69_opentherm_protocol.ino" -#ifdef USE_OPENTHERM - -#include "OpenTherm.h" - - - -#define OPENTHERM_BOILER_SETPOINT_TOLERANCE 1.0 - -typedef union { - uint8_t m_flags; - struct - { - uint8_t notSupported : 1; - uint8_t supported : 1; - uint8_t retryCount : 2; - }; -} OpenThermParamFlags; - -typedef union { - float m_float; - uint8_t m_u8; - uint16_t m_u16; - unsigned long m_ul; - bool m_bool; -} ResponseStorage; - -typedef struct OpenThermCommandT -{ - const char *m_command_name; - uint8_t m_command_code; - OpenThermParamFlags m_flags; - ResponseStorage m_results[2]; - unsigned long (*m_ot_make_request)(OpenThermCommandT *self, OT_BOILER_STATUS_T *boilerStatus); - void (*m_ot_parse_response)(OpenThermCommandT *self, OT_BOILER_STATUS_T *boilerStatus, unsigned long response); - void (*m_ot_appent_telemetry)(OpenThermCommandT *self); -} OpenThermCommand; - -OpenThermCommand sns_opentherm_commands[] = { - { - .m_command_name = "SLAVE", - .m_command_code = 0, - - - .m_flags = {.supported = 1}, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_set_slave_flags, - .m_ot_parse_response = sns_opentherm_parse_slave_flags, - .m_ot_appent_telemetry = sns_opentherm_tele_slave_flags}, - { - .m_command_name = "BTMP", - .m_command_code = 0, - - .m_flags = {.supported = 1}, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_set_boiler_temperature, - .m_ot_parse_response = sns_opentherm_parse_set_boiler_temperature, - .m_ot_appent_telemetry = sns_opentherm_tele_boiler_temperature}, - { - .m_command_name = "HWTMP", - .m_command_code = 0, - - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_set_boiler_dhw_temperature, - .m_ot_parse_response = sns_opentherm_parse_boiler_dhw_temperature, - .m_ot_appent_telemetry = sns_opentherm_tele_boiler_dhw_temperature}, - { - .m_command_name = "ASFF", - .m_command_code = 0, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_flags, - .m_ot_parse_response = sns_opentherm_parse_flags, - .m_ot_appent_telemetry = sns_opentherm_tele_flags}, - { - .m_command_name = "OEMD", - .m_command_code = 0, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_oem_diag, - .m_ot_parse_response = sns_opentherm_parse_oem_diag, - .m_ot_appent_telemetry = sns_opentherm_tele_oem_diag}, - { - .m_command_name = "FLM", - .m_command_code = (uint8_t)OpenThermMessageID::RelModLevel, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_flame_modulation, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "TB", - .m_command_code = (uint8_t)OpenThermMessageID::Tboiler, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_boiler_temperature, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "TDHW", - .m_command_code = (uint8_t)OpenThermMessageID::Tdhw, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_generic_float, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "TOUT", - .m_command_code = (uint8_t)OpenThermMessageID::Toutside, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_generic_float, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "TRET", - .m_command_code = (uint8_t)OpenThermMessageID::Tret, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_generic_float, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "DHWS", - .m_command_code = (uint8_t)OpenThermMessageID::TdhwSet, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_dhw_setpoint, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - { - .m_command_name = "TMAX", - .m_command_code = (uint8_t)OpenThermMessageID::MaxTSet, - .m_flags = 0, - .m_results = {{.m_u8 = 0}, {.m_u8 = 0}}, - .m_ot_make_request = sns_opentherm_get_generic_float, - .m_ot_parse_response = sns_opentherm_parse_generic_float, - .m_ot_appent_telemetry = sns_opentherm_tele_generic_float}, - -}; - - -unsigned long sns_opentherm_set_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) -{ - bool centralHeatingIsOn = status->m_enableCentralHeating; - - if (status->m_useDiagnosticIndicationAsHeatRequest) { - centralHeatingIsOn |= OpenTherm::isDiagnostic(status->m_slave_raw_status); - } - - if (self->m_results[1].m_bool != centralHeatingIsOn) { - AddLog_P2(LOG_LEVEL_INFO, - PSTR("[OTH]: Central Heating transitioning from %s to %s"), - self->m_results[1].m_bool ? "on" : "off", - status->m_enableCentralHeating ? "on" : "off"); - } - self->m_results[1].m_bool = centralHeatingIsOn; - - unsigned int data = centralHeatingIsOn | - (status->m_enableHotWater << 1) | - (status->m_enableCooling << 2) | - (status->m_enableOutsideTemperatureCompensation << 3) | - (status->m_enableCentralHeating2 << 4); - - data <<= 8; - - return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Status, data); -} - -void sns_opentherm_parse_slave_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - boilerStatus->m_slave_raw_status = response; - self->m_results[0].m_ul = response; -} - -#define OT_FLAG_TO_ON_OFF(status,flag) ((((status) & (flag)) != 0) ? 1 : 0) -void sns_opentherm_tele_slave_flags(struct OpenThermCommandT *self) -{ - unsigned long st = self->m_results[0].m_ul; - ResponseAppend_P(PSTR("{\"FAULT\":%d,\"CH\":%d,\"DHW\":%d,\"FL\":%d,\"COOL\":%d,\"CH2\":%d,\"DIAG\":%d,\"RAW\":%lu}"), - OT_FLAG_TO_ON_OFF(st, 0x01), - OT_FLAG_TO_ON_OFF(st, 0x02), - OT_FLAG_TO_ON_OFF(st, 0x04), - OT_FLAG_TO_ON_OFF(st, 0x08), - OT_FLAG_TO_ON_OFF(st, 0x10), - OT_FLAG_TO_ON_OFF(st, 0x20), - OT_FLAG_TO_ON_OFF(st, 0x40), - st); -} - - -unsigned long sns_opentherm_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) -{ - - - - float diff = abs(status->m_boilerSetpoint - self->m_results[0].m_float); - - if (diff < OPENTHERM_BOILER_SETPOINT_TOLERANCE) - { - return -1; - } - AddLog_P2(LOG_LEVEL_INFO, - PSTR("[OTH]: Setting Boiler Temp. Old: %d, New: %d"), - (int)self->m_results[0].m_float, - (int)status->m_boilerSetpoint); - self->m_results[0].m_float = status->m_boilerSetpoint; - - unsigned int data = OpenTherm::temperatureToData(status->m_boilerSetpoint); - return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::TSet, data); -} -void sns_opentherm_parse_set_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[1].m_float = OpenTherm::getFloat(response); -} -void sns_opentherm_tele_boiler_temperature(struct OpenThermCommandT *self) -{ - char requested[FLOATSZ]; - dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, requested); - char actual[FLOATSZ]; - dtostrfd(self->m_results[1].m_float, Settings.flag2.temperature_resolution, actual); - - - bool isFault = abs(self->m_results[1].m_float - self->m_results[0].m_float) > OPENTHERM_BOILER_SETPOINT_TOLERANCE; - - ResponseAppend_P(PSTR("{\"FAULT\":%d,\"REQ\":%s,\"ACT\": %s}"), - (int)isFault, - requested, - actual); -} - - -unsigned long sns_opentherm_set_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *status) -{ - - float diff = abs(status->m_hotWaterSetpoint - self->m_results[0].m_float); - - if (diff < OPENTHERM_BOILER_SETPOINT_TOLERANCE) - { - return -1; - } - AddLog_P2(LOG_LEVEL_INFO, - PSTR("[OTH]: Setting Hot Water Temp. Old: %d, New: %d"), - (int)self->m_results[0].m_float, - (int)status->m_hotWaterSetpoint); - - self->m_results[0].m_float = status->m_hotWaterSetpoint; - - unsigned int data = OpenTherm::temperatureToData(status->m_hotWaterSetpoint); - return OpenTherm::buildRequest(OpenThermMessageType::WRITE_DATA, OpenThermMessageID::TdhwSet, data); -} -void sns_opentherm_parse_boiler_dhw_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[1].m_float = OpenTherm::getFloat(response); -} -void sns_opentherm_tele_boiler_dhw_temperature(struct OpenThermCommandT *self) -{ - char requested[FLOATSZ]; - dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, requested); - char actual[FLOATSZ]; - dtostrfd(self->m_results[1].m_float, Settings.flag2.temperature_resolution, actual); - - ResponseAppend_P(PSTR("{\"REQ\":%s,\"ACT\": %s}"), - requested, - actual); -} - - -unsigned long sns_opentherm_get_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) -{ - return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::ASFflags, 0); -} - -void sns_opentherm_parse_flags(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - uint8_t fault_code = (response >> 8) & 0xFF; - uint8_t oem_fault_code = response & 0xFF; - boilerStatus->m_fault_code = fault_code; - boilerStatus->m_oem_fault_code = fault_code; - self->m_results[0].m_u8 = fault_code; - self->m_results[1].m_u8 = oem_fault_code; -} - -void sns_opentherm_tele_flags(struct OpenThermCommandT *self) -{ - ResponseAppend_P(PSTR("{\"FC\":%d,\"OFC\":%d}"), - (int)self->m_results[0].m_u8, - (int)self->m_results[1].m_u8); -} - - -unsigned long sns_opentherm_get_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) -{ - return OpenTherm::buildRequest(OpenThermRequestType::READ, OpenThermMessageID::OEMDiagnosticCode, 0); -} - -void sns_opentherm_parse_oem_diag(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - uint16_t diag_code = (uint16_t)response & 0xFFFF; - boilerStatus->m_oem_diag_code = diag_code; - self->m_results[0].m_u16 = diag_code; -} - -void sns_opentherm_tele_oem_diag(struct OpenThermCommandT *self) -{ - ResponseAppend_P(PSTR("%d"), (int)self->m_results[0].m_u16); -} - - -unsigned long sns_opentherm_get_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *) -{ - return OpenTherm::buildRequest(OpenThermRequestType::READ, (OpenThermMessageID)self->m_command_code, 0); -} - -void sns_opentherm_parse_generic_float(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[0].m_float = OpenTherm::getFloat(response); -} - -void sns_opentherm_tele_generic_float(struct OpenThermCommandT *self) -{ - char str[FLOATSZ]; - dtostrfd(self->m_results[0].m_float, Settings.flag2.temperature_resolution, str); - ResponseAppend_P(PSTR("%s"), str); -} - - -void sns_opentherm_parse_dhw_setpoint(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[0].m_float = OpenTherm::getFloat(response); - boilerStatus->m_hotWaterSetpoint_read = self->m_results[0].m_float; -} - -void sns_opentherm_parse_flame_modulation(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[0].m_float = OpenTherm::getFloat(response); - boilerStatus->m_flame_modulation_read = self->m_results[0].m_float; -} - -void sns_opentherm_parse_boiler_temperature(struct OpenThermCommandT *self, struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - self->m_results[0].m_float = OpenTherm::getFloat(response); - boilerStatus->m_boiler_temperature_read = self->m_results[0].m_float; -} - - - - - -#define SNS_OT_COMMANDS_COUNT (sizeof(sns_opentherm_commands) / sizeof(OpenThermCommand)) -int sns_opentherm_current_command = SNS_OT_COMMANDS_COUNT; - -unsigned long sns_opentherm_get_next_request(struct OT_BOILER_STATUS_T *boilerStatus) -{ - - if (++sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) - { - sns_opentherm_current_command = 0; - } - - struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; - - if (cmd->m_flags.notSupported) - { - return -1; - } - - return cmd->m_ot_make_request(cmd, boilerStatus); -} - -void sns_opentherm_check_retry_request() -{ - if (sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) - { - return; - } - struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; - - bool canRetry = ++cmd->m_flags.retryCount < 3; - - if (!canRetry && !cmd->m_flags.supported) - { - cmd->m_flags.notSupported = true; - AddLog_P2(LOG_LEVEL_ERROR, - PSTR("[OTH]: command %s is not supported by the boiler. Last status: %s"), - cmd->m_command_name, - sns_ot_master->statusToString(sns_ot_master->getLastResponseStatus())); - } -} - -void sns_opentherm_process_success_response(struct OT_BOILER_STATUS_T *boilerStatus, unsigned long response) -{ - if (sns_opentherm_current_command >= SNS_OT_COMMANDS_COUNT) - { - return; - } - struct OpenThermCommandT *cmd = &sns_opentherm_commands[sns_opentherm_current_command]; - - cmd->m_flags.supported = true; - - cmd->m_ot_parse_response(cmd, boilerStatus, response); -} - -void sns_opentherm_dump_telemetry() -{ - bool add_coma = false; - for (int i = 0; i < SNS_OT_COMMANDS_COUNT; ++i) - { - struct OpenThermCommandT *cmd = &sns_opentherm_commands[i]; - if (!cmd->m_flags.supported) - { - continue; - } - - ResponseAppend_P(PSTR("%s\"%s\":"), add_coma ? "," : "", cmd->m_command_name); - - cmd->m_ot_appent_telemetry(cmd); - - add_coma = true; - } -} -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_70_veml6075.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_70_veml6075.ino" -#ifdef USE_I2C -#ifdef USE_VEML6075 - - - - - - -#define XSNS_70 70 -#define XI2C_49 49 - - -#define VEML6075_ADDR 0x10 -#define VEML6075_CHIP_ID 0x26 - - -#define VEML6075_REG_CONF 0x00 -#define VEML6075_REG_UVA 0x07 -#define VEML6075_REG_DARK 0x08 -#define VEML6075_REG_UVB 0x09 -#define VEML6075_REG_UVCOMP1 0x0A -#define VEML6075_REG_UVCOMP2 0x0B -#define VEML6075_REG_ID 0x0C - - -#define VEML6075_DEFAULT_UVA_A_COEFF 2.22 -#define VEML6075_DEFAULT_UVA_B_COEFF 1.33 -#define VEML6075_DEFAULT_UVB_C_COEFF 2.95 -#define VEML6075_DEFAULT_UVB_D_COEFF 1.74 -#define UVA_RESPONSIVITY_100MS_UNCOVERED 0.001461 -#define UVB_RESPONSIVITY_100MS_UNCOVERED 0.002591 - -const float UVA_RESPONSIVITY[] PROGMEM = -{ - UVA_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, - UVA_RESPONSIVITY_100MS_UNCOVERED, - UVA_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, - UVA_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, - UVA_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 -}; - -const float UVB_RESPONSIVITY[] PROGMEM = -{ - UVB_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, - UVB_RESPONSIVITY_100MS_UNCOVERED, - UVB_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, - UVB_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, - UVB_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 -}; - - -#define D_NAME_VEML6075 "VEML6075" -#define D_UVA_INTENSITY "UVA intensity" -#define D_UVB_INTENSITY "UVB intensity" - -const char HTTP_SNS_UVA[] PROGMEM = "{s}%s " D_UVA_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}"; -const char HTTP_SNS_UVB[] PROGMEM = "{s}%s " D_UVB_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}"; -const char HTTP_SNS_UVINDEX[] PROGMEM = "{s}%s " D_UV_INDEX "{m}%s {e}"; -const char JSON_SNS_VEML6075[] PROGMEM = ",\"%s\":{\"" D_JSON_UVA_INTENSITY "\":%d,\"" D_JSON_UVB_INTENSITY "\":%d,\"" D_JSON_UV_INDEX "\":%s}"; -const char S_JSON_VEML6075_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_VEML6075 "\":{\"%s\":%d}}"; - -const char kVEML6075_Commands[] PROGMEM = D_CMND_VEML6075_POWER "|" D_CMND_VEML6075_DYNAMIC "|" D_CMND_VEML6075_INTTIME; - -enum VEML6075_Commands { - CMND_VEML6075_PWR, - CMND_VEML6075_SET_HD, - CMND_VEML6075_SET_UVIT, - }; - - -struct VEML6075STRUCT -{ - char types[9] = D_NAME_VEML6075; - uint8_t address = VEML6075_ADDR; - uint8_t inttime = 0; - uint16_t uva = 0; - uint16_t uvb = 0; - uint16_t uva_raw = 0; - uint16_t uvb_raw = 0; - uint16_t comp1 = 0; - uint16_t comp2 = 0; - uint16_t conf = 0; - float uvi = 0.0f; -} veml6075_sensor; - -uint8_t veml6075_active = 0; - - -typedef union { - struct { - uint8_t pwr:1; - uint8_t forded_auto:1; - uint8_t forced_trigger:1; - uint8_t hd:1; - uint8_t inttime:3; - uint8_t spare7:1; - }; - uint16_t config; -} veml6075configRegister; - -veml6075configRegister veml6075Config; - - - -uint16_t VEML6075read16 (uint8_t reg) { - uint16_t swap = I2cRead16(VEML6075_ADDR, reg); - uint16_t ret = ((swap & 0xFF) << 8) | (swap >> 8); - return ret; -} - -void VEML6075write16 (uint8_t reg, uint16_t val) { - uint16_t swap = ((val & 0xFF) << 8) | (val >> 8); - I2cWrite16(VEML6075_ADDR, reg, swap); -} - -float VEML6075calcUVA (void) { - float uva_calc = veml6075_sensor.uva_raw - (VEML6075_DEFAULT_UVA_A_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVA_B_COEFF * veml6075_sensor.comp2); - return uva_calc; -} - -float VEML6075calcUVB (void) { - float uvb_calc = veml6075_sensor.uvb_raw - (VEML6075_DEFAULT_UVB_C_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVB_D_COEFF * veml6075_sensor.comp2); - return uvb_calc; -} - -float VEML6075calcUVI (void) { - float uvi_calc = ((veml6075_sensor.uva * UVA_RESPONSIVITY[veml6075_sensor.inttime]) + (veml6075_sensor.uvb * UVB_RESPONSIVITY[veml6075_sensor.inttime])) / 2; - return uvi_calc; -} - -void VEML6075SetHD(uint8_t val){ - veml6075Config.hd = val; - VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); -} - -uint8_t VEML6075ReadHD(void){ - veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); - return veml6075Config.hd; -} - -void VEML6075SetUvIt(uint8_t val){ - veml6075Config.inttime = val; - VEML6075Pwr(1); - VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); - VEML6075Pwr(0); -} - -uint8_t VEML6075GetUvIt(void){ - veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); - return veml6075Config.inttime; -} - -void VEML6075Pwr(uint8_t val){ - veml6075Config.pwr = val; - VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config); -} - -uint8_t VEML6075GetPwr(void){ - veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF); - return veml6075Config.pwr; -} - -void VEML6075ReadData(void) -{ - veml6075_sensor.uva_raw = VEML6075read16 (VEML6075_REG_UVA); - veml6075_sensor.uvb_raw = VEML6075read16 (VEML6075_REG_UVB); - veml6075_sensor.comp1 = VEML6075read16 (VEML6075_REG_UVCOMP1); - veml6075_sensor.comp2 = VEML6075read16 (VEML6075_REG_UVCOMP2); - veml6075_sensor.inttime = VEML6075GetUvIt(); - veml6075_sensor.uva = VEML6075calcUVA(); - veml6075_sensor.uvb = VEML6075calcUVB(); - veml6075_sensor.uvi = VEML6075calcUVI(); -} - -bool VEML6075init(void) -{ - uint8_t id = VEML6075read16 (VEML6075_REG_ID); - if(id == VEML6075_CHIP_ID) - return true; - return false; -} - -void VEML6075Detect(void) { - if (I2cActive(veml6075_sensor.address)) return; - - if (VEML6075init()) { - I2cSetActiveFound(veml6075_sensor.address, veml6075_sensor.types); - VEML6075write16 (VEML6075_REG_CONF, 0x10); - veml6075_active = 1; - } -} - -void VEML6075EverySecond(void) { - VEML6075ReadData(); -} - -bool VEML6075Cmd(void) { - char command[CMDSZ]; - uint8_t name_len = strlen(D_NAME_VEML6075); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_VEML6075), name_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kVEML6075_Commands); - switch (command_code) { - case CMND_VEML6075_PWR: - if (XdrvMailbox.data_len) { - if (2 >= XdrvMailbox.payload) { - VEML6075Pwr(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetPwr()); - break; - case CMND_VEML6075_SET_HD: - if (XdrvMailbox.data_len) { - if (2 >= XdrvMailbox.payload) { - VEML6075SetHD(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075ReadHD()); - break; - case CMND_VEML6075_SET_UVIT: - if (XdrvMailbox.data_len) { - if (4 >= XdrvMailbox.payload) { - VEML6075SetUvIt(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetUvIt()); - break; - default: - return false; - } - return true; - } else { - return false; - } -} - -void VEML6075Show(bool json) -{ - char s_uvindex[FLOATSZ]; - dtostrfd(veml6075_sensor.uvi,1, s_uvindex); - - if (json) { - ResponseAppend_P(JSON_SNS_VEML6075, D_NAME_VEML6075, veml6075_sensor.uva, veml6075_sensor.uvb, s_uvindex); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_UVA, D_NAME_VEML6075, veml6075_sensor.uva); - WSContentSend_PD(HTTP_SNS_UVB, D_NAME_VEML6075, veml6075_sensor.uvb); - WSContentSend_PD(HTTP_SNS_UVINDEX, D_NAME_VEML6075 ,s_uvindex); -#endif - } -} - - - - - -bool Xsns70(uint8_t function) -{ - if (!I2cEnabled(XI2C_49)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - VEML6075Detect(); - } - else if (veml6075_active) { - switch (function) { - case FUNC_EVERY_SECOND: - VEML6075EverySecond(); - break; - case FUNC_COMMAND: - result = VEML6075Cmd(); - break; - case FUNC_JSON_APPEND: - VEML6075Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - VEML6075Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_71_veml7700.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_71_veml7700.ino" -#ifdef USE_I2C -#ifdef USE_VEML7700 - - - - - - -#define XSNS_71 71 -#define XI2C_50 50 - -#include "Adafruit_VEML7700.h" -Adafruit_VEML7700 veml7700 = Adafruit_VEML7700(); - -#define D_NAME_VEML7700 "VEML7700" -#define D_WHITE_CONTENT "White content" - -const char HTTP_SNS_WHITE[] PROGMEM = "{s}%s " D_WHITE_CONTENT "{m}%d {e}"; -const char JSON_SNS_VEML7700[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_WHITE_CONTENT "\":%d}"; - -#define D_CMND_VEML7700_PWR "power" -#define D_CMND_VEML7700_GAIN "gain" -#define D_CMND_VEML7700_INTTIME "inttime" -#define D_CMND_VEML7700_PERSIST "persist" - -const char S_JSON_VEML7700_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_VEML7700 "\":{\"%s\":%d}}"; -const char kVEML7700_Commands[] PROGMEM = D_CMND_VEML7700_PWR "|" D_CMND_VEML7700_GAIN "|" D_CMND_VEML7700_INTTIME "|" D_CMND_VEML7700_PERSIST; - -enum VEML7700_Commands { - CMND_VEML7700_PWR, - CMND_VEML7700_GAIN, - CMND_VEML7700_SET_IT, - CMND_VEML7700_PERSIST, -}; - -struct VEML7700STRUCT -{ - bool active = 0; - char types[9] = D_NAME_VEML7700; - uint8_t address = VEML7700_I2CADDR_DEFAULT; - uint32_t lux_normalized = 0; - uint32_t white_normalized = 0; -} veml7700_sensor; - - - - -void VEML7700Detect(void) { - if (!I2cSetDevice(veml7700_sensor.address)) return; - if (veml7700.begin()) { - I2cSetActiveFound(veml7700_sensor.address, veml7700_sensor.types); - veml7700_sensor.active = 1; - } -} - -uint16_t VEML7700TranslateItMs (uint8_t ittime){ - switch (ittime) { - case 0: return 100; - case 1: return 200; - case 2: return 400; - case 3: return 800; - case 8: return 50; - case 12: return 25; - default: return 0xFFFF; - } -} - -uint8_t VEML7700TranslateItInt (uint16_t ittimems){ - switch (ittimems) { - case 100: return 0; - case 200: return 1; - case 400: return 2; - case 800: return 3; - case 50: return 8; - case 25: return 12; - default: return 0xFF; - } -} - -void VEML7700EverySecond(void) { - veml7700_sensor.lux_normalized = (uint32_t) veml7700.readLuxNormalized(); - veml7700_sensor.white_normalized = (uint32_t) veml7700.readWhiteNormalized(); -} - -void VEML7700Show(bool json) -{ - if (json) { - ResponseAppend_P(JSON_SNS_VEML7700, D_NAME_VEML7700, veml7700_sensor.lux_normalized, veml7700_sensor.white_normalized); - -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, veml7700_sensor.lux_normalized); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, D_NAME_VEML7700, veml7700_sensor.lux_normalized); - WSContentSend_PD(HTTP_SNS_WHITE, D_NAME_VEML7700, veml7700_sensor.white_normalized); -#endif - } -} - -bool VEML7700Cmd(void) { - char command[CMDSZ]; - uint8_t name_len = strlen(D_NAME_VEML7700); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_VEML7700), name_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kVEML7700_Commands); - switch (command_code) { - case CMND_VEML7700_PWR: - if (XdrvMailbox.data_len) { - if (2 >= XdrvMailbox.payload) { - veml7700.enable(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.enabled()); - break; - case CMND_VEML7700_GAIN: - if (XdrvMailbox.data_len) { - if (4 >= XdrvMailbox.payload) { - veml7700.setGain(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.getGain()); - break; - case CMND_VEML7700_SET_IT: { - if (XdrvMailbox.data_len) { - uint8_t data = VEML7700TranslateItInt(XdrvMailbox.payload); - if (0xFF != data) { - veml7700.setIntegrationTime(data); - } - } - uint16_t dataret = VEML7700TranslateItMs(veml7700.getIntegrationTime()); - Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, dataret); - } - break; - case CMND_VEML7700_PERSIST: - if (XdrvMailbox.data_len) { - if (4 >= XdrvMailbox.payload) { - veml7700.setPersistence(XdrvMailbox.payload); - } - } - Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.getPersistence()); - break; - default: - return false; - } - return true; - } - else { - return false; - } -} - - - - -bool Xsns71(uint8_t function) -{ - if (!I2cEnabled(XI2C_50)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - VEML7700Detect(); - } - else if (veml7700_sensor.active) { - switch (function) { - case FUNC_EVERY_SECOND: - VEML7700EverySecond(); - break; - case FUNC_COMMAND: - result = VEML7700Cmd(); - break; - case FUNC_JSON_APPEND: - VEML7700Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - VEML7700Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_72_mcp9808.ino" -# 21 "/workspace/Tasmota/tasmota/xsns_72_mcp9808.ino" -#ifdef USE_I2C -#ifdef USE_MCP9808 - - - - - - - -#define XSNS_72 72 -#define XI2C_51 51 - -#include "Adafruit_MCP9808.h" -Adafruit_MCP9808 mcp9808 = Adafruit_MCP9808(); - -#define MCP9808_MAX_SENSORS 8 -#define MCP9808_START_ADDRESS 0x18 - -struct { -char types[9] = "MCP9808"; -uint8_t count = 0; -} mcp9808_cfg; - -struct { - float temperature = NAN; - uint8_t address; -} mcp9808_sensors[MCP9808_MAX_SENSORS]; - - - -float MCP9808Read(uint8_t addr) { - float t = mcp9808.readTempC(addr); - return t; -} - -void MCP9808Detect(void) { - for (uint8_t i = 0; i < MCP9808_MAX_SENSORS; i++) { - if (!I2cSetDevice(MCP9808_START_ADDRESS + i)) { continue; } - - if (mcp9808.begin(MCP9808_START_ADDRESS + i)) { - mcp9808_sensors[mcp9808_cfg.count].address = MCP9808_START_ADDRESS + i; - I2cSetActiveFound(mcp9808_sensors[mcp9808_cfg.count].address, mcp9808_cfg.types); - mcp9808.setResolution (mcp9808_sensors[mcp9808_cfg.count].address, 2); - mcp9808_cfg.count++; - } - } -} - -void MCP9808EverySecond(void) { - for (uint32_t i = 0; i < mcp9808_cfg.count; i++) { - float t = MCP9808Read(mcp9808_sensors[i].address); - mcp9808_sensors[i].temperature = ConvertTemp(t); - } -} - -void MCP9808Show(bool json) { - for (uint32_t i = 0; i < mcp9808_cfg.count; i++) { - char temperature[33]; - dtostrfd(mcp9808_sensors[i].temperature, Settings.flag2.temperature_resolution, temperature); - - char sensor_name[11]; - strlcpy(sensor_name, mcp9808_cfg.types, sizeof(sensor_name)); - if (mcp9808_cfg.count > 1) { - snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), mcp9808_sensors[i].address); - } - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, sensor_name, temperature); - if ((0 == tele_period) && (0 == i)) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, mcp9808_sensors[i].temperature); -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns72(uint8_t function) -{ - if (!I2cEnabled(XI2C_51)) { return false; } - bool result = false; - - if (FUNC_INIT == function) { - MCP9808Detect(); - } - else if (mcp9808_cfg.count){ - switch (function) { - case FUNC_EVERY_SECOND: - MCP9808EverySecond(); - break; - case FUNC_JSON_APPEND: - MCP9808Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MCP9808Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" -#ifdef USE_I2C -#ifdef USE_HP303B -# 30 "/workspace/Tasmota/tasmota/xsns_73_hp303b.ino" -#define XSNS_73 73 -#define XI2C_52 52 - -#define HP303B_MAX_SENSORS 2 -#define HP303B_START_ADDRESS 0x76 - -#include - -LOLIN_HP303B HP303BSensor = LOLIN_HP303B(); - -struct { - int16_t oversampling = 7; - char types[7] = "HP303B"; - uint8_t count = 0; -} hp303b_cfg; - -struct BHP303B { - float temperature = NAN; - float pressure = NAN; - uint8_t address; - uint8_t valid = 0; -} hp303b_sensor[HP303B_MAX_SENSORS]; - - - -bool HP303B_Read(uint32_t hp303b_idx) { - if (hp303b_sensor[hp303b_idx].valid) { hp303b_sensor[hp303b_idx].valid--; } - - float t; - if (HP303BSensor.measureTempOnce(t, hp303b_sensor[hp303b_idx].address, hp303b_cfg.oversampling) != 0) { - return false; - } - - float p; - if (HP303BSensor.measurePressureOnce(p, hp303b_sensor[hp303b_idx].address, hp303b_cfg.oversampling) != 0) { - return false; - } - - hp303b_sensor[hp303b_idx].temperature = (float)ConvertTemp(t); - hp303b_sensor[hp303b_idx].pressure = (float)ConvertPressure(p / 100); - - hp303b_sensor[hp303b_idx].valid = SENSOR_MAX_MISS; - return true; -} - - - -void HP303B_Detect(void) { - for (uint32_t i = 0; i < HP303B_MAX_SENSORS; i++) { - if (!I2cSetDevice(HP303B_START_ADDRESS + i)) { continue; } - - if (HP303BSensor.begin(HP303B_START_ADDRESS + i)) { - hp303b_sensor[hp303b_cfg.count].address = HP303B_START_ADDRESS + i; - I2cSetActiveFound(hp303b_sensor[hp303b_cfg.count].address, hp303b_cfg.types); - hp303b_cfg.count++; - } - } -} - -void HP303B_EverySecond(void) { - for (uint32_t i = 0; i < hp303b_cfg.count; i++) { - if (uptime &1) { - if (!HP303B_Read(i)) { - AddLogMissed(hp303b_cfg.types, hp303b_sensor[i].valid); - } - } - } -} - -void HP303B_Show(bool json) { - for (uint32_t i = 0; i < hp303b_cfg.count; i++) { - if (hp303b_sensor[i].valid) { - char sensor_name[12]; - strlcpy(sensor_name, hp303b_cfg.types, sizeof(sensor_name)); - if (hp303b_cfg.count > 1) { - snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), hp303b_sensor[i].address); - } - - float sealevel = 0.0; - if (hp303b_sensor[i].pressure != 0.0) { - sealevel = (hp303b_sensor[i].pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - sealevel = ConvertPressure(sealevel); - } - - char str_temperature[33]; - dtostrfd(hp303b_sensor[i].temperature, Settings.flag2.temperature_resolution, str_temperature); - char str_pressure[33]; - dtostrfd(hp303b_sensor[i].pressure, Settings.flag2.pressure_resolution, str_pressure); - char sea_pressure[33]; - dtostrfd(sealevel, Settings.flag2.pressure_resolution, sea_pressure); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_PRESSURE "\":%s"), sensor_name, str_temperature, str_pressure); - if (Settings.altitude != 0) { - ResponseAppend_P(PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_TEMP, hp303b_sensor[i].temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, str_temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_PRESSURE, sensor_name, str_pressure, PressureUnit().c_str()); - if (Settings.altitude != 0) { - WSContentSend_PD(HTTP_SNS_SEAPRESSURE, sensor_name, sea_pressure, PressureUnit().c_str()); - } -#endif - } - } - } -} - - - - - -bool Xsns73(uint8_t function) -{ - if (!I2cEnabled(XI2C_52)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - HP303B_Detect(); - } - else if (hp303b_cfg.count) { - switch (function) { - case FUNC_EVERY_SECOND: - HP303B_EverySecond(); - break; - case FUNC_JSON_APPEND: - HP303B_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HP303B_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_74_lmt01.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_74_lmt01.ino" -#ifdef USE_LMT01 - - - - - - - -#define XSNS_74 74 - -#define LMT01_TIMEOUT 200 - -bool lmt01_initialized = false; -float lmt01_temperature = NAN; - -void LMT01_Init(void) { - if (PinUsed(GPIO_LMT01)) { - pinMode(Pin(GPIO_LMT01), INPUT); - attachInterrupt(Pin(GPIO_LMT01), LMT01_countPulse, FALLING); - lmt01_initialized = true; - } -} - -volatile int lmt01_pulseCount = 0; - -void ICACHE_RAM_ATTR LMT01_countPulse(void) { - lmt01_pulseCount++; -} - -void LMT01_GetTemperature(void) { - int pulses = 0; - pulses = LMT01_getPulses(); - if (pulses >= 0) { - - - lmt01_temperature = ConvertTemp(0.0625 * pulses - 50); - } else { - lmt01_temperature = NAN; - } -} - -int LMT01_getPulses(void) { - int timeout = LMT01_TIMEOUT; - int hold = -1; - - while(lmt01_pulseCount != hold && --timeout > 0) { - hold = lmt01_pulseCount; - delay(1); - } - lmt01_pulseCount = 0; - - while(lmt01_pulseCount == 0 && --timeout > 0) { - delay(1); - } - hold = -1; - - while(lmt01_pulseCount != hold && --timeout > 0) { - hold = lmt01_pulseCount; - delay(1); - } - - if (timeout > 0 && hold >= 10) { - return hold; - } - return -1; -} - -void LMT01_Show(bool Json) { - char temp[33]; - dtostrfd(lmt01_temperature, Settings.flag2.temperature_resolution, temp); - - if (Json) { - ResponseAppend_P(JSON_SNS_TEMP, "LMT01", temp); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temp); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, lmt01_temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "LMT01", temp, TempUnit()); -#endif - } -} - - - - - -bool Xsns74(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - LMT01_Init(); - } - else if (lmt01_initialized) { - switch (function) { - case FUNC_EVERY_SECOND: - LMT01_GetTemperature(); - break; - case FUNC_JSON_APPEND: - LMT01_Show(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - LMT01_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" -#ifdef USE_PROMETHEUS - - - - -#define XSNS_75 75 - -void HandleMetrics(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); - - WSContentBegin(200, CT_PLAIN); - - - char parameter[FLOATSZ]; - - - WSContentSend_P(PSTR("# TYPE tasmota_info gauge\ntasmota_info{version=\"%s\",image=\"%s\",build_timestamp=\"%s\"} 1\n"), - my_version, my_image, GetBuildDateAndTime().c_str()); - WSContentSend_P(PSTR("# TYPE tasmota_uptime_seconds gauge\ntasmota_uptime_seconds %d\n"), uptime); - WSContentSend_P(PSTR("# TYPE tasmota_boot_count counter\ntasmota_boot_count %d\n"), Settings.bootcount); - WSContentSend_P(PSTR("# TYPE tasmota_flash_writes_total counter\ntasmota_flash_writes_total %d\n"), Settings.save_flag); - - - - WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_info gauge\ntasmota_wifi_station_info{bssid=\"%s\",ssid=\"%s\"} 1\n"), WiFi.BSSIDstr().c_str(), WiFi.SSID().c_str()); - - - WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_signal_dbm gauge\ntasmota_wifi_station_signal_dbm{mac_address=\"%s\"} %d\n"), WiFi.BSSIDstr().c_str(), WiFi.RSSI()); - - if (!isnan(global_temperature_celsius)) { - dtostrfd(global_temperature_celsius, Settings.flag2.temperature_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_temperature_celsius gauge\nglobal_temperature_celsius %s\n"), parameter); - } - if (global_humidity != 0) { - dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); - } - if (global_pressure_hpa != 0) { - dtostrfd(global_pressure_hpa, Settings.flag2.pressure_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_pressure_hpa gauge\nglobal_pressure_hpa %s\n"), parameter); - } - -#ifdef USE_ENERGY_SENSOR - dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_voltage_volts gauge\nenergy_voltage_volts %s\n"), parameter); - dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_current_amperes gauge\nenergy_current_amperes %s\n"), parameter); - dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_power_active_watts gauge\nenergy_power_active_watts %s\n"), parameter); - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_daily counter\nenergy_power_kilowatts_daily %s\n"), parameter); - dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter); -#endif -# 92 "/workspace/Tasmota/tasmota/xsns_75_prometheus.ino" - WSContentEnd(); -} - - - - - -bool Xsns75(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer_on(PSTR("/metrics"), HandleMetrics); - break; - } - return result; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" -#ifdef USE_DYP -# 34 "/workspace/Tasmota/tasmota/xsns_76_dyp.ino" -#define XSNS_76 76 - -#include - -TasmotaSerial *DYPSerial = nullptr; - -#define DYP_CRCERROR -1 -#define DYP_BELOWMIN 0 -#define DYP_MIN 300 -#define DYP_MAX 4000 -#define DYP_ABOVEMAX 4999 -#define DYP_NOSENSOR 5999 - -uint16_t DYPDistance = 0; -bool DYPSensor = false; - - - -void DYPInit(void) { - DYPSensor = false; - if (PinUsed(GPIO_DYP_RX)) { - DYPSerial = new TasmotaSerial(Pin(GPIO_DYP_RX), -1, 1); - if (DYPSerial->begin(9600)) { - if (DYPSerial->hardwareSerial()) { - ClaimSerial(); - } - DYPSensor = true; - } - } -} - -void DYPEverySecond(void) { - if (!DYPSensor) { return; } - - - if (DYPSerial->available() < 6) { - DYPDistance = DYP_NOSENSOR; - return; - } - - - while (DYPSerial->available() > 7) { - DYPSerial->read(); - } - - - while (DYPSerial->available() > 3) { - - if (DYPSerial->read() != 0xFF) { - continue; - } - - - if (DYPSerial->available() > 2) { - uint8_t msb = DYPSerial->read(); - uint8_t lsb = DYPSerial->read(); - if (((uint16_t)(0xFF + msb + lsb) & 0xFF) == DYPSerial->read()) { - uint16_t data = (msb << 8) | lsb; - if (data < DYP_MIN) { - data = DYP_BELOWMIN; - } - if (data > DYP_MAX) { - data = DYP_ABOVEMAX; - } - DYPDistance = data; - } else { - DYPDistance = DYP_CRCERROR; - } - } - } -} - -void DYPShow(bool json) { - char types[5] = "DYP"; - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_DISTANCE "\":%d}"), types, DYPDistance); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_RANGE, types, DYPDistance); -#endif - } -} - - - - - -bool Xsns76(uint8_t function) { - if (!PinUsed(GPIO_DYP_RX)) { return false; } - - switch (function) { - case FUNC_INIT: - DYPInit(); - break; - case FUNC_EVERY_SECOND: - DYPEverySecond(); - break; - case FUNC_JSON_APPEND: - DYPShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DYPShow(0); - break; -#endif - } - return false; -} - -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" -#ifdef USE_I2C -#ifdef USE_VL53L1X -# 30 "/workspace/Tasmota/tasmota/xsns_77_vl53l1x.ino" -#define XSNS_77 77 -#define XI2C_54 54 - -#include "VL53L1X.h" -VL53L1X vl53l1x = VL53L1X(); - -#define VL53L1X_ADDRESS 0x29 - -struct { - bool ready = false; - uint16_t distance = 0; -} vl53l1x_sensors; - - - -void Vl53l1Detect(void) { - if (!I2cSetDevice(VL53L1X_ADDRESS)) { return; } - if (!vl53l1x.init()) { return; } - - I2cSetActiveFound(vl53l1x.getAddress(), "VL53L1X"); - vl53l1x.setTimeout(500); - vl53l1x.setDistanceMode(VL53L1X::Long); - vl53l1x.setMeasurementTimingBudget(140000); - vl53l1x.startContinuous(50); - vl53l1x_sensors.ready = true; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_VL53L1X[] PROGMEM = - "{s}VL53L1X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; -#endif - -void Vl53l1Every_250MSecond(void) { - - uint16_t dist = vl53l1x.read(); - if (!dist || dist > 4000) { - dist = 9999; - } - vl53l1x_sensors.distance = dist; -} - -#ifdef USE_DOMOTICZ -void Vl53l1Every_Second(void) { - char distance[FLOATSZ]; - dtostrfd((float)vl53l1x_sensors.distance / 10, 1, distance); - DomoticzSensor(DZ_ILLUMINANCE, distance); -} -#endif - -void Vl53l1Show(bool json) { - if (json) { -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - Vl53l1Every_Second(); - } -#endif - ResponseAppend_P(PSTR(",\"VL53L1X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l1x_sensors.distance); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VL53L1X, vl53l1x_sensors.distance); -#endif - } -} - - - - - -bool Xsns77(uint8_t function) -{ - if (!I2cEnabled(XI2C_54)) { return false; } - bool result = false; - - if (FUNC_INIT == function) { - Vl53l1Detect(); - } - else if (vl53l1x_sensors.ready) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - Vl53l1Every_250MSecond(); - break; -#ifdef USE_DOMOTICZ - case FUNC_EVERY_SECOND: - Vl53l1Every_Second(); - break; -#endif - case FUNC_JSON_APPEND: - Vl53l1Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Vl53l1Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezo.ino" -# 19 "/workspace/Tasmota/tasmota/xsns_78_ezo.ino" -#ifdef USE_I2C - -#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) - #define USE_EZO -#endif -#if defined(USE_EZO) - -#define D_EZO_DELAY 300 -#define D_EZO_MAX_BUF 40 - -const char D_EZO_NAME[] PROGMEM = "EZO"; - - - - -struct EZOStruct { - EZOStruct(uint32_t addr) : valid(0), addr(addr), lastRead(-2000) {} - - void MeasureRequest(void) - { - const uint8_t EZOMeasureCmd[2] = {'R', 0}; - - if (valid) { - valid--; - } - - Wire.beginTransmission(addr); - Wire.write(EZOMeasureCmd, sizeof(EZOMeasureCmd)); - Wire.endTransmission(); - - lastRead = millis(); - } - - void HandleCommand(char *cmd, uint32_t len) const - { - - Wire.beginTransmission(addr); - Wire.write(cmd, len); - if (Wire.endTransmission() != 0) { - return; - } - - - char data[D_EZO_MAX_BUF]; - for (uint32_t code = 254; code == 254; code = Wire.read()) { - delay(D_EZO_DELAY); - Wire.requestFrom(addr, sizeof(data)); - } - - for (uint32_t i = 0; Wire.available() > 0; i++) { - data[i] = Wire.read(); - } - - ResponseCmndChar((char *)data); - } - - bool isValid(void) - { - return valid; - } - - virtual void ProcessMeasurement(void); - virtual void Show(bool json, const char *name); - - static const char id[] PROGMEM; - -protected: - void ProcessMeasurement(char *const data, const uint32_t len, const uint32_t latency) - { - - const int32_t dur = lastRead + latency - millis(); - - - if (dur > 0) { - delay(dur); - } - - Wire.requestFrom(addr, len); - const char code = Wire.read(); - - if (code == 1) { - for (uint32_t i = 0; (Wire.available() > 0) && (i < len); i++) { - data[i] = Wire.read(); - } - - valid = SENSOR_MAX_MISS; - } - } - - uint8_t valid; - uint8_t addr; - uint32_t lastRead; -}; - -const char EZOStruct::id[] PROGMEM = ""; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoco2.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoco2.ino" -#ifdef USE_I2C -#ifdef USE_EZOCO2 - -#define EZO_CO2_READ_LATENCY 900 - -struct EZOCO2 : public EZOStruct { - EZOCO2(uint32_t addr) : EZOStruct(addr), CO2(0) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_CO2_READ_LATENCY); - - - if (uptime >= 10) { - CO2 = atoi(data); - } - } - - virtual void Show(bool json, const char *name) - { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d}" ), name, CO2); - } -#ifdef USE_WEBSERVER - else { - WSContentSend_PD(HTTP_SNS_CO2, name, CO2); -#endif - } - } - - static const char id[] PROGMEM; - -private: - uint16_t CO2; -}; - -const char EZOCO2::id[] PROGMEM = "CO2"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoec.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoec.ino" -#ifdef USE_I2C -#ifdef USE_EZOEC - -#define EZO_EC_READ_LATENCY 600 - -struct EZOEC : public EZOStruct { - EZOEC(uint32_t addr) : EZOStruct(addr), EC(NAN) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_EC_READ_LATENCY); - EC = CharToFloat(data); - } - - virtual void Show(bool json, const char *name) - { - char str[10]; - dtostrfd(EC, 3, str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_EC "\":%s}" ), name, str); - } -#ifdef USE_WEBSERVER - else { - WSContentSend_PD(HTTP_SNS_EC, name, str); -#endif - } - } - - static const char id[] PROGMEM; - -private: - float EC; -}; - -const char EZOEC::id[] PROGMEM = "EC"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezohum.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezohum.ino" -#ifdef USE_I2C -#ifdef USE_EZOHUM - -#define EZO_HUM_READ_LATENCY 300 - -struct EZOHUM : public EZOStruct { - EZOHUM(uint32_t addr) : EZOStruct(addr), humidity(NAN), temperature(NAN) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_HUM_READ_LATENCY); - - humidity = CharToFloat(data); - - char *next = strchr(data, ','); - if (next) { - temperature = CharToFloat(next + 1); - } - } - - virtual void Show(bool json, const char *name) - { - if (isnan(temperature)) { - char parameter[FLOATSZ]; - - dtostrfd(humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_PD(HTTP_SNS_HUM, name, parameter); - } else { - TempHumDewShow(json, (0 == tele_period), name, temperature, humidity); - } - } - - static const char id[] PROGMEM; - -private: - float humidity; - float temperature; -}; - -const char EZOHUM::id[] PROGMEM = "HUM"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoorp.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoorp.ino" -#ifdef USE_I2C -#ifdef USE_EZOORP - -#define EZO_ORP_READ_LATENCY 900 - -struct EZOORP : public EZOStruct { - EZOORP(uint32_t addr) : EZOStruct(addr), ORP(NAN) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_ORP_READ_LATENCY); - ORP = CharToFloat(data); - } - - virtual void Show(bool json, const char *name) - { - char str[8]; - dtostrfd(ORP, 2, str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ORP "\":%s}" ), name, str); - } -#ifdef USE_WEBSERVER - else { - WSContentSend_PD(HTTP_SNS_ORP, name, str); -#endif - } - } - - static const char id[] PROGMEM; - -private: - float ORP; -}; - -const char EZOORP::id[] PROGMEM = "ORP"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezoph.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezoph.ino" -#ifdef USE_I2C -#ifdef USE_EZOPH - -#define EZO_PH_READ_LATENCY 900 - -struct EZOPH : public EZOStruct { - EZOPH(uint32_t addr) : EZOStruct(addr), pH(NAN) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_PH_READ_LATENCY); - pH = CharToFloat(data); - } - - virtual void Show(bool json, const char *name) - { - char str[6]; - dtostrfd(pH, 2, str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PH "\":%s}" ), name, str); - } -#ifdef USE_WEBSERVER - else { - WSContentSend_PD(HTTP_SNS_PH, name, str); -#endif - } - } - - static const char id[] PROGMEM; - -private: - float pH; -}; - -const char EZOPH::id[] PROGMEM = "pH"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_ezortd.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_ezortd.ino" -#ifdef USE_I2C -#ifdef USE_EZORTD - -#define EZO_RTD_READ_LATENCY 600 - -struct EZORTD : public EZOStruct { - EZORTD(uint32_t addr) : EZOStruct(addr), temperature(NAN) {} - - virtual void ProcessMeasurement(void) - { - char data[D_EZO_MAX_BUF]; - - EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_RTD_READ_LATENCY); - temperature = CharToFloat(data); - } - - virtual void Show(bool json, const char *name) - { - char str[10]; - dtostrfd(ConvertTemp(temperature), Settings.flag2.temperature_resolution, str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), name, str); - } -#ifdef USE_WEBSERVER - else { - WSContentSend_PD(HTTP_SNS_TEMP, name, str, TempUnit()); -#endif - } - } - - static const char id[] PROGMEM; - -private: - float temperature; -}; - -const char EZORTD::id[] PROGMEM = "RTD"; - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_78_xezo.ino" -# 20 "/workspace/Tasmota/tasmota/xsns_78_xezo.ino" -#ifdef USE_I2C -#if defined(USE_EZO) - -#define XSNS_78 78 -#define XI2C_55 55 - -#define EZO_ADDR_0 0x61 -#define EZO_ADDR_n 16 - - - -enum { - EZO_DO = 0x61, - EZO_ORP = 0x62, - EZO_PH = 0x63, - EZO_EC = 0x64, - - EZO_RTD = 0x66, - EZO_PMP = 0x67, - EZO_FLO = 0x68, - EZO_CO2 = 0x69, - EZO_PRS = 0x6A, - - EZO_O2 = 0x6C, - - - EZO_HUM = 0x6F, - EZO_RGB = 0x70, -}; - - - - -template struct IsComplete : std::false_type {}; -template struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type {}; - -#define GET_EZO_CLASS(CLASS) std::conditional::value, CLASS, EZOStruct>::type - - -const char *const EZOSupport[EZO_ADDR_n] PROGMEM = { - EZOStruct::id, - GET_EZO_CLASS(EZOORP)::id, - GET_EZO_CLASS(EZOPH)::id, - GET_EZO_CLASS(EZOEC)::id, - EZOStruct::id, - GET_EZO_CLASS(EZORTD)::id, - EZOStruct::id, - EZOStruct::id, - GET_EZO_CLASS(EZOCO2)::id, - EZOStruct::id, - EZOStruct::id, - EZOStruct::id, - EZOStruct::id, - EZOStruct::id, - GET_EZO_CLASS(EZOHUM)::id, - EZOStruct::id, -}; - -#define CREATE_EZO_CLASS(CLASS) \ - case EZO_ ## CLASS: \ - sensor[count] = new EZO ## CLASS(addr); \ - break; - - -struct EZOManager { - void Command() - { - char *at = XdrvMailbox.data; - uint32_t len = XdrvMailbox.data_len; - - - - if (at[0] == '-') { - int32_t idx = atoi(&at[1]) - 1; - at = strchr(at, ' '); - - if (!at++) { - return; - } - - len -= (at - XdrvMailbox.data); - - if ((idx >= 0) && (idx < count)) { - sensor[idx]->ProcessMeasurement(); - sensor[idx]->HandleCommand(at, len); - } - } else { - for (uint32_t i = 0; i < count; i++) { - sensor[i]->ProcessMeasurement(); - sensor[i]->HandleCommand(at, len); - } - } - } - - void EverySecond() - { - - if (count < 0) { - - if (uptime >= next) { - count++; - - if (count == -1) { - DetectRequest(); - next = uptime + 1; - } else if (count == 0) { - ProcessDetection(); - } - } - } - - for (int32_t i = 0; i < count; i++) { - sensor[i]->ProcessMeasurement(); - sensor[i]->MeasureRequest(); - } - } - - void Show(bool json) - { - for (int32_t i = 0; i < count; i++) { - if (sensor[i]->isValid()) { - char name[7]; - snprintf_P(name, sizeof(name), PSTR("%s%c%X"), D_EZO_NAME, IndexSeparator(), i + 1); - - if (count == 1) { - name[sizeof(D_EZO_NAME) - 1] = 0; - } - - sensor[i]->Show(json, name); - } - } - } - -private: - void DetectRequest(void) - { - const uint8_t EZOInfoCmd[2] = {'i', 0}; - alive = 0; - - - uint16_t shift = 1; - for (uint8_t i = EZO_ADDR_0; shift; i++) { - if (!I2cActive(i)) { - - Wire.beginTransmission(i); - Wire.write(EZOInfoCmd, sizeof(EZOInfoCmd)); - - int c = Wire.endTransmission(); - - if (c == 0) { - alive |= shift; - } - } - shift <<= 1; - } - } - - void ProcessDetection(void) - { - - for (uint8_t addr = EZO_ADDR_0; addr < EZO_ADDR_0 + EZO_ADDR_n; addr++) { - if (alive & 1) { - char data[D_EZO_MAX_BUF]; - Wire.requestFrom(addr, sizeof(data)); - char code = Wire.read(); - - if (code == 1) { - uint32_t i; - - for (i = 0; Wire.available() > 0; i++) { - char c = Wire.read(); - - - data[i] = (c == ',') ? 0 : c; - } - - - if (i >= 3) { - for (uint32_t j = 0; j < EZO_ADDR_n; j++) { - if (strcasecmp_P(&data[3], EZOSupport[j]) == 0) { - data[0] = 'E'; - data[1] = 'Z'; - data[2] = 'O'; - I2cSetActiveFound(addr, data); - - - switch (j + EZO_ADDR_0) { -#ifdef USE_EZOORP - CREATE_EZO_CLASS(ORP) -#endif -#ifdef USE_EZOPH - CREATE_EZO_CLASS(PH) -#endif -#ifdef USE_EZOEC - CREATE_EZO_CLASS(EC) -#endif -#ifdef USE_EZORTD - CREATE_EZO_CLASS(RTD) -#endif -#ifdef USE_EZOCO2 - CREATE_EZO_CLASS(CO2) -#endif -#ifdef USE_EZOHUM - CREATE_EZO_CLASS(HUM) -#endif - } - - count++; - } - } - } - } - } - - alive >>= 1; - } - } - - uint32_t next = 2; - int8_t count = -2; - - - uint16_t alive; - EZOStruct *sensor[EZO_ADDR_n]; -} EZOManager; - - - - - -bool Xsns78(uint8_t function) -{ - if (!I2cEnabled(XI2C_55)) { - return false; - } - - switch (function) { - case FUNC_COMMAND_SENSOR: - EZOManager.Command(); - break; - - case FUNC_EVERY_SECOND: - EZOManager.EverySecond(); - break; - - case FUNC_JSON_APPEND: - EZOManager.Show(1); - break; - -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - EZOManager.Show(0); - break; -#endif - } - - return false; -} - -#endif -#endif -# 1 "/workspace/Tasmota/tasmota/xsns_interface.ino" -# 20 "/workspace/Tasmota/tasmota/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) -{ - if (0 == xsns_present) { - xsns_index = 0; - return false; - } - - 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; - - DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); - -#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; -} -# 1 "/workspace/Tasmota/tasmota/xx2c_interface.ino" -# 20 "/workspace/Tasmota/tasmota/xx2c_interface.ino" -#ifdef USE_I2C - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kI2cList[] PROGMEM = { -#else -const uint8_t kI2cList[] = { -#endif - -#ifdef XI2C_01 - XI2C_01, -#endif - -#ifdef XI2C_02 - XI2C_02, -#endif - -#ifdef XI2C_03 - XI2C_03, -#endif - -#ifdef XI2C_04 - XI2C_04, -#endif - -#ifdef XI2C_05 - XI2C_05, -#endif - -#ifdef XI2C_06 - XI2C_06, -#endif - -#ifdef XI2C_07 - XI2C_07, -#endif - -#ifdef XI2C_08 - XI2C_08, -#endif - -#ifdef XI2C_09 - XI2C_09, -#endif - -#ifdef XI2C_10 - XI2C_10, -#endif - -#ifdef XI2C_11 - XI2C_11, -#endif - -#ifdef XI2C_12 - XI2C_12, -#endif - -#ifdef XI2C_13 - XI2C_13, -#endif - -#ifdef XI2C_14 - XI2C_14, -#endif - -#ifdef XI2C_15 - XI2C_15, -#endif - -#ifdef XI2C_16 - XI2C_16, -#endif - -#ifdef XI2C_17 - XI2C_17, -#endif - -#ifdef XI2C_18 - XI2C_18, -#endif - -#ifdef XI2C_19 - XI2C_19, -#endif - -#ifdef XI2C_20 - XI2C_20, -#endif - -#ifdef XI2C_21 - XI2C_21, -#endif - -#ifdef XI2C_22 - XI2C_22, -#endif - -#ifdef XI2C_23 - XI2C_23, -#endif - -#ifdef XI2C_24 - XI2C_24, -#endif - -#ifdef XI2C_25 - XI2C_25, -#endif - -#ifdef XI2C_26 - XI2C_26, -#endif - -#ifdef XI2C_27 - XI2C_27, -#endif - -#ifdef XI2C_28 - XI2C_28, -#endif - -#ifdef XI2C_29 - XI2C_29, -#endif - -#ifdef XI2C_30 - XI2C_30, -#endif - -#ifdef XI2C_31 - XI2C_31, -#endif - -#ifdef XI2C_32 - XI2C_32, -#endif - -#ifdef XI2C_33 - XI2C_33, -#endif - -#ifdef XI2C_34 - XI2C_34, -#endif - -#ifdef XI2C_35 - XI2C_35, -#endif - -#ifdef XI2C_36 - XI2C_36, -#endif - -#ifdef XI2C_37 - XI2C_37, -#endif - -#ifdef XI2C_38 - XI2C_38, -#endif - -#ifdef XI2C_39 - XI2C_39, -#endif - -#ifdef XI2C_40 - XI2C_40, -#endif - -#ifdef XI2C_41 - XI2C_41, -#endif - -#ifdef XI2C_42 - XI2C_42, -#endif - -#ifdef XI2C_43 - XI2C_43, -#endif - -#ifdef XI2C_44 - XI2C_44, -#endif - -#ifdef XI2C_45 - XI2C_45, -#endif - -#ifdef XI2C_46 - XI2C_46, -#endif - -#ifdef XI2C_47 - XI2C_47, -#endif - -#ifdef XI2C_48 - XI2C_48, -#endif - -#ifdef XI2C_49 - XI2C_49, -#endif - -#ifdef XI2C_50 - XI2C_50, -#endif - -#ifdef XI2C_51 - XI2C_51, -#endif - -#ifdef XI2C_52 - XI2C_52, -#endif - -#ifdef XI2C_53 - XI2C_53, -#endif - -#ifdef XI2C_54 - XI2C_54, -#endif - -#ifdef XI2C_55 - XI2C_55, -#endif - -#ifdef XI2C_56 - XI2C_56, -#endif - -#ifdef XI2C_57 - XI2C_57, -#endif - -#ifdef XI2C_58 - XI2C_58, -#endif - -#ifdef XI2C_59 - XI2C_59, -#endif - -#ifdef XI2C_60 - XI2C_60, -#endif - -#ifdef XI2C_61 - XI2C_61, -#endif - -#ifdef XI2C_62 - XI2C_62, -#endif - -#ifdef XI2C_63 - XI2C_63, -#endif - -#ifdef XI2C_64 - XI2C_64, -#endif - -#ifdef XI2C_65 - XI2C_65, -#endif - -#ifdef XI2C_66 - XI2C_66, -#endif - -#ifdef XI2C_67 - XI2C_67, -#endif - -#ifdef XI2C_68 - XI2C_68, -#endif - -#ifdef XI2C_69 - XI2C_69, -#endif - -#ifdef XI2C_70 - XI2C_70, -#endif - -#ifdef XI2C_71 - XI2C_71, -#endif - -#ifdef XI2C_72 - XI2C_72, -#endif - -#ifdef XI2C_73 - XI2C_73, -#endif - -#ifdef XI2C_74 - XI2C_74, -#endif - -#ifdef XI2C_75 - XI2C_75, -#endif - -#ifdef XI2C_76 - XI2C_76, -#endif - -#ifdef XI2C_77 - XI2C_77, -#endif - -#ifdef XI2C_78 - XI2C_78, -#endif - -#ifdef XI2C_79 - XI2C_79, -#endif - -#ifdef XI2C_80 - XI2C_80, -#endif - -#ifdef XI2C_81 - XI2C_81, -#endif - -#ifdef XI2C_82 - XI2C_82, -#endif - -#ifdef XI2C_83 - XI2C_83, -#endif - -#ifdef XI2C_84 - XI2C_84, -#endif - -#ifdef XI2C_85 - XI2C_85, -#endif - -#ifdef XI2C_86 - XI2C_86, -#endif - -#ifdef XI2C_87 - XI2C_87, -#endif - -#ifdef XI2C_88 - XI2C_88, -#endif - -#ifdef XI2C_89 - XI2C_89, -#endif - -#ifdef XI2C_90 - XI2C_90, -#endif - -#ifdef XI2C_91 - XI2C_91, -#endif - -#ifdef XI2C_92 - XI2C_92, -#endif - -#ifdef XI2C_93 - XI2C_93, -#endif - -#ifdef XI2C_94 - XI2C_94, -#endif - -#ifdef XI2C_95 - XI2C_95, -#endif - -#ifdef XI2C_96 - XI2C_96 -#endif -}; - - - -bool I2cEnabled(uint32_t i2c_index) -{ - return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); -} - -void I2cDriverState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kI2cList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); -#else - uint32_t i2c_driver_id = kI2cList[i]; -#endif - bool disabled = false; - if (i2c_driver_id < MAX_I2C_DRIVERS) { - disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); - } - ResponseAppend_P(PSTR("\"")); -} - -#endif \ No newline at end of file From b6e6e76e954d8fb5e668b944ea03a9c970a4477a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 26 Oct 2020 15:20:48 +0100 Subject: [PATCH 37/38] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f0bda9039..3211e2985 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build build_output firmware.map firmware.asm +tasmota.ino.cpp tasmota*.bin tasmota*.bin.gz tasmota*.map From e030b9fece5505f45d5d3eca6d664394ecda7949 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 26 Oct 2020 16:42:44 +0100 Subject: [PATCH 38/38] Fix rule expressions using mems corrupts character pool Fix rule expressions using mems corrupts character pool (#9301) --- CHANGELOG.md | 4 ++++ RELEASENOTES.md | 2 ++ tasmota/xdrv_10_rules.ino | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a1c370f..ddef54c65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,12 @@ All notable changes to this project will be documented in this file. ### Added - TLS in binary tasmota-zbbridge (#9620) +### Changed +- PlatformIO library structure redesigned for compilation speed by Jason2866 + ### Fixed - Rule Break not working as expected when ONCE is enabled (#9245) +- Rule expressions using mems corrupts character pool (#9301) ## [9.0.0.2] - 20201025 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3f9f212ba..bbd0c486a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -97,6 +97,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Rotary driver adjusted accordingly if Mi Desk Lamp module is selected (#9399) - Tasmota Arduino Core v2.7.4.5 allowing webpassword over 47 characters (#9687) - Webserver code optimizations (#9580, #9590) +- PlatformIO library structure redesigned for compilation speed by Jason2866 ### Fixed - Ledlink blink when no network connected regression from v8.3.1.4 (#9292) @@ -113,6 +114,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Zigbee battery percentage (#9607) - HassAnyKey anomaly (#9601) - Rule Break not working as expected when ONCE is enabled (#9245) +- Rule expressions using mems corrupts character pool (#9301) ### Removed - Support for direct upgrade from Tasmota versions before v7.0 diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 35b7525dc..accb43042 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -2176,7 +2176,10 @@ void CmndMemory(void) if (XdrvMailbox.data_len > 0) { #ifdef USE_EXPRESSION if (XdrvMailbox.data[0] == '=') { // Spaces already been skipped in data - dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, SettingsText(SET_MEM1 + XdrvMailbox.index -1)); + char rules_mem[FLOATSZ]; + dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_mem); + SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, rules_mem); + } else { SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); }