mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Merge branch 'development' into pre-release-9.1.0
This commit is contained in:
commit
1838c582b3
@ -134,6 +134,7 @@
|
||||
| USE_MCP9808 | - | - | - | - | - | - | - |
|
||||
| USE_HP303B | - | - | - | - | - | - | - |
|
||||
| USE_EZOCO2 | - | - | - | - | - | - | - |
|
||||
| USE_EZODO | - | - | - | - | - | - | - |
|
||||
| USE_EZOEC | - | - | - | - | - | - | - |
|
||||
| USE_EZOFLO | - | - | - | - | - | - | - |
|
||||
| USE_EZOHUM | - | - | - | - | - | - | - |
|
||||
|
@ -15,11 +15,13 @@ All notable changes to this project will be documented in this file.
|
||||
- Support for EZO O2 sensors by Christopher Tremblay (#9619)
|
||||
- Support for EZO PRS sensors by Christopher Tremblay (#9659)
|
||||
- Support for EZO FLO sensors by Christopher Tremblay (#9697)
|
||||
- Support for EZO DO sensors by Christopher Tremblay (#9707)
|
||||
- Zigbee reduce battery drain (#9642)
|
||||
- Zigbee command ``ZbMap`` to describe Zigbee topology (#9651)
|
||||
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
|
||||
- Command ``Gpios 255`` to show all possible GPIO configurations
|
||||
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
|
||||
- HM10 Beacon support and refactoring by Christian Baars (#9702)
|
||||
|
||||
### Changed
|
||||
- PlatformIO library structure redesigned for compilation speed by Jason2866
|
||||
@ -29,6 +31,8 @@ All notable changes to this project will be documented in this file.
|
||||
### Fixed
|
||||
- Rule Break not working as expected when ONCE is enabled (#9245)
|
||||
- Rule expressions using mems corrupts character pool (#9301)
|
||||
- Button press rules regression introduced by #9589 (#9700)
|
||||
- Rule handling of JSON ``null`` regression from v8.5.0.1 (#9685)
|
||||
|
||||
## [9.0.0.2] - 20201025
|
||||
### Added
|
||||
@ -45,9 +49,10 @@ All notable changes to this project will be documented in this file.
|
||||
- Support for EZO CO2 sensors by Christopher Tremblay (#9619)
|
||||
- On ZigbeeBridge support for glowing led when permit join is active (#9581)
|
||||
- Support for PWM Dimmer multi-press and ledmask (#9584)
|
||||
- Make button press rules override PWM Dimmer functions (#9589)
|
||||
- Support for fixed output Hi or Lo GPIO selection
|
||||
- ESP32 support for Wireless-Tag WT32-ETH01 (#9496)
|
||||
- ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring (#9609)
|
||||
- ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring by Christian Baars (#9609)
|
||||
|
||||
### Changed
|
||||
- Command ``Gpio17`` replaces command ``Adc``
|
||||
|
@ -86,3 +86,4 @@ Index | Define | Driver | Device | Address(es) | Description
|
||||
55 | USE_EZOO2 | xsns_78 | EZOO2 | 0x61 - 0x70 | O2 sensor
|
||||
55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor
|
||||
55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor
|
||||
55 | USE_EZODO | xsns_78 | EZODO | 0x61 - 0x70 | Disolved Oxygen sensor
|
||||
|
@ -81,7 +81,8 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
- TLS in binary tasmota-zbbridge (#9620)
|
||||
- Zigbee reduce battery drain (#9642)
|
||||
- ESP32 support for Wireless-Tag WT32-ETH01 (#9496)
|
||||
- ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring (#9609)
|
||||
- ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring by Christian Baars (#9609)
|
||||
- HM10 Beacon support and refactoring by Christian Baars (#9702)
|
||||
|
||||
### Breaking Changed
|
||||
- Redesigned ESP8266 GPIO internal representation in line with ESP32 changing ``Template`` layout too
|
||||
@ -113,6 +114,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
- Thermostat sensor status corruption regression from v8.5.0.1 (#9449)
|
||||
- Telegram message decoding error regression from v8.5.0.1
|
||||
- Rule handling of Var or Mem using text regression from v8.5.0.1 (#9540)
|
||||
- Rule handling of JSON ``null`` regression from v8.5.0.1 (#9685)
|
||||
- Correct Energy period display shortly after midnight by gominoa (#9536)
|
||||
- TuyaMcu energy display regression from v8.5.0.1 (#9547)
|
||||
- Tuyamcu dimmers MQTT topic (#9606)
|
||||
|
@ -28,7 +28,7 @@ const char * k_current_json_buffer = "";
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Lightweight String to Float, because atof() or strtof() takes 10KB
|
||||
*
|
||||
*
|
||||
* To remove code, exponents are not parsed
|
||||
* (commented out below, just in case we need them after all)
|
||||
\*********************************************************************************************/
|
||||
@ -51,7 +51,7 @@ float json_strtof(const char* s) {
|
||||
}
|
||||
|
||||
while ((unsigned int)(*p - '0') < 10u) {
|
||||
value = value*10 + (*p++ - '0');
|
||||
value = value*10 + (*p++ - '0');
|
||||
}
|
||||
|
||||
if (*p == '.' ) {
|
||||
@ -335,7 +335,7 @@ float JsonParserToken::getFloat(float val) const {
|
||||
}
|
||||
const char * JsonParserToken::getStr(const char * val) const {
|
||||
if (t->type == JSMN_INVALID) { return val; }
|
||||
if (t->type == JSMN_NULL) return "";
|
||||
if (t->type == JSMN_NULL) return "null";
|
||||
return (t->type >= JSMN_STRING) ? &k_current_json_buffer[t->start] : val;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ JsonParserToken JsonParserObject::findStartsWith(const char * needle) const {
|
||||
if ((!this->isValid()) || (nullptr == needle) || (0 == pgm_read_byte(needle))) {
|
||||
return JsonParserToken(&token_bad);
|
||||
}
|
||||
|
||||
|
||||
String needle_s((const __FlashStringHelper *)needle);
|
||||
needle_s.toLowerCase();
|
||||
|
||||
|
292
platformio.ini
292
platformio.ini
@ -1,146 +1,146 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter, extra scripting
|
||||
; Upload options: custom port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/en/stable/projectconf.html
|
||||
|
||||
|
||||
; *** Tasmota build variant selection
|
||||
[build_envs]
|
||||
default_envs =
|
||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||
; tasmota
|
||||
; tasmota-ircustom
|
||||
; tasmota-minimal
|
||||
; tasmota-lite
|
||||
; tasmota-knx
|
||||
; tasmota-sensors
|
||||
; tasmota-display
|
||||
; tasmota-zbbridge
|
||||
; tasmota-ir
|
||||
; tasmota-BG
|
||||
; tasmota-BR
|
||||
; tasmota-CN
|
||||
; tasmota-CZ
|
||||
; tasmota-DE
|
||||
; tasmota-ES
|
||||
; tasmota-FR
|
||||
; tasmota-GR
|
||||
; tasmota-HE
|
||||
; tasmota-HU
|
||||
; tasmota-IT
|
||||
; tasmota-KO
|
||||
; tasmota-NL
|
||||
; tasmota-PL
|
||||
; tasmota-PT
|
||||
; tasmota-RO
|
||||
; tasmota-RU
|
||||
; tasmota-SE
|
||||
; tasmota-SK
|
||||
; tasmota-TR
|
||||
; tasmota-TW
|
||||
; tasmota-UK
|
||||
; tasmota-VN
|
||||
;
|
||||
; *** Selection for Tasmota ESP32 is done in platformio_tasmota32.ini
|
||||
;
|
||||
; *** alternatively can be done in: platformio_override.ini
|
||||
; *** See example: platformio_override_sample.ini
|
||||
; *********************************************************************
|
||||
|
||||
[platformio]
|
||||
description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware
|
||||
src_dir = tasmota
|
||||
lib_dir = lib/default
|
||||
build_cache_dir = .cache
|
||||
extra_configs = platformio_tasmota32.ini
|
||||
platformio_tasmota_env.ini
|
||||
platformio_tasmota_env32.ini
|
||||
platformio_override.ini
|
||||
default_envs = ${build_envs.default_envs}
|
||||
|
||||
[common]
|
||||
framework = arduino
|
||||
board = esp01_1m
|
||||
board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.1m.ld
|
||||
|
||||
platform = ${core.platform}
|
||||
platform_packages = ${core.platform_packages}
|
||||
build_unflags = ${core.build_unflags}
|
||||
build_flags = ${core.build_flags}
|
||||
|
||||
board_build.f_cpu = 80000000L
|
||||
board_build.f_flash = 40000000L
|
||||
monitor_speed = 115200
|
||||
upload_speed = 115200
|
||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||
upload_resetmethod = nodemcu
|
||||
upload_port = COM5
|
||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
lib_ldf_mode = chain+
|
||||
shared_libdeps_dir = lib
|
||||
lib_extra_dirs =
|
||||
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
|
||||
pio/name-firmware.py
|
||||
pio/gzip-firmware.py
|
||||
pio/override_copy.py
|
||||
|
||||
[esp_defaults]
|
||||
; *** remove undesired all warnings
|
||||
build_unflags = -Wall
|
||||
-Wdeprecated-declarations
|
||||
build_flags = -Wno-deprecated-declarations
|
||||
-D_IR_ENABLE_DEFAULT_=false
|
||||
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
|
||||
-DDECODE_RC5=true -DSEND_RC5=true -DDECODE_RC6=true -DSEND_RC6=true
|
||||
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
|
||||
|
||||
; *********************************************************************
|
||||
; *** Use custom settings from file user_config_override.h
|
||||
-DUSE_CONFIG_OVERRIDE
|
||||
; *********************************************************************
|
||||
|
||||
[esp82xx_defaults]
|
||||
build_flags = ${esp_defaults.build_flags}
|
||||
-Wl,-Map,firmware.map
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D NDEBUG
|
||||
-mtarget-align
|
||||
-DFP_IN_IROM
|
||||
-DBEARSSL_SSL_BASIC
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||
; lwIP 2 - Higher Bandwidth no Features
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; VTABLES in Flash
|
||||
-DVTABLES_IN_FLASH
|
||||
; remove the 4-bytes alignment for PSTR()
|
||||
-DPSTR_ALIGN=1
|
||||
; restrict to minimal mime-types
|
||||
-DMIMETYPE_MINIMAL
|
||||
|
||||
[irremoteesp_full]
|
||||
build_flags = -DUSE_IR_REMOTE_FULL
|
||||
-U_IR_ENABLE_DEFAULT_
|
||||
-DDECODE_PRONTO=false -DSEND_PRONTO=false
|
||||
|
||||
[core]
|
||||
; *** 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}
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter, extra scripting
|
||||
; Upload options: custom port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/en/stable/projectconf.html
|
||||
|
||||
|
||||
; *** Tasmota build variant selection
|
||||
[build_envs]
|
||||
default_envs =
|
||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||
; tasmota
|
||||
; tasmota-ircustom
|
||||
; tasmota-minimal
|
||||
; tasmota-lite
|
||||
; tasmota-knx
|
||||
; tasmota-sensors
|
||||
; tasmota-display
|
||||
; tasmota-zbbridge
|
||||
; tasmota-ir
|
||||
; tasmota-BG
|
||||
; tasmota-BR
|
||||
; tasmota-CN
|
||||
; tasmota-CZ
|
||||
; tasmota-DE
|
||||
; tasmota-ES
|
||||
; tasmota-FR
|
||||
; tasmota-GR
|
||||
; tasmota-HE
|
||||
; tasmota-HU
|
||||
; tasmota-IT
|
||||
; tasmota-KO
|
||||
; tasmota-NL
|
||||
; tasmota-PL
|
||||
; tasmota-PT
|
||||
; tasmota-RO
|
||||
; tasmota-RU
|
||||
; tasmota-SE
|
||||
; tasmota-SK
|
||||
; tasmota-TR
|
||||
; tasmota-TW
|
||||
; tasmota-UK
|
||||
; tasmota-VN
|
||||
;
|
||||
; *** Selection for Tasmota ESP32 is done in platformio_tasmota32.ini
|
||||
;
|
||||
; *** alternatively can be done in: platformio_override.ini
|
||||
; *** See example: platformio_override_sample.ini
|
||||
; *********************************************************************
|
||||
|
||||
[platformio]
|
||||
description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware
|
||||
src_dir = tasmota
|
||||
lib_dir = lib/default
|
||||
build_cache_dir = .cache
|
||||
extra_configs = platformio_tasmota32.ini
|
||||
platformio_tasmota_env.ini
|
||||
platformio_tasmota_env32.ini
|
||||
platformio_override.ini
|
||||
default_envs = ${build_envs.default_envs}
|
||||
|
||||
[common]
|
||||
framework = arduino
|
||||
board = esp01_1m
|
||||
board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.1m.ld
|
||||
|
||||
platform = ${core.platform}
|
||||
platform_packages = ${core.platform_packages}
|
||||
build_unflags = ${core.build_unflags}
|
||||
build_flags = ${core.build_flags}
|
||||
|
||||
board_build.f_cpu = 80000000L
|
||||
board_build.f_flash = 40000000L
|
||||
monitor_speed = 115200
|
||||
upload_speed = 115200
|
||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||
upload_resetmethod = nodemcu
|
||||
upload_port = COM5
|
||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
lib_ldf_mode = chain+
|
||||
shared_libdeps_dir = lib
|
||||
lib_extra_dirs =
|
||||
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
|
||||
pio/name-firmware.py
|
||||
pio/gzip-firmware.py
|
||||
pio/override_copy.py
|
||||
|
||||
[esp_defaults]
|
||||
; *** remove undesired all warnings
|
||||
build_unflags = -Wall
|
||||
-Wdeprecated-declarations
|
||||
build_flags = -Wno-deprecated-declarations
|
||||
-D_IR_ENABLE_DEFAULT_=false
|
||||
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
|
||||
-DDECODE_RC5=true -DSEND_RC5=true -DDECODE_RC6=true -DSEND_RC6=true
|
||||
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
|
||||
; *********************************************************************
|
||||
; *** Use custom settings from file user_config_override.h
|
||||
-DUSE_CONFIG_OVERRIDE
|
||||
; *********************************************************************
|
||||
|
||||
|
||||
[esp82xx_defaults]
|
||||
build_flags = ${esp_defaults.build_flags}
|
||||
-Wl,-Map,firmware.map
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D NDEBUG
|
||||
-mtarget-align
|
||||
-DFP_IN_IROM
|
||||
-DBEARSSL_SSL_BASIC
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; VTABLES in Flash
|
||||
-DVTABLES_IN_FLASH
|
||||
; remove the 4-bytes alignment for PSTR()
|
||||
-DPSTR_ALIGN=1
|
||||
; restrict to minimal mime-types
|
||||
-DMIMETYPE_MINIMAL
|
||||
|
||||
[irremoteesp_full]
|
||||
build_flags = -DUSE_IR_REMOTE_FULL
|
||||
-U_IR_ENABLE_DEFAULT_
|
||||
-DDECODE_PRONTO=false -DSEND_PRONTO=false
|
||||
|
||||
|
||||
[core]
|
||||
; *** 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}
|
||||
|
@ -1,200 +1,234 @@
|
||||
; *** Example PlatformIO Project Configuration Override File ***
|
||||
; *** Changes done here override settings in platformio.ini ***
|
||||
;
|
||||
; *****************************************************************
|
||||
; *** to activate rename this file to platformio_override.ini ***
|
||||
; *****************************************************************
|
||||
;
|
||||
; Please visit documentation for the options and examples
|
||||
; http://docs.platformio.org/en/stable/projectconf.html
|
||||
|
||||
[platformio]
|
||||
; For best Gitpod performance remove the ";" in the next line. Needed Platformio files are cached and installed at first run
|
||||
;core_dir = .platformio
|
||||
extra_configs = platformio_tasmota_cenv.ini
|
||||
|
||||
; *** Build/upload environment
|
||||
default_envs =
|
||||
; *** Uncomment the line(s) below to select version(s)
|
||||
tasmota
|
||||
; tasmota-debug
|
||||
; tasmota-ircustom
|
||||
; tasmota-minimal
|
||||
; tasmota-lite
|
||||
; tasmota-knx
|
||||
; tasmota-sensors
|
||||
; tasmota-display
|
||||
; tasmota-zbbridge
|
||||
; tasmota-ir
|
||||
; tasmota32
|
||||
; tasmota32-webcam
|
||||
; tasmota32-minimal
|
||||
; tasmota32-lite
|
||||
; tasmota32-knx
|
||||
; tasmota32-sensors
|
||||
; tasmota32-display
|
||||
; tasmota32-ir
|
||||
; tasmota32-ircustom
|
||||
|
||||
|
||||
[common]
|
||||
platform_packages = ${core.platform_packages}
|
||||
build_unflags = ${core.build_unflags}
|
||||
build_flags = ${core.build_flags}
|
||||
; *** Optional Debug messages
|
||||
; -DDEBUG_TASMOTA_CORE
|
||||
; -DDEBUG_TASMOTA_DRIVER
|
||||
; -DDEBUG_TASMOTA_SENSOR
|
||||
|
||||
; set CPU frequency to 80MHz (default) or 160MHz
|
||||
;board_build.f_cpu = 160000000L
|
||||
|
||||
; set Flash chip frequency to 40MHz (default), 20MHz, 26Mhz, 80Mhz
|
||||
;board_build.f_flash = 20000000L
|
||||
;board_build.f_flash = 26000000L
|
||||
;board_build.f_flash = 80000000L
|
||||
|
||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||
upload_port = COM5
|
||||
|
||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/obj-dump.py
|
||||
|
||||
; *** Upload file to OTA server using SCP
|
||||
;upload_port = user@host:/path
|
||||
;extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/strip-floats.py
|
||||
; pio/sftp-uploader.py
|
||||
|
||||
; *** Upload file to OTA server in folder api/arduino using HTTP
|
||||
;upload_port = domus1:80/api/upload-arduino.php
|
||||
;extra_scripts = ${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/lib_basic
|
||||
; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled
|
||||
lib/lib_i2c
|
||||
; *** Displays. Disable if you dont have any Display activated
|
||||
lib/lib_display
|
||||
; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated
|
||||
lib/lib_ssl
|
||||
; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable
|
||||
lib/lib_audio
|
||||
; *** RF 433 stuff (not RF Bridge). Recommended to disable
|
||||
lib/lib_rf
|
||||
; *** Mostly not used functions. Recommended to disable
|
||||
lib/lib_div
|
||||
|
||||
[core]
|
||||
; Activate only (one set) if you want to override the standard core defined in platformio.ini !!!
|
||||
|
||||
;platform_packages = ${tasmota_stage.platform_packages}
|
||||
;build_unflags = ${tasmota_stage.build_unflags}
|
||||
;build_flags = ${tasmota_stage.build_flags}
|
||||
|
||||
;platform_packages = ${core_stage.platform_packages}
|
||||
;build_unflags = ${core_stage.build_unflags}
|
||||
;build_flags = ${core_stage.build_flags}
|
||||
|
||||
|
||||
[tasmota_stage]
|
||||
; *** Esp8266 core for Arduino version Tasmota stage (PR7231 and Backport PR7514)
|
||||
platform_packages = framework-arduinoespressif8266@https://github.com/Jason2866/Arduino.git#2.7.4.4
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
|
||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||
; NONOSDK221
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||
; NONOSDK22x_190313
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
; NONOSDK3V0 (known issues)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||
; lwIP 1.4
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Low Memory
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
; lwIP 2 - Higher Bandwidth
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||
; VTABLES in Heap
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
; Exception code in firmware /needs much space!
|
||||
; -fexceptions
|
||||
; -lstdc++-exc
|
||||
|
||||
[core_stage]
|
||||
; *** Esp8266 core version. Tasmota stage or Arduino stage version. Built with GCC 10.1 toolchain
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/Jason2866/platform-espressif8266/releases/download/2.9.1/framework-arduinoespressif8266-3.20901.0.tar.gz
|
||||
;framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||
toolchain-xtensa @ ~2.100100.0
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
-Wswitch-unreachable
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-Wno-switch-unreachable
|
||||
|
||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||
; NONOSDK221
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||
; NONOSDK22x_190313
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
; NONOSDK3V0 (known issues)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||
; lwIP 2 - Low Memory
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
; lwIP 2 - Higher Bandwidth
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||
; VTABLES in Heap
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
; Exception code in firmware /needs much space!
|
||||
; -fexceptions
|
||||
; -lstdc++-exc
|
||||
|
||||
[core32]
|
||||
; Activate Stage Core32 by removing ";" in next lines, if you want to override the standard core32
|
||||
;platform_packages = ${core32_stage.platform_packages}
|
||||
;build_flags = ${core32_stage.build_flags}
|
||||
|
||||
[core32_stage]
|
||||
platform_packages = tool-esptoolpy@1.20800.0
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#f7fb00632e04d74a7890a77fa7dbbb8ae572e866
|
||||
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
-D ESP32_STAGE=true
|
||||
|
||||
; *** Debug version used for PlatformIO Home Project Inspection
|
||||
[env:tasmota-debug]
|
||||
build_type = debug
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-Wstack-usage=300
|
||||
; *** Example PlatformIO Project Configuration Override File ***
|
||||
; *** Changes done here override settings in platformio.ini ***
|
||||
;
|
||||
; *****************************************************************
|
||||
; *** to activate rename this file to platformio_override.ini ***
|
||||
; *****************************************************************
|
||||
;
|
||||
; Please visit documentation for the options and examples
|
||||
; http://docs.platformio.org/en/stable/projectconf.html
|
||||
|
||||
[platformio]
|
||||
; For best Gitpod performance remove the ";" in the next line. Needed Platformio files are cached and installed at first run
|
||||
;core_dir = .platformio
|
||||
extra_configs = platformio_tasmota_cenv.ini
|
||||
|
||||
; *** Build/upload environment
|
||||
default_envs =
|
||||
; *** Uncomment the line(s) below to select version(s)
|
||||
tasmota
|
||||
; tasmota-debug
|
||||
; tasmota-ircustom
|
||||
; tasmota-minimal
|
||||
; tasmota-lite
|
||||
; tasmota-knx
|
||||
; tasmota-sensors
|
||||
; tasmota-display
|
||||
; tasmota-zbbridge
|
||||
; tasmota-ir
|
||||
; tasmota32
|
||||
; tasmota32-webcam
|
||||
; tasmota32-minimal
|
||||
; tasmota32-lite
|
||||
; tasmota32-knx
|
||||
; tasmota32-sensors
|
||||
; tasmota32-display
|
||||
; tasmota32-ir
|
||||
; tasmota32-ircustom
|
||||
|
||||
|
||||
[common]
|
||||
platform_packages = ${core.platform_packages}
|
||||
build_unflags = ${core.build_unflags}
|
||||
build_flags = ${core.build_flags}
|
||||
; *** Optional Debug messages
|
||||
; -DDEBUG_TASMOTA_CORE
|
||||
; -DDEBUG_TASMOTA_DRIVER
|
||||
; -DDEBUG_TASMOTA_SENSOR
|
||||
|
||||
; set CPU frequency to 80MHz (default) or 160MHz
|
||||
;board_build.f_cpu = 160000000L
|
||||
|
||||
; set Flash chip frequency to 40MHz (default), 20MHz, 26Mhz, 80Mhz
|
||||
;board_build.f_flash = 20000000L
|
||||
;board_build.f_flash = 26000000L
|
||||
;board_build.f_flash = 80000000L
|
||||
|
||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||
upload_port = COM5
|
||||
|
||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/obj-dump.py
|
||||
|
||||
; *** Upload file to OTA server using SCP
|
||||
;upload_port = user@host:/path
|
||||
;extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/strip-floats.py
|
||||
; pio/sftp-uploader.py
|
||||
|
||||
; *** Upload file to OTA server in folder api/arduino using HTTP
|
||||
;upload_port = domus1:80/api/upload-arduino.php
|
||||
;extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/strip-floats.py
|
||||
; pio/http-uploader.py
|
||||
|
||||
lib_extra_dirs = ${library.lib_extra_dirs}
|
||||
|
||||
[core]
|
||||
; Activate only (one set) if you want to override the standard core defined in platformio.ini !!!
|
||||
|
||||
;platform_packages = ${tasmota_stage.platform_packages}
|
||||
;build_unflags = ${tasmota_stage.build_unflags}
|
||||
;build_flags = ${tasmota_stage.build_flags}
|
||||
|
||||
;platform_packages = ${core_stage.platform_packages}
|
||||
;build_unflags = ${core_stage.build_unflags}
|
||||
;build_flags = ${core_stage.build_flags}
|
||||
|
||||
|
||||
[tasmota_stage]
|
||||
; *** Esp8266 core for Arduino version Tasmota stage (PR7231 and Backport PR7514)
|
||||
platform_packages = framework-arduinoespressif8266@https://github.com/Jason2866/Arduino.git#2.7.4.4
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
|
||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||
; NONOSDK221
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||
; NONOSDK22x_190313
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
; NONOSDK3V0 (known issues)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||
; lwIP 1.4
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Low Memory
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
; lwIP 2 - Higher Bandwidth
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||
; VTABLES in Heap
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
; Exception code in firmware /needs much space!
|
||||
; -fexceptions
|
||||
; -lstdc++-exc
|
||||
|
||||
[core_stage]
|
||||
; *** Esp8266 core version. Tasmota stage or Arduino stage version. Built with GCC 10.1 toolchain
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/Jason2866/platform-espressif8266/releases/download/2.9.1/framework-arduinoespressif8266-3.20901.0.tar.gz
|
||||
;framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||
toolchain-xtensa @ ~2.100100.0
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
-Wswitch-unreachable
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-Wno-switch-unreachable
|
||||
|
||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||
; NONOSDK221
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||
; NONOSDK22x_190313
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
; NONOSDK3V0 (known issues)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||
; lwIP 2 - Low Memory
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
; lwIP 2 - Higher Bandwidth
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||
; VTABLES in Heap
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
; Exception code in firmware /needs much space!
|
||||
; -fexceptions
|
||||
; -lstdc++-exc
|
||||
|
||||
[common32]
|
||||
platform = ${core32.platform}
|
||||
platform_packages = ${core32.platform_packages}
|
||||
build_unflags = ${core32.build_unflags}
|
||||
build_flags = ${core32.build_flags}
|
||||
board = esp32dev
|
||||
board_build.ldscript = esp32_out.ld
|
||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||
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}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
upload_speed = 921600
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
lib_extra_dirs = ${library.lib_extra_dirs}
|
||||
; *** ESP32 lib. ALWAYS needed for ESP32 !!!
|
||||
lib/libesp32
|
||||
[core32]
|
||||
; Activate Stage Core32 by removing ";" in next 4 lines, if you want to override the standard core32
|
||||
;platform = ${core32_stage.platform}
|
||||
;platform_packages = ${core32_stage.platform_packages}
|
||||
;build_unflags = ${core32_stage.build_unflags}
|
||||
;build_flags = ${core32_stage.build_flags}
|
||||
|
||||
|
||||
[core32_stage]
|
||||
platform = espressif32@2.0.0
|
||||
platform_packages = tool-esptoolpy@1.20800.0
|
||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#f7fb00632e04d74a7890a77fa7dbbb8ae572e866
|
||||
build_unflags = ${esp32_defaults.build_unflags}
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
-D ESP32_STAGE=true
|
||||
|
||||
[library]
|
||||
lib_ldf_mode = chain+
|
||||
shared_libdeps_dir = lib
|
||||
; *** Library disable / enable for variant Tasmota(32). 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/lib_basic
|
||||
; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled
|
||||
lib/lib_i2c
|
||||
; *** Displays. Disable if you dont have any Display activated
|
||||
lib/lib_display
|
||||
; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated
|
||||
lib/lib_ssl
|
||||
; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable
|
||||
lib/lib_audio
|
||||
; *** RF 433 stuff (not RF Bridge). Recommended to disable
|
||||
lib/lib_rf
|
||||
; *** Mostly not used functions. Recommended to disable
|
||||
lib/lib_div
|
||||
|
||||
|
||||
|
||||
; *** Debug version used for PlatformIO Home Project Inspection
|
||||
[env:tasmota-debug]
|
||||
build_type = debug
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
; -Wstack-usage=300
|
||||
|
||||
[env:tasmota32-debug]
|
||||
extends = env:tasmota32
|
||||
build_type = debug
|
||||
build_unflags = ${esp32_defaults.build_unflags}
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
; -Wstack-usage=300
|
||||
|
@ -1,92 +1,92 @@
|
||||
; *** BETA ESP32 Tasmota version ***
|
||||
; *** expect the unexpected. Some features not working!!! ***
|
||||
|
||||
[platformio]
|
||||
|
||||
; *** Tasmota build variant selection
|
||||
default_envs = ${build_envs.default_envs}
|
||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||
; tasmota32
|
||||
; tasmota32-webcam
|
||||
; tasmota32-minimal
|
||||
; tasmota32-lite
|
||||
; tasmota32-knx
|
||||
; tasmota32-sensors
|
||||
; tasmota32-display
|
||||
; tasmota32-ir
|
||||
; tasmota32-ircustom
|
||||
; tasmota32-BG
|
||||
; tasmota32-BR
|
||||
; tasmota32-CN
|
||||
; tasmota32-CZ
|
||||
; tasmota32-DE
|
||||
; tasmota32-ES
|
||||
; tasmota32-FR
|
||||
; tasmota32-GR
|
||||
; tasmota32-HE
|
||||
; tasmota32-HU
|
||||
; tasmota32-IT
|
||||
; tasmota32-KO
|
||||
; tasmota32-NL
|
||||
; tasmota32-PL
|
||||
; tasmota32-PT
|
||||
; tasmota32-RO
|
||||
; tasmota32-RU
|
||||
; tasmota32-SE
|
||||
; tasmota32-SK
|
||||
; tasmota32-TR
|
||||
; tasmota32-TW
|
||||
; tasmota32-UK
|
||||
; tasmota32-VN
|
||||
|
||||
[common32]
|
||||
board = esp32dev
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.ldscript = esp32_out.ld
|
||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||
|
||||
platform = ${core32.platform}
|
||||
platform_packages = ${core32.platform_packages}
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
-Wpointer-arith
|
||||
build_flags = ${core32.build_flags}
|
||||
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
board_build.f_flash = ${common.board_build.f_flash}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
upload_speed = 921600
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
|
||||
lib_ldf_mode = chain+
|
||||
shared_libdeps_dir = lib
|
||||
lib_extra_dirs =
|
||||
lib/libesp32
|
||||
lib/lib_basic
|
||||
lib/lib_i2c
|
||||
lib/lib_display
|
||||
lib/lib_ssl
|
||||
lib/lib_audio
|
||||
lib/lib_rf
|
||||
lib/lib_div
|
||||
|
||||
[esp32_defaults]
|
||||
build_flags = ${esp_defaults.build_flags}
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D BUFFER_LENGTH=128
|
||||
-D MQTT_MAX_PACKET_SIZE=1200
|
||||
-D uint32=uint32_t
|
||||
-D uint16=uint16_t
|
||||
-D uint8=uint8_t
|
||||
-D sint8_t=int8_t
|
||||
-D sint32_t=int32_t
|
||||
-D sint16_t=int16_t
|
||||
-D memcpy_P=memcpy
|
||||
-D memcmp_P=memcmp
|
||||
|
||||
[core32]
|
||||
platform = espressif32@2.0.0
|
||||
platform_packages = tool-esptoolpy@1.20800.0
|
||||
platformio/framework-arduinoespressif32 @ 3.10004.201016
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
; *** BETA ESP32 Tasmota version ***
|
||||
; *** expect the unexpected. Some features not working!!! ***
|
||||
|
||||
[platformio]
|
||||
|
||||
; *** Tasmota build variant selection
|
||||
default_envs = ${build_envs.default_envs}
|
||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||
; tasmota32
|
||||
; tasmota32-webcam
|
||||
; tasmota32-minimal
|
||||
; tasmota32-lite
|
||||
; tasmota32-knx
|
||||
; tasmota32-sensors
|
||||
; tasmota32-display
|
||||
; tasmota32-ir
|
||||
; tasmota32-ircustom
|
||||
; tasmota32-BG
|
||||
; tasmota32-BR
|
||||
; tasmota32-CN
|
||||
; tasmota32-CZ
|
||||
; tasmota32-DE
|
||||
; tasmota32-ES
|
||||
; tasmota32-FR
|
||||
; tasmota32-GR
|
||||
; tasmota32-HE
|
||||
; tasmota32-HU
|
||||
; tasmota32-IT
|
||||
; tasmota32-KO
|
||||
; tasmota32-NL
|
||||
; tasmota32-PL
|
||||
; tasmota32-PT
|
||||
; tasmota32-RO
|
||||
; tasmota32-RU
|
||||
; tasmota32-SE
|
||||
; tasmota32-SK
|
||||
; tasmota32-TR
|
||||
; tasmota32-TW
|
||||
; tasmota32-UK
|
||||
; tasmota32-VN
|
||||
|
||||
[common32]
|
||||
platform = ${core32.platform}
|
||||
platform_packages = ${core32.platform_packages}
|
||||
build_unflags = ${core32.build_unflags}
|
||||
build_flags = ${core32.build_flags}
|
||||
board = esp32dev
|
||||
board_build.ldscript = esp32_out.ld
|
||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||
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}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
upload_speed = 921600
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
lib_ldf_mode = chain+
|
||||
shared_libdeps_dir = lib
|
||||
lib_extra_dirs =
|
||||
lib/libesp32
|
||||
lib/lib_basic
|
||||
lib/lib_i2c
|
||||
lib/lib_display
|
||||
lib/lib_ssl
|
||||
lib/lib_audio
|
||||
lib/lib_rf
|
||||
lib/lib_div
|
||||
|
||||
[esp32_defaults]
|
||||
build_unflags = ${esp_defaults.build_unflags}
|
||||
-Wpointer-arith
|
||||
build_flags = ${esp_defaults.build_flags}
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D BUFFER_LENGTH=128
|
||||
-D MQTT_MAX_PACKET_SIZE=1200
|
||||
-D uint32=uint32_t
|
||||
-D uint16=uint16_t
|
||||
-D uint8=uint8_t
|
||||
-D sint8_t=int8_t
|
||||
-D sint32_t=int32_t
|
||||
-D sint16_t=int16_t
|
||||
-D memcpy_P=memcpy
|
||||
-D memcmp_P=memcmp
|
||||
|
||||
|
||||
[core32]
|
||||
platform = espressif32@2.0.0
|
||||
platform_packages = tool-esptoolpy@1.20800.0
|
||||
platformio/framework-arduinoespressif32 @ 3.10004.201016
|
||||
build_unflags = ${esp32_defaults.build_unflags}
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define D_JSON_DARKNESS "Darkness"
|
||||
#define D_JSON_DATA "Data"
|
||||
#define D_JSON_DEWPOINT "DewPoint"
|
||||
#define D_JSON_DO "DisolvedOxygen"
|
||||
#define D_JSON_DISTANCE "Distance"
|
||||
#define D_JSON_DNSSERVER "DNSServer"
|
||||
#define D_JSON_DONE "Done"
|
||||
@ -785,6 +786,7 @@ const char HTTP_SNS_EC[] PROGMEM = "{s}%s " D_EC "{
|
||||
const char HTTP_SNS_O2[] PROGMEM = "{s}%s " D_O2 "{m}%s " D_UNIT_PERCENT "{e}";
|
||||
const char HTTP_SNS_LITERS[] PROGMEM = "{s}%s " D_VOLUME "{m}%s " D_UNIT_LITERS "{e}";
|
||||
const char HTTP_SNS_LPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_LITERS_PER_MIN "{e}";
|
||||
const char HTTP_SNS_DO[] PROGMEM = "{s}%s " D_DO "{m}%s " D_UNIT_PARTS_PER_MILLION "{e}";
|
||||
|
||||
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Забранен"
|
||||
#define D_DISTANCE "Разстояние"
|
||||
#define D_DNS_SERVER "DNS Сървър"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Изпълнено"
|
||||
#define D_DST_TIME "Лятно време"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Zablokováno"
|
||||
#define D_DISTANCE "Distance"
|
||||
#define D_DNS_SERVER "Server DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Provedeno"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "deaktiviert"
|
||||
#define D_DISTANCE "Abstand"
|
||||
#define D_DNS_SERVER "DNS-Server"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "erledigt"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Ανενεργό"
|
||||
#define D_DISTANCE "Απόσταση"
|
||||
#define D_DNS_SERVER "Διακομιστής DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Ολοκληρώθηκε"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Disabled"
|
||||
#define D_DISTANCE "Distance"
|
||||
#define D_DNS_SERVER "DNS Server"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Done"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Deshabilitado"
|
||||
#define D_DISTANCE "Distancia"
|
||||
#define D_DNS_SERVER "Servidor DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Listo"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -80,6 +80,7 @@
|
||||
#define D_DISABLED "Désactivé"
|
||||
#define D_DISTANCE "Distance"
|
||||
#define D_DNS_SERVER "Serveur DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Terminé"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "מבוטל"
|
||||
#define D_DISTANCE "מרחק"
|
||||
#define D_DNS_SERVER "DNS שרת"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "סיים"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Letiltva"
|
||||
#define D_DISTANCE "Távolság"
|
||||
#define D_DNS_SERVER "DNS szerver"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Kész"
|
||||
#define D_DST_TIME "nyári idő"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Disabilitato/a"
|
||||
#define D_DISTANCE "Distanza"
|
||||
#define D_DNS_SERVER "Server DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Completato"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "사용안함"
|
||||
#define D_DISTANCE "거리"
|
||||
#define D_DNS_SERVER "DNS 서버"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "완료"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -28,7 +28,7 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v8.0.0
|
||||
* Updated until v9.1.0
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Uitgeschakeld"
|
||||
#define D_DISTANCE "Afstand"
|
||||
#define D_DNS_SERVER "DNS Server"
|
||||
#define D_DO "Opgelost zuurstof"
|
||||
#define D_DONE "Klaar"
|
||||
#define D_DST_TIME "ZT"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Wyłączony"
|
||||
#define D_DISTANCE "Odległość"
|
||||
#define D_DNS_SERVER "Serwer DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Wykonane"
|
||||
#define D_DST_TIME "Czas DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Desabilitado"
|
||||
#define D_DISTANCE "Distância"
|
||||
#define D_DNS_SERVER "Servidor DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Concluído"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Disabilitado"
|
||||
#define D_DISTANCE "Distância"
|
||||
#define D_DNS_SERVER "Servidor DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Concluído"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Dezactivat"
|
||||
#define D_DISTANCE "Distanță"
|
||||
#define D_DNS_SERVER "Server DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Terminat"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Блокирован"
|
||||
#define D_DISTANCE "Distance"
|
||||
#define D_DNS_SERVER "DNS Сервер"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Выполнено"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -85,6 +85,7 @@
|
||||
#define D_DISABLED "Zablokované"
|
||||
#define D_DISTANCE "Vzdialenosť"
|
||||
#define D_DNS_SERVER "Server DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Hotovo"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Inaktiverad"
|
||||
#define D_DISTANCE "Distans"
|
||||
#define D_DNS_SERVER "DNS-server"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Gjort"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Etkin Değil"
|
||||
#define D_DISTANCE "Mesage"
|
||||
#define D_DNS_SERVER "DNS Sunucu"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Tamam"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Вимкнено"
|
||||
#define D_DISTANCE "Відстань"
|
||||
#define D_DNS_SERVER "Сервер DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Виконано"
|
||||
#define D_DST_TIME "Літній час"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "Vô hiệu hóa"
|
||||
#define D_DISTANCE "Khoảng cách"
|
||||
#define D_DNS_SERVER "Máy chủ DNS"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "Hoàn thành"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "禁用"
|
||||
#define D_DISTANCE "距离"
|
||||
#define D_DNS_SERVER "DNS服务器"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "完成"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -84,6 +84,7 @@
|
||||
#define D_DISABLED "已停用"
|
||||
#define D_DISTANCE "距離"
|
||||
#define D_DNS_SERVER "DNS伺服器"
|
||||
#define D_DO "Disolved Oxygen"
|
||||
#define D_DONE "完成"
|
||||
#define D_DST_TIME "DST"
|
||||
#define D_EC "EC"
|
||||
|
@ -571,6 +571,7 @@
|
||||
// #define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 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
|
||||
|
@ -649,8 +649,9 @@ void ResponseAppendFeatures(void)
|
||||
#if defined(USE_I2C) && defined(USE_EZOFLO)
|
||||
feature7 |= 0x00000080;
|
||||
#endif
|
||||
|
||||
// feature7 |= 0x00000100;
|
||||
#if defined(USE_I2C) && defined(USE_EZODO)
|
||||
feature7 |= 0x00000100;
|
||||
#endif
|
||||
// feature7 |= 0x00000200;
|
||||
// feature7 |= 0x00000400;
|
||||
// feature7 |= 0x00000800;
|
||||
|
@ -490,7 +490,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
|
||||
result = XdrvRulesProcess();
|
||||
}
|
||||
#ifdef USE_PWM_DIMMER
|
||||
if (PWM_DIMMER == TasmotaGlobal.module_type && !result) {
|
||||
if (PWM_DIMMER != TasmotaGlobal.module_type || !result) {
|
||||
#endif // USE_PWM_DIMMER
|
||||
int32_t payload_save = XdrvMailbox.payload;
|
||||
XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device;
|
||||
|
@ -136,6 +136,7 @@
|
||||
//#define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
//#define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
//#define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||
// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 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)
|
||||
|
@ -67,6 +67,8 @@
|
||||
|
||||
#define XDRV_10 10
|
||||
|
||||
//#define DEBUG_RULES
|
||||
|
||||
#include <unishox.h>
|
||||
|
||||
#define D_CMND_RULE "Rule"
|
||||
@ -424,7 +426,9 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
// rule_name = "INA219#CURRENT"
|
||||
// rule_param = "0.100" or "%VAR1%"
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: expr %s, name %s, param %s"), rule_expr.c_str(), rule_name.c_str(), rule_param.c_str());
|
||||
#ifdef DEBUG_RULES
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RM1: expr %s, name %s, param %s"), rule_expr.c_str(), rule_name.c_str(), rule_param.c_str());
|
||||
#endif
|
||||
|
||||
char rule_svalue[80] = { 0 };
|
||||
float rule_value = 0;
|
||||
@ -499,7 +503,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
|
||||
String buf = event; // copy the string into a new buffer that will be modified
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: RulesRuleMatch |%s|"), buf.c_str());
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RM2: RulesRuleMatch |%s|"), buf.c_str());
|
||||
|
||||
JsonParser parser((char*)buf.c_str());
|
||||
JsonParserObject obj = parser.getRootObject();
|
||||
@ -513,7 +517,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT"
|
||||
subtype = rule_name.substring(0, pos);
|
||||
obj = obj[subtype.c_str()].getObject();
|
||||
if (!obj) { return false; } // not found
|
||||
if (!obj) { return false; } // not found
|
||||
|
||||
rule_name = rule_name.substring(pos +1);
|
||||
if (i++ > 10) { return false; } // Abandon possible loop
|
||||
@ -522,7 +526,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
}
|
||||
|
||||
JsonParserToken val = obj[rule_name.c_str()];
|
||||
if (!val) { return false; } // last level not found
|
||||
if (!val) { return false; } // last level not found
|
||||
const char* str_value;
|
||||
if (rule_name_idx) {
|
||||
if (val.isArray()) {
|
||||
@ -531,11 +535,14 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
str_value = val.getStr();
|
||||
}
|
||||
} else {
|
||||
str_value = val.getStr(); // "CURRENT"
|
||||
str_value = val.getStr(); // "CURRENT"
|
||||
}
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"),
|
||||
// rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none");
|
||||
#ifdef DEBUG_RULES
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RM3: Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json |%s|"),
|
||||
rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set],
|
||||
Rules.trigger_count[rule_set]), event.c_str(), (str_value[0] != '\0') ? str_value : "none");
|
||||
#endif
|
||||
|
||||
Rules.event_value = str_value; // Prepare %value%
|
||||
|
||||
@ -577,7 +584,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
|
||||
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]);
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RM4: 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
|
||||
@ -591,7 +598,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
||||
}
|
||||
}
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 2 %d, Triggers %08X, TriggerCount %d"), match, Rules.triggers[rule_set], Rules.trigger_count[rule_set]);
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RM5: Match 2 %d, Triggers %08X, TriggerCount %d"), match, Rules.triggers[rule_set], Rules.trigger_count[rule_set]);
|
||||
|
||||
return match;
|
||||
}
|
||||
@ -663,7 +670,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
||||
|
||||
delay(0); // Prohibit possible loop software watchdog
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]);
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RP1: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]);
|
||||
|
||||
String rules = GetRule(rule_set);
|
||||
|
||||
@ -696,7 +703,9 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
||||
Rules.event_value = "";
|
||||
String event = 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());
|
||||
#ifdef DEBUG_RULES
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL-RP2: Event |%s|, Rule |%s|, Command(s) |%s|"), event.c_str(), event_trigger.c_str(), commands.c_str());
|
||||
#endif
|
||||
|
||||
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
|
||||
|
@ -543,6 +543,9 @@ public:
|
||||
inline bool getReachable(void) const { return reachable; }
|
||||
inline bool getPower(uint8_t ep =0) const;
|
||||
|
||||
inline void setLQI(uint8_t _lqi) { lqi = _lqi; }
|
||||
inline void setBatteryPercent(uint8_t bp) { batterypercent = bp; }
|
||||
|
||||
// Add an endpoint to a device
|
||||
bool addEndpoint(uint8_t endpoint);
|
||||
void clearEndpoints(void);
|
||||
@ -552,6 +555,8 @@ public:
|
||||
void setModelId(const char * str);
|
||||
void setFriendlyName(const char * str);
|
||||
|
||||
void setLastSeenNow(void);
|
||||
|
||||
// dump device attributes to ZbData
|
||||
void toAttributes(Z_attribute_list & attr_list) const;
|
||||
|
||||
@ -568,30 +573,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// returns: dirty flag, did we change the value of the object
|
||||
bool setLightChannels(int8_t channels) {
|
||||
bool dirty = false;
|
||||
if (channels >= 0) {
|
||||
// retrieve of create light object
|
||||
Z_Data_Light & light = data.get<Z_Data_Light>(0);
|
||||
if (channels != light.getConfig()) {
|
||||
light.setConfig(channels);
|
||||
dirty = true;
|
||||
}
|
||||
Z_Data_OnOff & onoff = data.get<Z_Data_OnOff>(0);
|
||||
} else {
|
||||
// remove light / onoff object if any
|
||||
for (auto & data_elt : data) {
|
||||
if ((data_elt.getType() == Z_Data_Type::Z_Light) ||
|
||||
(data_elt.getType() == Z_Data_Type::Z_OnOff)) {
|
||||
// remove light object
|
||||
data.remove(&data_elt);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
void setLightChannels(int8_t channels);
|
||||
|
||||
protected:
|
||||
|
||||
static void setStringAttribute(char*& attr, const char * str);
|
||||
@ -655,9 +638,9 @@ public:
|
||||
// - 0x0000 = not found
|
||||
// - BAD_SHORTADDR = bad parameter
|
||||
// - 0x<shortaddr> = the device's short address
|
||||
uint16_t isKnownLongAddr(uint64_t longaddr) const;
|
||||
uint16_t isKnownIndex(uint32_t index) const;
|
||||
uint16_t isKnownFriendlyName(const char * name) const;
|
||||
Z_Device & isKnownLongAddrDevice(uint64_t longaddr) const;
|
||||
Z_Device & isKnownIndexDevice(uint32_t index) const;
|
||||
Z_Device & isKnownFriendlyNameDevice(const char * name) const;
|
||||
|
||||
Z_Device & findShortAddr(uint16_t shortaddr);
|
||||
const Z_Device & findShortAddr(uint16_t shortaddr) const;
|
||||
@ -666,9 +649,7 @@ public:
|
||||
Z_Device & getShortAddr(uint16_t shortaddr); // find Device from shortAddr, creates it if does not exist
|
||||
Z_Device & getLongAddr(uint64_t longaddr); // find Device from shortAddr, creates it if does not exist
|
||||
// check if a device was found or if it's the fallback device
|
||||
inline bool foundDevice(const Z_Device & device) const {
|
||||
return (&device != &device_unk);
|
||||
}
|
||||
inline bool foundDevice(const Z_Device & device) const { return device.valid(); }
|
||||
|
||||
int32_t findFriendlyName(const char * name) const;
|
||||
uint64_t getDeviceLongAddr(uint16_t shortaddr) const;
|
||||
@ -689,26 +670,15 @@ public:
|
||||
return findShortAddr(shortaddr).manufacturerId;
|
||||
}
|
||||
|
||||
void setReachable(uint16_t shortaddr, bool reachable);
|
||||
void setLQI(uint16_t shortaddr, uint8_t lqi);
|
||||
void setLastSeenNow(uint16_t shortaddr);
|
||||
// uint8_t getLQI(uint16_t shortaddr) const;
|
||||
void setBatteryPercent(uint16_t shortaddr, uint8_t bp);
|
||||
uint8_t getBatteryPercent(uint16_t shortaddr) const;
|
||||
|
||||
// get next sequence number for (increment at each all)
|
||||
uint8_t getNextSeqNumber(uint16_t shortaddr);
|
||||
|
||||
// Dump json
|
||||
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;
|
||||
static String dumpLightState(const Z_Device & device);
|
||||
String dumpDevice(uint32_t dump_mode, const Z_Device & device) const;
|
||||
static String dumpSingleDevice(uint32_t dump_mode, const Z_Device & device);
|
||||
int32_t deviceRestore(JsonParserObject json);
|
||||
|
||||
// General Zigbee device profile support
|
||||
void setLightProfile(uint16_t shortaddr, uint8_t light_profile);
|
||||
uint8_t getLightProfile(uint16_t shortaddr) const ;
|
||||
|
||||
// Hue support
|
||||
int8_t getHueBulbtype(uint16_t shortaddr) const ;
|
||||
void hideHueBulb(uint16_t shortaddr, bool hidden);
|
||||
@ -731,14 +701,7 @@ public:
|
||||
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;
|
||||
}
|
||||
}
|
||||
Z_Device & devicesAt(size_t i) const;
|
||||
|
||||
// Remove device from list
|
||||
bool removeDevice(uint16_t shortaddr);
|
||||
@ -746,10 +709,10 @@ public:
|
||||
// Mark data as 'dirty' and requiring to save in Flash
|
||||
void dirty(void);
|
||||
void clean(void); // avoid writing to flash the last changes
|
||||
void shrinkToFit(uint16_t shortaddr);
|
||||
|
||||
// Find device by name, can be short_addr, long_addr, number_in_array or name
|
||||
uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const;
|
||||
Z_Device & parseDeviceFromName(const char * param, bool short_must_be_known = false);
|
||||
|
||||
|
||||
private:
|
||||
LList<Z_Device> _devices; // list of devices
|
||||
@ -757,10 +720,6 @@ private:
|
||||
uint32_t _saveTimer = 0;
|
||||
uint8_t _seqNumber = 0; // global seqNumber if device is unknown
|
||||
|
||||
// Following device is used represent the unknown device, with all defaults
|
||||
// Any find() function will not return Null, instead it will return this instance
|
||||
const Z_Device device_unk = Z_Device(BAD_SHORTADDR);
|
||||
|
||||
//int32_t findShortAddrIdx(uint16_t shortaddr) const;
|
||||
// Create a new entry in the devices list - must be called if it is sure it does not already exist
|
||||
Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0);
|
||||
@ -772,6 +731,10 @@ private:
|
||||
\*********************************************************************************************/
|
||||
Z_Devices zigbee_devices = Z_Devices();
|
||||
|
||||
// Following device is used represent the unknown device, with all defaults
|
||||
// Any find() function will not return Null, instead it will return this instance
|
||||
Z_Device device_unk = Z_Device(BAD_SHORTADDR);
|
||||
|
||||
// Local coordinator information
|
||||
uint64_t localIEEEAddr = 0;
|
||||
uint16_t localShortAddr = 0;
|
||||
|
@ -23,12 +23,21 @@
|
||||
* Implementation
|
||||
\*********************************************************************************************/
|
||||
|
||||
Z_Device & Z_Devices::devicesAt(size_t i) const {
|
||||
Z_Device * devp = (Z_Device*) _devices.at(i);
|
||||
if (devp) {
|
||||
return *devp;
|
||||
} else {
|
||||
return device_unk;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new Z_Device entry in _devices. Only to be called if you are sure that no
|
||||
// entry with same shortaddr or longaddr exists.
|
||||
//
|
||||
Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) {
|
||||
if ((BAD_SHORTADDR == shortaddr) && !longaddr) { return (Z_Device&) device_unk; } // it is not legal to create this entry
|
||||
if ((BAD_SHORTADDR == shortaddr) && !longaddr) { return device_unk; } // it is not legal to create this entry
|
||||
Z_Device & device = _devices.addToLast();
|
||||
device.shortaddr = shortaddr;
|
||||
device.longaddr = longaddr;
|
||||
@ -56,7 +65,7 @@ Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) {
|
||||
for (auto & elem : _devices) {
|
||||
if (elem.shortaddr == shortaddr) { return elem; }
|
||||
}
|
||||
return (Z_Device&) device_unk;
|
||||
return device_unk;
|
||||
}
|
||||
const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const {
|
||||
for (const auto & elem : _devices) {
|
||||
@ -73,11 +82,11 @@ const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const {
|
||||
// index in _devices of entry, -1 if not found
|
||||
//
|
||||
Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) {
|
||||
if (!longaddr) { return (Z_Device&) device_unk; }
|
||||
if (!longaddr) { return device_unk; }
|
||||
for (auto &elem : _devices) {
|
||||
if (elem.longaddr == longaddr) { return elem; }
|
||||
}
|
||||
return (Z_Device&) device_unk;
|
||||
return device_unk;
|
||||
}
|
||||
const Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) const {
|
||||
if (!longaddr) { return device_unk; }
|
||||
@ -109,32 +118,25 @@ int32_t Z_Devices::findFriendlyName(const char * name) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const {
|
||||
const Z_Device & device = findLongAddr(longaddr);
|
||||
if (foundDevice(device)) {
|
||||
return device.shortaddr; // can be zero, if not yet registered
|
||||
} else {
|
||||
return BAD_SHORTADDR;
|
||||
}
|
||||
Z_Device & Z_Devices::isKnownLongAddrDevice(uint64_t longaddr) const {
|
||||
return (Z_Device &) findLongAddr(longaddr);
|
||||
}
|
||||
|
||||
uint16_t Z_Devices::isKnownIndex(uint32_t index) const {
|
||||
Z_Device & Z_Devices::isKnownIndexDevice(uint32_t index) const {
|
||||
if (index < devicesSize()) {
|
||||
const Z_Device & device = devicesAt(index);
|
||||
return device.shortaddr;
|
||||
return devicesAt(index);
|
||||
} else {
|
||||
return BAD_SHORTADDR;
|
||||
return device_unk;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Z_Devices::isKnownFriendlyName(const char * name) const {
|
||||
if ((!name) || (0 == strlen(name))) { return BAD_SHORTADDR; } // Error
|
||||
Z_Device & Z_Devices::isKnownFriendlyNameDevice(const char * name) const {
|
||||
if ((!name) || (0 == strlen(name))) { return device_unk; } // Error
|
||||
int32_t found = findFriendlyName(name);
|
||||
if (found >= 0) {
|
||||
const Z_Device & device = devicesAt(found);
|
||||
return device.shortaddr; // can be zero, if not yet registered
|
||||
return devicesAt(found);
|
||||
} else {
|
||||
return BAD_SHORTADDR;
|
||||
return device_unk;
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +148,7 @@ uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const {
|
||||
// We have a seen a shortaddr on the network, get the corresponding device object
|
||||
//
|
||||
Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) {
|
||||
if (BAD_SHORTADDR == shortaddr) { return (Z_Device&) device_unk; } // this is not legal
|
||||
if (BAD_SHORTADDR == shortaddr) { return device_unk; } // this is not legal
|
||||
Z_Device & device = findShortAddr(shortaddr);
|
||||
if (foundDevice(device)) {
|
||||
return device;
|
||||
@ -156,7 +158,7 @@ Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) {
|
||||
|
||||
// find the Device object by its longaddr (unique key if not null)
|
||||
Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) {
|
||||
if (!longaddr) { return (Z_Device&) device_unk; }
|
||||
if (!longaddr) { return device_unk; }
|
||||
Z_Device & device = findLongAddr(longaddr);
|
||||
if (foundDevice(device)) {
|
||||
return device;
|
||||
@ -211,7 +213,7 @@ Z_Device & Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) {
|
||||
if ((BAD_SHORTADDR != shortaddr) || longaddr) {
|
||||
return createDeviceEntry(shortaddr, longaddr);
|
||||
}
|
||||
return (Z_Device&) device_unk;
|
||||
return device_unk;
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,29 +310,13 @@ void Z_Device::setFriendlyName(const char * str) {
|
||||
setStringAttribute(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; }
|
||||
void Z_Device::setLastSeenNow(void) {
|
||||
// Only update time if after 2020-01-01 0000.
|
||||
// Fixes issue where zigbee device pings before WiFi/NTP has set utc_time
|
||||
// to the correct time, and "last seen" calculations are based on the
|
||||
// pre-corrected last_seen time and the since-corrected utc_time.
|
||||
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;
|
||||
last_seen = Rtc.utc_time;
|
||||
}
|
||||
|
||||
// get the next sequance number for the device, or use the global seq number if device is unknown
|
||||
@ -345,22 +331,32 @@ uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) {
|
||||
}
|
||||
}
|
||||
|
||||
// General Zigbee device profile support
|
||||
void Z_Devices::setLightProfile(uint16_t shortaddr, uint8_t light_profile) {
|
||||
Z_Device &device = getShortAddr(shortaddr);
|
||||
if (device.setLightChannels(light_profile)) {
|
||||
dirty();
|
||||
// returns: dirty flag, did we change the value of the object
|
||||
void Z_Device::setLightChannels(int8_t channels) {
|
||||
if (channels >= 0) {
|
||||
// retrieve of create light object
|
||||
Z_Data_Light & light = data.get<Z_Data_Light>(0);
|
||||
if (channels != light.getConfig()) {
|
||||
light.setConfig(channels);
|
||||
zigbee_devices.dirty();
|
||||
}
|
||||
Z_Data_OnOff & onoff = data.get<Z_Data_OnOff>(0);
|
||||
} else {
|
||||
// remove light / onoff object if any
|
||||
for (auto & data_elt : data) {
|
||||
if ((data_elt.getType() == Z_Data_Type::Z_Light) ||
|
||||
(data_elt.getType() == Z_Data_Type::Z_OnOff)) {
|
||||
// remove light object
|
||||
data.remove(&data_elt);
|
||||
zigbee_devices.dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the device profile or 0xFF if the device or profile is unknown
|
||||
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);
|
||||
const Z_Device &device = findShortAddr(shortaddr);
|
||||
int8_t light_profile = device.getLightChannels();
|
||||
if (0x00 == (light_profile & 0xF0)) {
|
||||
return (light_profile & 0x07);
|
||||
} else {
|
||||
@ -575,57 +571,56 @@ void Z_Devices::clean(void) {
|
||||
// - a long address starting with "0x", example: 0x7CB03EBB0A0292DD
|
||||
// - a number 0..99, the index number in ZigbeeStatus
|
||||
// - a friendly name, between quotes, example: "Room_Temp"
|
||||
uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const {
|
||||
if (nullptr == param) { return BAD_SHORTADDR; }
|
||||
Z_Device & Z_Devices::parseDeviceFromName(const char * param, bool short_must_be_known) {
|
||||
if (nullptr == param) { return device_unk; }
|
||||
size_t param_len = strlen(param);
|
||||
char dataBuf[param_len + 1];
|
||||
strcpy(dataBuf, param);
|
||||
RemoveSpace(dataBuf);
|
||||
uint16_t shortaddr = BAD_SHORTADDR; // start with unknown
|
||||
|
||||
if (strlen(dataBuf) < 4) {
|
||||
if ((dataBuf[0] >= '0') && (dataBuf[0] <= '9') && (strlen(dataBuf) < 4)) {
|
||||
// simple number 0..99
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) {
|
||||
shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1);
|
||||
return isKnownIndexDevice(XdrvMailbox.payload - 1);
|
||||
} else {
|
||||
return device_unk;
|
||||
}
|
||||
} else if ((dataBuf[0] == '0') && ((dataBuf[1] == 'x') || (dataBuf[1] == 'X'))) {
|
||||
// starts with 0x
|
||||
if (strlen(dataBuf) < 18) {
|
||||
// expect a short address
|
||||
shortaddr = strtoull(dataBuf, nullptr, 0);
|
||||
uint16_t shortaddr = strtoull(dataBuf, nullptr, 0);
|
||||
if (short_must_be_known) {
|
||||
shortaddr = zigbee_devices.findShortAddr(shortaddr).shortaddr; // if not found, it reverts to the unknown_device with address BAD_SHORTADDR
|
||||
return (Z_Device&) findShortAddr(shortaddr); // if not found, it reverts to the unknown_device with address BAD_SHORTADDR
|
||||
} else {
|
||||
return getShortAddr(shortaddr); // create it if not registered
|
||||
}
|
||||
// else we don't check if it's already registered to force unregistered devices
|
||||
} else {
|
||||
// expect a long address
|
||||
uint64_t longaddr = strtoull(dataBuf, nullptr, 0);
|
||||
shortaddr = zigbee_devices.isKnownLongAddr(longaddr);
|
||||
return isKnownLongAddrDevice(longaddr);
|
||||
}
|
||||
} else {
|
||||
// expect a Friendly Name
|
||||
shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf);
|
||||
return isKnownFriendlyNameDevice(dataBuf);
|
||||
}
|
||||
|
||||
return shortaddr;
|
||||
}
|
||||
|
||||
// Display the tracked status for a light
|
||||
String Z_Devices::dumpLightState(uint16_t shortaddr) const {
|
||||
String Z_Devices::dumpLightState(const Z_Device & device) {
|
||||
Z_attribute_list attr_list;
|
||||
char hex[8];
|
||||
|
||||
const Z_Device & device = findShortAddr(shortaddr);
|
||||
const char * fname = getFriendlyName(shortaddr);
|
||||
const char * fname = device.friendlyName;
|
||||
bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname?
|
||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr);
|
||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), device.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)) {
|
||||
if (device.valid()) {
|
||||
// dump all known values
|
||||
attr_list.addAttribute(F("Reachable")).setBool(device.getReachable());
|
||||
if (device.validPower()) { attr_list.addAttribute(F("Power")).setUInt(device.getPower()); }
|
||||
@ -654,60 +649,70 @@ String Z_Devices::dumpLightState(uint16_t shortaddr) const {
|
||||
// Dump the internal memory of Zigbee devices
|
||||
// Mode = 1: simple dump of devices addresses
|
||||
// Mode = 2: simple dump of devices addresses and names, endpoints, light
|
||||
String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const {
|
||||
String Z_Devices::dumpSingleDevice(uint32_t dump_mode, const class Z_Device & device) {
|
||||
uint16_t shortaddr = device.shortaddr;
|
||||
char hex[22];
|
||||
|
||||
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'; // prefix with '0x'
|
||||
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);
|
||||
}
|
||||
if (device.manufacturerId) {
|
||||
attr_list.addAttribute(F("Manufacturer")).setStr(device.manufacturerId);
|
||||
}
|
||||
|
||||
JsonGeneratorArray 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());
|
||||
|
||||
JsonGeneratorArray arr_data;
|
||||
for (auto & data_elt : device.data) {
|
||||
char key[8];
|
||||
if (data_elt.validConfig()) {
|
||||
snprintf_P(key, sizeof(key), "?%02X.%1X", data_elt.getEndpoint(), data_elt.getConfig());
|
||||
} else {
|
||||
snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint());
|
||||
}
|
||||
key[0] = Z_Data::DataTypeToChar(data_elt.getType());
|
||||
arr_data.addStr(key);
|
||||
}
|
||||
attr_list.addAttribute(F("Config")).setStrRaw(arr_data.toString().c_str());
|
||||
}
|
||||
return attr_list.toString(true);
|
||||
}
|
||||
|
||||
// If &device == nullptr, then dump all
|
||||
String Z_Devices::dumpDevice(uint32_t dump_mode, const Z_Device & device) const {
|
||||
JsonGeneratorArray json_arr;
|
||||
|
||||
for (const auto & device : _devices) {
|
||||
uint16_t shortaddr = device.shortaddr;
|
||||
char hex[22];
|
||||
|
||||
// ignore non-current device, if device specified
|
||||
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 (&device == nullptr) {
|
||||
if (dump_mode < 2) {
|
||||
// dump light mode for all devices
|
||||
for (const auto & device2 : _devices) {
|
||||
json_arr.addStrRaw(dumpSingleDevice(dump_mode, device2).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (2 <= dump_mode) {
|
||||
hex[0] = '0'; // prefix with '0x'
|
||||
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);
|
||||
}
|
||||
if (device.manufacturerId) {
|
||||
attr_list.addAttribute(F("Manufacturer")).setStr(device.manufacturerId);
|
||||
}
|
||||
|
||||
JsonGeneratorArray 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());
|
||||
|
||||
JsonGeneratorArray arr_data;
|
||||
for (auto & data_elt : device.data) {
|
||||
char key[8];
|
||||
if (data_elt.validConfig()) {
|
||||
snprintf_P(key, sizeof(key), "?%02X.%1X", data_elt.getEndpoint(), data_elt.getConfig());
|
||||
} else {
|
||||
snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint());
|
||||
}
|
||||
key[0] = Z_Data::DataTypeToChar(data_elt.getType());
|
||||
arr_data.addStr(key);
|
||||
}
|
||||
attr_list.addAttribute(F("Config")).setStrRaw(arr_data.toString().c_str());
|
||||
}
|
||||
json_arr.addStrRaw(attr_list.toString(true).c_str());
|
||||
} else {
|
||||
json_arr.addStrRaw(dumpSingleDevice(dump_mode, device).c_str());
|
||||
}
|
||||
|
||||
return json_arr.toString();
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version) {
|
||||
|
||||
// Hue bulbtype - if present
|
||||
if (1 == version) {
|
||||
zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d));
|
||||
device.setLightChannels(buf_d.get8(d));
|
||||
d++;
|
||||
} else if (2 == version) {
|
||||
// v2 parser
|
||||
|
@ -1853,7 +1853,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
|
||||
switch (ccccaaaa) {
|
||||
case 0x00000004: device.setManufId(attr.getStr()); break;
|
||||
case 0x00000005: device.setModelId(attr.getStr()); break;
|
||||
case 0x00010021: zigbee_devices.setBatteryPercent(shortaddr, uval16 / 2); break;
|
||||
case 0x00010021: device.setBatteryPercent(uval16 / 2); break;
|
||||
case 0x00060000:
|
||||
case 0x00068000: device.setPower(attr.getBool(), src_ep); break;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ void Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster
|
||||
// This callback is registered after a an attribute read command was made to a light, and fires if we don't get any response after 1000 ms
|
||||
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); // mark device as reachable
|
||||
zigbee_devices.getShortAddr(shortaddr).setReachable(false); // mark device as reachable
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1470,8 +1470,11 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
|
||||
// log the packet details
|
||||
zcl_received.log();
|
||||
|
||||
zigbee_devices.setLQI(srcaddr, linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI
|
||||
zigbee_devices.setLastSeenNow(srcaddr);
|
||||
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||
if (srcaddr != localShortAddr) {
|
||||
device.setLQI(linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI
|
||||
device.setLastSeenNow();
|
||||
}
|
||||
|
||||
char shortaddr[8];
|
||||
snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr);
|
||||
@ -1519,7 +1522,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) {
|
||||
|
||||
// since we just receveived data from the device, it is reachable
|
||||
zigbee_devices.resetTimersForDevice(srcaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there
|
||||
zigbee_devices.setReachable(srcaddr, true); // mark device as reachable
|
||||
device.setReachable(true); // mark device as reachable
|
||||
|
||||
if (defer_attributes) {
|
||||
// Prepare for publish
|
||||
@ -1615,8 +1618,11 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
|
||||
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
|
||||
// ZDO request
|
||||
// Report LQI
|
||||
zigbee_devices.setLQI(srcaddr, linkquality);
|
||||
zigbee_devices.setLastSeenNow(srcaddr);
|
||||
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||
if (srcaddr != localShortAddr) {
|
||||
device.setLQI(linkquality);
|
||||
device.setLastSeenNow();
|
||||
}
|
||||
// Since ZDO messages start with a sequence number, we skip it
|
||||
// but we add the source address in the last 2 bytes
|
||||
SBuffer zdo_buf(buf.get8(20) - 1 + 2);
|
||||
|
@ -683,7 +683,7 @@ void CmndZbSend(void) {
|
||||
// parse "Device" and "Group"
|
||||
JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)];
|
||||
if (val_device) {
|
||||
device = zigbee_devices.parseDeviceParam(val_device.getStr());
|
||||
device = zigbee_devices.parseDeviceFromName(val_device.getStr(), true).shortaddr;
|
||||
if (BAD_SHORTADDR == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
||||
}
|
||||
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
||||
@ -823,19 +823,19 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||
uint8_t endpoint = 0x00; // 0x00 is invalid for the src endpoint
|
||||
uint8_t toendpoint = 0x01; // default dest endpoint to 0x01
|
||||
uint16_t toGroup = 0x0000; // group address
|
||||
uint16_t cluster = 0; // 0xFFFF is invalid
|
||||
uint16_t cluster = 0; // cluster 0 is default
|
||||
uint32_t group = 0xFFFFFFFF; // 16 bits values, otherwise 0xFFFFFFFF is unspecified
|
||||
|
||||
// Information about source device: "Device", "Endpoint", "Cluster"
|
||||
// - the source endpoint must have a known IEEE address
|
||||
srcDevice = zigbee_devices.parseDeviceParam(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr));
|
||||
if (BAD_SHORTADDR == srcDevice) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
|
||||
const Z_Device & src_device = zigbee_devices.parseDeviceFromName(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr), true);
|
||||
if (!src_device.valid()) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
|
||||
// check if IEEE address is known
|
||||
uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice);
|
||||
uint64_t srcLongAddr = src_device.longaddr;
|
||||
if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; }
|
||||
// look for source endpoint
|
||||
endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), endpoint);
|
||||
if (0 == endpoint) { endpoint = zigbee_devices.findFirstEndpoint(srcDevice); }
|
||||
if (0 == endpoint) { endpoint = zigbee_devices.findFirstEndpoint(src_device.shortaddr); }
|
||||
// look for source cluster
|
||||
JsonParserToken val_cluster = root[PSTR(D_CMND_ZIGBEE_CLUSTER)];
|
||||
if (val_cluster) {
|
||||
@ -858,26 +858,23 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||
// If no target is specified, we default to coordinator 0x0000
|
||||
if ((!to_group) && (!dst_device)) {
|
||||
dstDevice = 0x0000;
|
||||
dstLongAddr = localIEEEAddr;
|
||||
toendpoint = 1;
|
||||
}
|
||||
|
||||
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; }
|
||||
if (dst_device) {
|
||||
const Z_Device & dstDevice = zigbee_devices.parseDeviceFromName(dst_device.getStr(nullptr), true);
|
||||
if (!dstDevice.valid()) { ResponseCmndChar_P(PSTR("Unknown dest device")); return; }
|
||||
dstLongAddr = dstDevice.longaddr;
|
||||
}
|
||||
|
||||
if (!to_group) {
|
||||
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
|
||||
toendpoint = root.getUInt(PSTR("ToEndpoint"), toendpoint);
|
||||
}
|
||||
|
||||
// make sure we don't have conflicting parameters
|
||||
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; }
|
||||
if (to_group && dst_device) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; }
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
SBuffer buf(34);
|
||||
@ -891,7 +888,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||
buf.add64(srcLongAddr);
|
||||
buf.add8(endpoint);
|
||||
buf.add16(cluster);
|
||||
if (dstLongAddr) {
|
||||
if (!to_group) {
|
||||
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
||||
buf.add64(dstLongAddr);
|
||||
buf.add8(toendpoint);
|
||||
@ -910,7 +907,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||
buf.add64(srcLongAddr);
|
||||
buf.add8(endpoint);
|
||||
buf.add16(cluster);
|
||||
if (dstLongAddr) {
|
||||
if (!to_group) {
|
||||
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
||||
buf.add64(dstLongAddr);
|
||||
buf.add8(toendpoint);
|
||||
@ -941,7 +938,7 @@ void CmndZbUnbind(void) {
|
||||
|
||||
void CmndZbBindState_or_Map(uint16_t zdo_cmd) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true).shortaddr;
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
uint8_t index = XdrvMailbox.index - 1; // change default 1 to 0
|
||||
|
||||
@ -1002,7 +999,7 @@ void CmndZbProbe(void) {
|
||||
//
|
||||
void CmndZbProbeOrPing(boolean probe) {
|
||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true).shortaddr;
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
// everything is good, we can send the command
|
||||
@ -1034,19 +1031,19 @@ void CmndZbName(void) {
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p;
|
||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
char *str = strtok_r(XdrvMailbox.data, ",", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, false); // it's the only case where we create a new device
|
||||
if (!device.valid()) { 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 : "");
|
||||
const char * friendlyName = device.friendlyName;
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), device.shortaddr, friendlyName ? friendlyName : "");
|
||||
} else {
|
||||
if (strlen(p) > 32) { p[32] = 0x00; } // truncate to 32 chars max
|
||||
zigbee_devices.getShortAddr(shortaddr).setFriendlyName(p);
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p);
|
||||
device.setFriendlyName(p);
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), device.shortaddr, p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1066,18 +1063,18 @@ void CmndZbModelId(void) {
|
||||
|
||||
// check if parameters contain a comma ','
|
||||
char *p;
|
||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
char *str = strtok_r(XdrvMailbox.data, ",", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { 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 : "");
|
||||
const char * modelId = device.modelId;
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), device.shortaddr, modelId ? modelId : "");
|
||||
} else {
|
||||
zigbee_devices.getShortAddr(shortaddr).setModelId(p);
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, p);
|
||||
device.setModelId(p);
|
||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), device.shortaddr, p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1098,16 +1095,16 @@ void CmndZbLight(void) {
|
||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { 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);
|
||||
device.setLightChannels(bulbtype);
|
||||
}
|
||||
String dump = zigbee_devices.dumpLightState(shortaddr);
|
||||
String dump = zigbee_devices.dumpLightState(device);
|
||||
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));
|
||||
@ -1141,10 +1138,8 @@ void CmndZbOccupancy(void) {
|
||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||
|
||||
// parse first part, <device_id>
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
Z_Device & device = zigbee_devices.getShortAddr(shortaddr);
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
int8_t occupancy_time = -1;
|
||||
if (p) {
|
||||
@ -1170,11 +1165,11 @@ void CmndZbOccupancy(void) {
|
||||
//
|
||||
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; }
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
// everything is good, we can send the command
|
||||
if (zigbee_devices.removeDevice(shortaddr)) {
|
||||
if (zigbee_devices.removeDevice(device.shortaddr)) {
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
ResponseCmndChar_P(PSTR("Unknown device"));
|
||||
@ -1369,12 +1364,17 @@ void ZigbeeGlowPermitJoinLight(void) {
|
||||
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);
|
||||
String dump;
|
||||
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true);
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device);
|
||||
} else {
|
||||
if (XdrvMailbox.index >= 2) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
dump = zigbee_devices.dumpDevice(XdrvMailbox.index, *(Z_Device*)nullptr);
|
||||
}
|
||||
|
||||
String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr);
|
||||
Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str());
|
||||
}
|
||||
}
|
||||
@ -1502,9 +1502,8 @@ void CmndZbData(void) {
|
||||
}
|
||||
|
||||
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);
|
||||
Z_Device & device = zigbee_devices.parseDeviceFromName(device_name.getStr(), true);
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
JsonParserObject inner_data = device_name.getValue().getObject();
|
||||
if (inner_data) {
|
||||
if (!parseDeviceInnerData(device, inner_data)) {
|
||||
@ -1518,9 +1517,8 @@ void CmndZbData(void) {
|
||||
// non-JSON, export current data
|
||||
// ZbData 0x1234
|
||||
// ZbData Device_Name
|
||||
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_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true);
|
||||
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
Z_attribute_list attr_data;
|
||||
|
||||
@ -1568,7 +1566,7 @@ void CmndZbData(void) {
|
||||
}
|
||||
|
||||
char hex[8];
|
||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr);
|
||||
snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), device.shortaddr);
|
||||
Response_P(PSTR("{\"%s\":{\"%s\":%s}}"), XdrvMailbox.command, hex, attr_data.toString(true).c_str());
|
||||
}
|
||||
}
|
||||
|
@ -107,9 +107,21 @@ struct METER_DESC {
|
||||
#define COMBO3b 12
|
||||
#define WGS_COMBO 13
|
||||
#define EBZD_G 14
|
||||
#define SML_NO_OP 15
|
||||
|
||||
// select this meter
|
||||
#define METER EHZ161_1
|
||||
// SML_NO_OP ignores hardcoded interface
|
||||
#define METER SML_NO_OP
|
||||
//#define METER EHZ161_1
|
||||
|
||||
#if METER==SML_NO_OP
|
||||
#undef METERS_USED
|
||||
#define METERS_USED 0
|
||||
struct METER_DESC const meter_desc[1]={
|
||||
[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|";
|
||||
#endif
|
||||
|
||||
|
||||
#if METER==EHZ161_0
|
||||
@ -1662,6 +1674,7 @@ void SML_Show(boolean json) {
|
||||
//char b_mqtt_data[MESSZ];
|
||||
//b_mqtt_data[0]=0;
|
||||
|
||||
if (!meters_used) return;
|
||||
|
||||
int8_t lastmind=((*mp)&7)-1;
|
||||
if (lastmind<0 || lastmind>=meters_used) lastmind=0;
|
||||
@ -1794,7 +1807,7 @@ void SML_Show(boolean json) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (json && !TasmotaGlobal.tele_period) {
|
||||
char str[16];
|
||||
@ -1806,7 +1819,7 @@ void SML_Show(boolean json) {
|
||||
DomoticzSensor(DZ_CURRENT, str); // Current
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
struct SML_COUNTER {
|
||||
@ -1826,39 +1839,32 @@ struct SML_COUNTER {
|
||||
#endif
|
||||
} sml_counters[MAX_COUNTERS];
|
||||
|
||||
void ICACHE_RAM_ATTR SML_CounterUpd(uint8_t index) {
|
||||
uint8_t sml_counter_pinstate;
|
||||
|
||||
uint8_t level=digitalRead(meter_desc_p[sml_counters[index].sml_cnt_old_state].srcpin);
|
||||
if (!level) {
|
||||
// falling edge
|
||||
uint32_t ltime=millis()-sml_counters[index].sml_counter_ltime;
|
||||
sml_counters[index].sml_counter_ltime=millis();
|
||||
if (ltime>sml_counters[index].sml_debounce) {
|
||||
RtcSettings.pulse_counter[index]++;
|
||||
sml_counters[index].sml_cnt_updated=1;
|
||||
//InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]);
|
||||
}
|
||||
} else {
|
||||
// rising edge
|
||||
sml_counters[index].sml_counter_ltime=millis();
|
||||
uint8_t sml_cnt_index[MAX_COUNTERS] = { 0, 1, 2, 3 };
|
||||
void ICACHE_RAM_ATTR SML_CounterIsr(void *arg) {
|
||||
uint32_t index = *static_cast<uint8_t*>(arg);
|
||||
|
||||
uint32_t time = micros();
|
||||
uint32_t debounce_time;
|
||||
|
||||
if (digitalRead(meter_desc_p[sml_counters[index].sml_cnt_old_state].srcpin) == bitRead(sml_counter_pinstate, index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
debounce_time = time - sml_counters[index].sml_counter_ltime;
|
||||
|
||||
if (debounce_time <= sml_counters[index].sml_debounce * 1000) return;
|
||||
|
||||
if bitRead(sml_counter_pinstate, index) {
|
||||
// falling edge
|
||||
RtcSettings.pulse_counter[index]++;
|
||||
sml_counters[index].sml_cnt_updated=1;
|
||||
}
|
||||
sml_counters[index].sml_counter_ltime = time;
|
||||
sml_counter_pinstate ^= (1<<index);
|
||||
}
|
||||
|
||||
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];
|
||||
@ -1916,14 +1922,6 @@ uint32_t SML_getscriptsize(char *lp) {
|
||||
#endif
|
||||
|
||||
bool Gpio_used(uint8_t gpiopin) {
|
||||
/*
|
||||
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) {
|
||||
// if (pin_gpio[i]==gpiopin) {
|
||||
if (Pin(i)==gpiopin) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if ((gpiopin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) {
|
||||
return true;
|
||||
}
|
||||
@ -2131,7 +2129,6 @@ next_line:
|
||||
|
||||
init10:
|
||||
typedef void (*function)();
|
||||
function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4};
|
||||
uint8_t cindex=0;
|
||||
// preloud counters
|
||||
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
||||
@ -2158,7 +2155,7 @@ init10:
|
||||
// check for irq mode
|
||||
if (meter_desc_p[meters].params<=0) {
|
||||
// init irq mode
|
||||
attachInterrupt(meter_desc_p[meters].srcpin, counter_callbacks[cindex], CHANGE);
|
||||
attachInterruptArg(meter_desc_p[meters].srcpin, SML_CounterIsr,&sml_cnt_index[cindex], CHANGE);
|
||||
sml_counters[cindex].sml_cnt_old_state=meters;
|
||||
sml_counters[cindex].sml_debounce=-meter_desc_p[meters].params;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
--------------------------------------------------------------------------------------------
|
||||
Version yyyymmdd Action Description
|
||||
--------------------------------------------------------------------------------------------
|
||||
0.9.5.0 20201101 added - bugfixes, better advertisement parsing, beacon, HASS-fixes, CGD1 now passive readable
|
||||
---
|
||||
0.9.4.1 20200807 added - add ATC, some optimizations and a bit more error handling
|
||||
---
|
||||
0.9.4.0 20200807 added - multiple backports from the HM10-driver (NLIGHT,MJYD2S,YEERC,MHOC401,MHOC303),
|
||||
@ -54,44 +56,7 @@ TasmotaSerial *HM10Serial;
|
||||
#define HM10_MAX_TASK_NUMBER 12
|
||||
uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms
|
||||
|
||||
#define HM10_MAX_RX_BUF 384
|
||||
|
||||
struct {
|
||||
uint8_t current_task_delay; // number of 100ms-cycles
|
||||
uint8_t last_command;
|
||||
uint16_t perPage = 4;
|
||||
uint16_t firmware;
|
||||
uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
||||
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; // points to to the number 0...255
|
||||
// TODO: more to come
|
||||
} 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;
|
||||
#define HM10_MAX_RX_BUF 64
|
||||
|
||||
#pragma pack(1) // byte-aligned structures to read the sensor data
|
||||
|
||||
@ -152,8 +117,44 @@ struct ATCPacket_t{
|
||||
uint8_t frameCnt;
|
||||
};
|
||||
|
||||
struct cg_packet_t {
|
||||
uint16_t frameID;
|
||||
uint8_t MAC[6];
|
||||
uint16_t mode;
|
||||
union {
|
||||
struct {
|
||||
int16_t temp; // -9 - 59 °C
|
||||
uint16_t hum;
|
||||
};
|
||||
uint8_t bat;
|
||||
};
|
||||
};
|
||||
#pragma pack(0)
|
||||
|
||||
struct scan_entry_t {
|
||||
uint8_t MAC[6];
|
||||
uint16_t CID;
|
||||
uint16_t UUID;
|
||||
int32_t RSSI;
|
||||
uint8_t TX;
|
||||
union{
|
||||
uint16_t SVC;
|
||||
uint8_t svcData[32];
|
||||
};
|
||||
};
|
||||
|
||||
struct generic_beacon_t {
|
||||
uint8_t MAC[6];
|
||||
uint32_t time;
|
||||
int32_t RSSI;
|
||||
uint16_t CID; // company identifier
|
||||
uint16_t UUID; // the first, if more than one exists
|
||||
uint16_t SVC;
|
||||
uint16_t TX;
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
|
||||
struct mi_sensor_t{
|
||||
uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6
|
||||
uint8_t lastCnt; //device generated counter of the packet
|
||||
@ -216,8 +217,51 @@ struct mi_sensor_t{
|
||||
};
|
||||
};
|
||||
|
||||
struct {
|
||||
uint8_t current_task_delay; // number of 100ms-cycles
|
||||
uint8_t last_command;
|
||||
uint16_t perPage = 4;
|
||||
uint16_t firmware;
|
||||
uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
||||
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;
|
||||
uint32_t activeBeacon:1;
|
||||
uint32_t firstAutodiscoveryDone:1;
|
||||
} mode;
|
||||
struct {
|
||||
uint8_t sensor; // points to to the number 0...255
|
||||
uint8_t beaconScanCounter;
|
||||
// TODO: more to come
|
||||
} state;
|
||||
struct {
|
||||
uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode
|
||||
uint32_t noSummary:1; // no sensor values at TELE-period
|
||||
uint32_t directBridgeMode:1; // send every received BLE-packet as a MQTT-message in real-time
|
||||
uint32_t holdBackFirstAutodiscovery:1; // allows to trigger it later
|
||||
uint32_t showRSSI:1;
|
||||
uint32_t ignoreBogusBattery:1;
|
||||
uint32_t minimalSummary:1; // DEPRECATED!!
|
||||
} option;
|
||||
scan_entry_t rxAdvertisement;
|
||||
char *rxBuffer;
|
||||
} HM10;
|
||||
|
||||
std::vector<mi_sensor_t> MIBLEsensors;
|
||||
std::array<generic_beacon_t,4> MIBLEbeacons; // we support a fixed number
|
||||
std::vector<scan_entry_t> MINBLEscanResult;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* constants
|
||||
@ -226,8 +270,9 @@ std::vector<mi_sensor_t> 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_SVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s%u\":\"%s\"}";
|
||||
const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}";
|
||||
const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto|Page";
|
||||
const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto|Page|Beacon";
|
||||
|
||||
#define FLORA 1
|
||||
#define MJ_HT_V1 2
|
||||
@ -285,7 +330,8 @@ enum HM10_Commands { // commands useable in console or rules
|
||||
CMND_HM10_BAUD, // serial speed of ESP8266 (<-> HM10), does not change baud rate of HM10
|
||||
CMND_HM10_TIME, // set LYWSD02-Time from ESP8266-time
|
||||
CMND_HM10_AUTO, // do discovery scans permanently to receive MiBeacons in seconds between read-cycles
|
||||
CMND_HM10_PAGE // sensor entries per web page, which will be shown alternated
|
||||
CMND_HM10_PAGE, // sensor entries per web page, which will be shown alternated
|
||||
CMND_HM10_BEACON // add up to 4 beacons defined by their MAC addresses
|
||||
};
|
||||
|
||||
enum HM10_awaitData: uint8_t {
|
||||
@ -354,6 +400,50 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){
|
||||
HM10_TASK_LIST[slot][0] = task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove all colons from null terminated char array
|
||||
*
|
||||
* @param _string Typically representing a MAC-address like AA:BB:CC:DD:EE:FF
|
||||
*/
|
||||
void HM10stripColon(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert string that repesents a hexadecimal number to a byte array
|
||||
*
|
||||
* @param _string input string in format: AABBCCDDEEFF or AA:BB:CC:DD:EE:FF, caseinsensitive
|
||||
* @param _mac target byte array must match the correct size (i.e. AA:BB -> uint8_t bytes[2])
|
||||
*/
|
||||
|
||||
void HM10HexStringToBytes(char* _string, uint8_t* _byteArray) {
|
||||
HM10stripColon(_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 HM10_ReverseMAC(uint8_t _mac[]){
|
||||
uint8_t _reversedMAC[6];
|
||||
for (uint8_t i=0; i<6; i++){
|
||||
@ -361,7 +451,23 @@ void HM10_ReverseMAC(uint8_t _mac[]){
|
||||
}
|
||||
memcpy(_mac,_reversedMAC, sizeof(_reversedMAC));
|
||||
}
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
/**
|
||||
* @brief For HASS only, changes last entry of JSON in mqtt_data to 'null'
|
||||
*/
|
||||
|
||||
void HM10nullifyEndOfMQTT_DATA(){
|
||||
char *p = TasmotaGlobal.mqtt_data + strlen(TasmotaGlobal.mqtt_data);
|
||||
while(true){
|
||||
*p--;
|
||||
if(p[0]==':'){
|
||||
p[1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ResponseAppend_P(PSTR("null"));
|
||||
}
|
||||
#endif // USE_HOME_ASSISTANT
|
||||
/*********************************************************************************************\
|
||||
* chained tasks
|
||||
\*********************************************************************************************/
|
||||
@ -377,9 +483,9 @@ void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disco
|
||||
}
|
||||
|
||||
void HM10_Discovery_Scan(void) {
|
||||
HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
|
||||
HM10_Launchtask(TASK_HM10_DISC,1,1); // discovery
|
||||
HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); // status
|
||||
// HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
|
||||
HM10_Launchtask(TASK_HM10_DISC,0,1); // discovery
|
||||
// HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); // status
|
||||
}
|
||||
|
||||
void HM10_Read_LYWSD03(void) { //and MHO-C401
|
||||
@ -441,7 +547,7 @@ void HM10_Read_MJ_HT_V1(void) {
|
||||
* @param _type Type number of the sensor
|
||||
* @return uint32_t Known or new slot in the sensors-vector
|
||||
*/
|
||||
uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){
|
||||
uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, int _rssi){
|
||||
|
||||
DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type);
|
||||
bool _success = false;
|
||||
@ -461,6 +567,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){
|
||||
for(uint32_t i=0; i<MIBLEsensors.size(); i++){
|
||||
if(memcmp(_MAC,MIBLEsensors[i].MAC,sizeof(_MAC))==0){
|
||||
DEBUG_SENSOR_LOG(PSTR("%s: known sensor at slot: %u"),D_CMND_HM10, i);
|
||||
MIBLEsensors[i].rssi=_rssi;
|
||||
if(MIBLEsensors[i].showedUp < 4){ // if we got an intact packet, the sensor should show up several times
|
||||
MIBLEsensors[i].showedUp++; // count up to the above number ... now we are pretty sure
|
||||
}
|
||||
@ -477,7 +584,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){
|
||||
_newSensor.feature.raw = 0;
|
||||
_newSensor.temp =NAN;
|
||||
_newSensor.bat=0x00;
|
||||
_newSensor.rssi=_rssi * -1;
|
||||
_newSensor.rssi=_rssi;
|
||||
_newSensor.lux = 0x00ffffff;
|
||||
switch (_type){
|
||||
case FLORA:
|
||||
@ -540,13 +647,15 @@ void HM10SerialInit(void) {
|
||||
HM10.period = Settings.tele_period;
|
||||
DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10);
|
||||
|
||||
//test section for options - TODO: make a real interface for it
|
||||
HM10.option.noRealTime = 1;
|
||||
//test section for options
|
||||
HM10.option.allwaysAggregate = 1;
|
||||
HM10.option.showRSSI = 0;
|
||||
HM10.option.ignoreBogusBattery = 1;
|
||||
HM10.option.noSummary = 0;
|
||||
HM10.option.minimalSummary = 0;
|
||||
HM10.option.directBridgeMode = 0;
|
||||
HM10.option.showRSSI = 1;
|
||||
HM10.option.ignoreBogusBattery = 1; // from advertisements
|
||||
HM10.option.holdBackFirstAutodiscovery = 1;
|
||||
HM10.mode.autoScan = 1;
|
||||
|
||||
HM10.rxBuffer = new char[HM10_MAX_RX_BUF];
|
||||
}
|
||||
@ -568,24 +677,26 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
|
||||
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; // probably false alarm from a damaged packet
|
||||
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++;
|
||||
// if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){
|
||||
// if (MIBLEsensors[_slot].showedUp>3) return; // probably false alarm from a damaged packet
|
||||
// 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]);
|
||||
|
||||
// MIBLEsensors[_slot].rssi = _rssi;
|
||||
if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){
|
||||
if(MIBLEsensors[_slot].type==LYWSD03MMC || MIBLEsensors[_slot].type==CGD1 || MIBLEsensors[_slot].type==MHOC401){
|
||||
DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type);
|
||||
return;
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: %s mibeacon type: %x"),D_CMND_HM10, kHM10DeviceType[MIBLEsensors[_slot].type-1], _beacon.type);
|
||||
|
||||
DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
||||
switch(_beacon.type){
|
||||
case 0x01:
|
||||
@ -659,7 +770,7 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
|
||||
}
|
||||
if(MIBLEsensors[_slot].eventType.raw == 0) return;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
|
||||
void HM10parseATC(char * _buf, uint32_t _slot){
|
||||
@ -669,75 +780,64 @@ void HM10parseATC(char * _buf, uint32_t _slot){
|
||||
MIBLEsensors.at(_slot).hum = (float)_packet->hum;
|
||||
MIBLEsensors.at(_slot).bat = _packet->batPer;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
|
||||
char* HM10ParseResponse(char *buf, uint16_t bufsize) {
|
||||
if (!strncmp(buf,"HMSoft",6)) { //8
|
||||
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)){ //strstr() does miss too much
|
||||
_idx=_pos-buf;
|
||||
if(memcmp(&_pos+1,_subStr,3)){
|
||||
break;
|
||||
void HM10parseCGD1Packet(char * _buf, uint32_t _slot){ // no MiBeacon
|
||||
cg_packet_t *_packet = (cg_packet_t*)_buf;
|
||||
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"));
|
||||
}
|
||||
}
|
||||
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;
|
||||
_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("HM10: unexpected CGD1-packet"));
|
||||
}
|
||||
if(MIBLEsensors[_slot].eventType.raw == 0) return;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
|
||||
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; // LYWSD02 or MHO-C303
|
||||
_type = 0xa1c; //ATC
|
||||
_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;
|
||||
void HM10ParseResponse(char *buf, uint16_t bufsize) {
|
||||
if (!strncmp(buf,"HMSoft",6)) { //8
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void HM10readHT_LY(char *_buf){
|
||||
@ -768,7 +868,7 @@ void HM10readHT_LY(char *_buf){
|
||||
MIBLEsensors[_slot].eventType.bat = 1;
|
||||
}
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -797,7 +897,7 @@ void HM10readHT_CGD1(char *_buf){
|
||||
}
|
||||
MIBLEsensors[_slot].eventType.tempHum = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -827,7 +927,7 @@ void HM10readHT_MJ_HT_V1(char *_buf){
|
||||
}
|
||||
MIBLEsensors[_slot].eventType.tempHum = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
}
|
||||
|
||||
void HM10readTLMF(char *_buf){
|
||||
@ -851,8 +951,7 @@ void HM10readTLMF(char *_buf){
|
||||
MIBLEsensors[_slot].eventType.moist = 1;
|
||||
MIBLEsensors[_slot].eventType.fert = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
HM10.mode.awaiting = none;
|
||||
HM10.current_task_delay = 0;
|
||||
}
|
||||
@ -873,13 +972,90 @@ bool HM10readBat(char *_buf){
|
||||
MIBLEsensors[_slot].showedUp=255; // this sensor is real
|
||||
MIBLEsensors[_slot].eventType.bat = 1;
|
||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||
HM10.mode.shallTriggerTele = 1;
|
||||
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* beacon functions
|
||||
\*********************************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Handle a generic BLE advertisment in a running scan or to check a beacon
|
||||
*
|
||||
*
|
||||
*/
|
||||
void HM10HandleGenericBeacon(void){
|
||||
if(HM10.state.beaconScanCounter==0){ //handle beacon
|
||||
for(auto &_beacon : MIBLEbeacons){
|
||||
if(memcmp(HM10.rxAdvertisement.MAC,_beacon.MAC,6)==0){
|
||||
_beacon.time = 0;
|
||||
_beacon.RSSI = HM10.rxAdvertisement.RSSI;
|
||||
_beacon.SVC = HM10.rxAdvertisement.SVC;
|
||||
_beacon.CID = HM10.rxAdvertisement.CID;
|
||||
_beacon.UUID = HM10.rxAdvertisement.UUID;
|
||||
_beacon.TX = HM10.rxAdvertisement.TX;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// else handle scan
|
||||
if(MINBLEscanResult.size()>19) {
|
||||
AddLog_P2(LOG_LEVEL_INFO,PSTR("HM10: Scan buffer full"));
|
||||
HM10.state.beaconScanCounter = 1;
|
||||
return;
|
||||
}
|
||||
for(auto _scanResult : MINBLEscanResult){
|
||||
if(memcmp(HM10.rxAdvertisement.MAC,_scanResult.MAC,6)==0){
|
||||
// AddLog_P2(LOG_LEVEL_INFO,PSTR("HM10: known device"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
MINBLEscanResult.push_back(HM10.rxAdvertisement);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a beacon defined by its MAC-address, if only zeros are given, the beacon will be deactivated
|
||||
*
|
||||
* @param index 1-4 beacons are currently supported
|
||||
* @param data null terminated char array representing a MAC-address in hex
|
||||
*/
|
||||
void HM10addBeacon(uint8_t index, char* data){
|
||||
auto &_new = MIBLEbeacons[index-1]; //TODO: check
|
||||
HM10HexStringToBytes(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("HM10: beacon%u deactivated"), index);
|
||||
}
|
||||
else{
|
||||
_new.active = true;
|
||||
HM10.mode.activeBeacon = 1;
|
||||
AddLog_P2(LOG_LEVEL_INFO,PSTR("HM10: beacon added with MAC: %s"), _MAC);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Present BLE scan in the console, after that deleting the scan data
|
||||
*
|
||||
*/
|
||||
void HM10showScanResults(){
|
||||
AddLog_P2(LOG_LEVEL_INFO,PSTR("HM10: 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 _ TX: %02u _ RSSI: %d"), _MAC, _scanResult.CID, _scanResult.SVC, _scanResult.UUID, _scanResult.TX, _scanResult.RSSI);
|
||||
}
|
||||
MINBLEscanResult.clear();
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* handle the return value from the HM10
|
||||
\*********************************************************************************************/
|
||||
@ -887,19 +1063,63 @@ bool HM10readBat(char *_buf){
|
||||
bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
||||
bool success = false;
|
||||
uint32_t i = 0;
|
||||
uint32_t _targetsize = 64; //set to some save value
|
||||
bool _isPotentialAdv = false;
|
||||
bool _isValidAdv = false;
|
||||
char* _rx = HM10.rxBuffer; // we start always with the buffer
|
||||
uint32_t _nextStep = 2; // we can expect length and AD type at the first two positions anyway
|
||||
uint8_t length_type[64]; // length,AD-type,buffer - buffer should be too large
|
||||
while(HM10Serial->available() && (_targetsize!=i)) {
|
||||
*_rx= HM10Serial->read();
|
||||
if(i==18){
|
||||
if(memcmp(HM10.rxBuffer+4,"ISA:",4)==0){ //last 4 bytes of "OK+DISA:" should be safe enough
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s packet size: %u"),D_CMND_HM10,HM10.rxBuffer[16]);
|
||||
_targetsize = HM10.rxBuffer[16] + 19; // this is the size byte according to HM-10 docs
|
||||
if(_targetsize>64) _targetsize=64;
|
||||
memcpy(HM10.rxAdvertisement.MAC,HM10.rxBuffer+8,6);
|
||||
HM10_ReverseMAC(HM10.rxAdvertisement.MAC);
|
||||
HM10.rxAdvertisement.RSSI = (256 - HM10.rxBuffer[15]) * -1;
|
||||
length_type[0] = HM10.rxBuffer[17]; //length
|
||||
length_type[1] = HM10.rxBuffer[18]; //AD-type
|
||||
_isPotentialAdv = true;
|
||||
}
|
||||
}
|
||||
|
||||
while(HM10Serial->available()) {
|
||||
if(i<HM10_MAX_RX_BUF){
|
||||
HM10.rxBuffer[i] = HM10Serial->read();
|
||||
if(_isPotentialAdv){ // we will change the pointer now according to the AD-type and data length
|
||||
if(_nextStep>length_type[0]){
|
||||
if(length_type[1]==0xff){ //we only want the CID from the custom data 0xff ...
|
||||
memcpy((uint8_t*)&HM10.rxAdvertisement.CID,length_type+2,2); // ... and leave the rest unused in the buffer
|
||||
}
|
||||
_nextStep=0;
|
||||
_rx = (char*)&length_type - 1;
|
||||
}
|
||||
else if(_nextStep == 2){
|
||||
switch(length_type[1]){ //AD type
|
||||
case 0x02: case 0x03:
|
||||
_rx = (char*)&HM10.rxAdvertisement.UUID - 1;
|
||||
break;
|
||||
case 0x0a:
|
||||
if(length_type[0] == 0xd) {
|
||||
if(_targetsize-i == 1)_isValidAdv = true; // expected trailing bytes for a valid packet
|
||||
}
|
||||
_rx = (char*)&HM10.rxAdvertisement.TX - 1;
|
||||
break;
|
||||
case 0x16:
|
||||
_rx = (char*)HM10.rxAdvertisement.svcData - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_nextStep++;
|
||||
}
|
||||
i++;
|
||||
_rx++;
|
||||
success = true;
|
||||
}
|
||||
|
||||
if(i==0){
|
||||
if(HM10.mode.shallTriggerTele){ // let us use the spare time for other things
|
||||
HM10.mode.shallTriggerTele=0;
|
||||
if(HM10.option.noRealTime){
|
||||
if(HM10.option.directBridgeMode){
|
||||
HM10.mode.triggeredTele=0;
|
||||
return success;
|
||||
}
|
||||
@ -928,11 +1148,23 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
||||
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)); // try a second parse
|
||||
}
|
||||
if(_isValidAdv) {
|
||||
if(HM10.state.beaconScanCounter!=0 || HM10.mode.activeBeacon){
|
||||
HM10HandleGenericBeacon();
|
||||
}
|
||||
uint16_t _type = (uint8_t)HM10.rxAdvertisement.svcData[5]*256 + (uint8_t)HM10.rxAdvertisement.svcData[4];
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%04x %02x %04x %04x %04x"),HM10.rxAdvertisement.UUID,HM10.rxAdvertisement.TX,HM10.rxAdvertisement.CID,HM10.rxAdvertisement.SVC, _type);
|
||||
if(HM10.rxAdvertisement.SVC==0x181a) _type = 0xa1c;
|
||||
else if(HM10.rxAdvertisement.SVC==0xfdcd) _type = 0x0576;
|
||||
uint16_t _slot = MIBLEgetSensorSlot(HM10.rxAdvertisement.MAC, _type, HM10.rxAdvertisement.RSSI);
|
||||
if(_slot!=0xff){
|
||||
if (_type==0xa1c) HM10parseATC((char*)HM10.rxAdvertisement.svcData+2,_slot);
|
||||
else if (_type==0x0576) HM10parseCGD1Packet((char*)HM10.rxAdvertisement.svcData+2,_slot);
|
||||
else HM10parseMiBeacon((char*)HM10.rxAdvertisement.svcData+2,_slot);
|
||||
}
|
||||
else{
|
||||
// AddLogBuffer(LOG_LEVEL_INFO,(uint8_t*)HM10.rxAdvertisement.svcData,16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tempHumMJ:
|
||||
@ -949,6 +1181,9 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
||||
break;
|
||||
}
|
||||
memset(HM10.rxBuffer,0,i); // wipe away the recent bytes
|
||||
if(_isPotentialAdv){
|
||||
memset((void*)&HM10.rxAdvertisement,0,sizeof(HM10.rxAdvertisement));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -1203,7 +1438,7 @@ void HM10StatusInfo() {
|
||||
AddLog_P2(LOG_LEVEL_INFO, stemp);
|
||||
RulesProcessEvent(stemp);
|
||||
*/
|
||||
Response_P(PSTR("{%s:{\"found\":%u}}"), D_CMND_HM10, MIBLEsensors.size());
|
||||
Response_P(PSTR("{\"%s\":{\"found\":%u}}"), D_CMND_HM10, MIBLEsensors.size());
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
|
||||
@ -1223,6 +1458,25 @@ void HM10EverySecond(bool restart){
|
||||
return;
|
||||
}
|
||||
|
||||
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}}"), _idx, _beacon.time);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
if(_activeBeacons==0) HM10.mode.activeBeacon = 0;
|
||||
|
||||
if(HM10.state.beaconScanCounter!=0){
|
||||
HM10.state.beaconScanCounter--;
|
||||
if(HM10.state.beaconScanCounter==0){
|
||||
HM10showScanResults();
|
||||
}
|
||||
}
|
||||
|
||||
if(HM10.firmware == 0) return;
|
||||
if(HM10.mode.pending_task == 1) return;
|
||||
if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return;
|
||||
@ -1358,6 +1612,31 @@ bool HM10Cmd(void) {
|
||||
HM10_Discovery_Scan();
|
||||
Response_P(S_JSON_HM10_COMMAND, command, "");
|
||||
break;
|
||||
case CMND_HM10_BEACON:
|
||||
if (XdrvMailbox.data_len == 0) {
|
||||
switch(XdrvMailbox.index){
|
||||
case 0:
|
||||
HM10.state.beaconScanCounter = 8;
|
||||
Response_P(S_JSON_HM10_COMMAND_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_HM10_COMMAND_SVALUE, command, XdrvMailbox.index,_MAC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(XdrvMailbox.data_len == 12 || XdrvMailbox.data_len == 17){ // MAC-string without or with colons
|
||||
switch(XdrvMailbox.index){
|
||||
case 1: case 2: case 3: case 4:
|
||||
HM10addBeacon(XdrvMailbox.index,XdrvMailbox.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Response_P(S_JSON_HM10_COMMAND_SVALUE, command, XdrvMailbox.index,XdrvMailbox.data);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// else for Unknown command
|
||||
serviced = false;
|
||||
@ -1388,7 +1667,7 @@ void HM10triggerTele(void){
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}";
|
||||
const char HTTP_HM10[] PROGMEM = "{s}HM10 FW%u V0950{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}";
|
||||
@ -1398,6 +1677,20 @@ const char HTTP_HM10_HL[] PROGMEM = "{s}<hr>{m}<hr>{e}";
|
||||
void HM10Show(bool json)
|
||||
{
|
||||
if (json) {
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
bool _noSummarySave = HM10.option.noSummary;
|
||||
bool _minimalSummarySave = HM10.option.minimalSummary;
|
||||
if(hass_mode==2){
|
||||
if(HM10.option.holdBackFirstAutodiscovery){
|
||||
if(!HM10.mode.firstAutodiscoveryDone){
|
||||
HM10.mode.firstAutodiscoveryDone = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
HM10.option.noSummary = false;
|
||||
HM10.option.minimalSummary = false;
|
||||
}
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
if(!HM10.mode.triggeredTele){
|
||||
if(HM10.option.noSummary) return; // no message at TELEPERIOD
|
||||
}
|
||||
@ -1416,7 +1709,11 @@ void HM10Show(bool json)
|
||||
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)) {
|
||||
if (!isnan(MIBLEsensors[i].hum) && !isnan(MIBLEsensors[i].temp)
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum);
|
||||
tempHumSended = true;
|
||||
@ -1425,7 +1722,11 @@ void HM10Show(bool json)
|
||||
}
|
||||
if(MIBLEsensors[i].feature.temp && !tempHumSended){
|
||||
if(MIBLEsensors[i].eventType.temp || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
|
||||
if (!isnan(MIBLEsensors[i].temp)) {
|
||||
if (!isnan(MIBLEsensors[i].temp)
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) {
|
||||
char temperature[FLOATSZ];
|
||||
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), temperature);
|
||||
@ -1434,7 +1735,11 @@ void HM10Show(bool json)
|
||||
}
|
||||
if(MIBLEsensors[i].feature.hum && !tempHumSended){
|
||||
if(MIBLEsensors[i].eventType.hum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
|
||||
if (!isnan(MIBLEsensors[i].hum)) {
|
||||
if (!isnan(MIBLEsensors[i].hum)
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) {
|
||||
char hum[FLOATSZ];
|
||||
dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), hum);
|
||||
@ -1443,22 +1748,43 @@ void HM10Show(bool json)
|
||||
}
|
||||
if (MIBLEsensors[i].feature.lux){
|
||||
if(MIBLEsensors[i].eventType.lux || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
||||
if (MIBLEsensors[i].lux!=0x0ffffff) { // this is the error code -> no lux
|
||||
if (MIBLEsensors[i].lux!=0x0ffffff
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) { // this is the error code -> no lux
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux);
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if (MIBLEsensors[i].lux==0x0ffffff) HM10nullifyEndOfMQTT_DATA();
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MIBLEsensors[i].feature.moist){
|
||||
if(MIBLEsensors[i].eventType.moist || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
||||
if (MIBLEsensors[i].moisture!=0xff) {
|
||||
if (MIBLEsensors[i].moisture!=0xff
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%u"), MIBLEsensors[i].moisture);
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if (MIBLEsensors[i].moisture==0xff) HM10nullifyEndOfMQTT_DATA();
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MIBLEsensors[i].feature.fert){
|
||||
if(MIBLEsensors[i].eventType.fert || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
||||
if (MIBLEsensors[i].fertility!=0xffff) {
|
||||
if (MIBLEsensors[i].fertility!=0xffff
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) {
|
||||
ResponseAppend_P(PSTR(",\"Fertility\":%u"), MIBLEsensors[i].fertility);
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if (MIBLEsensors[i].fertility==0xffff) HM10nullifyEndOfMQTT_DATA();
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1491,12 +1817,19 @@ void HM10Show(bool json)
|
||||
}
|
||||
if (MIBLEsensors[i].feature.bat){
|
||||
if(MIBLEsensors[i].eventType.bat || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
||||
if (MIBLEsensors[i].bat != 0x00) { // this is the error code -> no battery
|
||||
if (MIBLEsensors[i].bat != 0x00
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
||(hass_mode!=-1)
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
) { // this is the error code -> no battery
|
||||
ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat);
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if (MIBLEsensors[i].bat == 0x00) HM10nullifyEndOfMQTT_DATA();
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HM10.option.showRSSI && HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi);
|
||||
if (HM10.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi);
|
||||
|
||||
|
||||
if(_positionCurlyBracket==strlen(TasmotaGlobal.mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step
|
||||
@ -1509,7 +1842,23 @@ void HM10Show(bool json)
|
||||
}
|
||||
}
|
||||
HM10.mode.triggeredTele = 0;
|
||||
|
||||
// add beacons
|
||||
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,\"TX\":%u}"),
|
||||
_idx,_MAC,_beacon.CID,_beacon.SVC,_beacon.UUID,_beacon.time,_beacon.RSSI,_beacon.TX);
|
||||
}
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
if(hass_mode==2){
|
||||
HM10.option.noSummary = _noSummarySave;
|
||||
HM10.option.minimalSummary = _minimalSummarySave;
|
||||
}
|
||||
#endif //USE_HOME_ASSISTANT
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
static uint16_t _page = 0;
|
||||
@ -1564,6 +1913,27 @@ void HM10Show(bool json)
|
||||
}
|
||||
if(MIBLEsensors.size()%HM10.perPage==0 && _page==MIBLEsensors.size()/HM10.perPage) _page=0;
|
||||
if(_page>MIBLEsensors.size()/HM10.perPage) _page=0;
|
||||
//always at the bottom of the page
|
||||
uint32_t _idx=0;
|
||||
if(HM10.mode.activeBeacon){
|
||||
WSContentSend_PD(HTTP_HM10_HL);
|
||||
char _sbeacon[] = "Beacon1";
|
||||
for (auto &_beacon : MIBLEbeacons){
|
||||
_idx++;
|
||||
if(!_beacon.active) continue;
|
||||
WSContentSend_PD(HTTP_HM10_HL);
|
||||
_sbeacon[6] = _idx + 0x30;
|
||||
char _MAC[18];
|
||||
ToHex_P(_beacon.MAC,6,_MAC,18,':');
|
||||
WSContentSend_PD(HTTP_HM10_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);
|
||||
if(_beacon.TX!=0) WSContentSend_PD(PSTR("{s}Beacon%u TX{m}%u{e}"),_idx, _beacon.TX);
|
||||
WSContentSend_PD(PSTR("{s}Beacon%u Time{m}%u seconds{e}"),_idx, _beacon.time);
|
||||
}
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
#ifdef USE_I2C
|
||||
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO)
|
||||
#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) || defined(USE_EZODO)
|
||||
#define USE_EZO
|
||||
#endif
|
||||
#if defined(USE_EZO)
|
||||
|
60
tasmota/xsns_78_ezodo.ino
Normal file
60
tasmota/xsns_78_ezodo.ino
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
xsns_78_ezodo.ino - EZO DO I2C DO sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Christopher Tremblay
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_EZODO
|
||||
|
||||
#define EZO_DO_READ_LATENCY 600
|
||||
|
||||
struct EZODO : public EZOStruct {
|
||||
EZODO(uint32_t addr) : EZOStruct(addr), DO(0) {}
|
||||
|
||||
virtual void ProcessMeasurement(void)
|
||||
{
|
||||
char data[D_EZO_MAX_BUF];
|
||||
|
||||
EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_DO_READ_LATENCY);
|
||||
DO = CharToFloat(data);
|
||||
}
|
||||
|
||||
virtual void Show(bool json, const char *name)
|
||||
{
|
||||
char str[8];
|
||||
dtostrfd(DO, 2, str);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_DO "\":%d}" ), name, str);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
else {
|
||||
WSContentSend_PD(HTTP_SNS_DO, name, str);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
static const char id[] PROGMEM;
|
||||
|
||||
private:
|
||||
float DO;
|
||||
};
|
||||
|
||||
const char EZODO::id[] PROGMEM = "D.O.";
|
||||
|
||||
#endif // USE_EZODO
|
||||
#endif // USE_I2C
|
@ -51,7 +51,11 @@ enum {
|
||||
|
||||
// The order of the EZO devices must map with the enum declared above
|
||||
const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||
EZOStruct::id, // "DO"
|
||||
#ifdef USE_EZODO
|
||||
EZODO::id,
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
#ifdef USE_EZOORP
|
||||
EZOORP::id,
|
||||
#else
|
||||
@ -67,7 +71,7 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
EZOStruct::id,
|
||||
EZOStruct::id, // <unnamed>
|
||||
#ifdef USE_EZORTD
|
||||
EZORTD::id,
|
||||
#else
|
||||
@ -89,14 +93,14 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
EZOStruct::id,
|
||||
EZOStruct::id, // <unnamed>
|
||||
#ifdef USE_EZOO2
|
||||
EZOO2::id,
|
||||
#else
|
||||
EZOStruct::id,
|
||||
#endif
|
||||
EZOStruct::id,
|
||||
EZOStruct::id,
|
||||
EZOStruct::id, // <unnamed>
|
||||
EZOStruct::id, // <unnamed>
|
||||
#ifdef USE_EZOHUM
|
||||
EZOHUM::id,
|
||||
#else
|
||||
@ -234,6 +238,9 @@ private:
|
||||
|
||||
// We use switch intead of virtual function to save RAM
|
||||
switch (j + EZO_ADDR_0) {
|
||||
#ifdef USE_EZODO
|
||||
CREATE_EZO_CLASS(DO)
|
||||
#endif
|
||||
#ifdef USE_EZOORP
|
||||
CREATE_EZO_CLASS(ORP)
|
||||
#endif
|
||||
|
@ -235,7 +235,7 @@ a_features = [[
|
||||
],[
|
||||
"USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC",
|
||||
"USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO",
|
||||
"","","","",
|
||||
"USE_EZODO","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
@ -268,7 +268,7 @@ else:
|
||||
obj = json.load(fp)
|
||||
|
||||
def StartDecode():
|
||||
print ("\n*** decode-status.py v20201101 by Theo Arends and Jacek Ziolkowski ***")
|
||||
print ("\n*** decode-status.py v20201102 by Theo Arends and Jacek Ziolkowski ***")
|
||||
|
||||
# print("Decoding\n{}".format(obj))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user