mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-27 20:56:35 +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_MCP9808 | - | - | - | - | - | - | - |
|
||||||
| USE_HP303B | - | - | - | - | - | - | - |
|
| USE_HP303B | - | - | - | - | - | - | - |
|
||||||
| USE_EZOCO2 | - | - | - | - | - | - | - |
|
| USE_EZOCO2 | - | - | - | - | - | - | - |
|
||||||
|
| USE_EZODO | - | - | - | - | - | - | - |
|
||||||
| USE_EZOEC | - | - | - | - | - | - | - |
|
| USE_EZOEC | - | - | - | - | - | - | - |
|
||||||
| USE_EZOFLO | - | - | - | - | - | - | - |
|
| USE_EZOFLO | - | - | - | - | - | - | - |
|
||||||
| USE_EZOHUM | - | - | - | - | - | - | - |
|
| 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 O2 sensors by Christopher Tremblay (#9619)
|
||||||
- Support for EZO PRS sensors by Christopher Tremblay (#9659)
|
- Support for EZO PRS sensors by Christopher Tremblay (#9659)
|
||||||
- Support for EZO FLO sensors by Christopher Tremblay (#9697)
|
- Support for EZO FLO sensors by Christopher Tremblay (#9697)
|
||||||
|
- Support for EZO DO sensors by Christopher Tremblay (#9707)
|
||||||
- Zigbee reduce battery drain (#9642)
|
- Zigbee reduce battery drain (#9642)
|
||||||
- Zigbee command ``ZbMap`` to describe Zigbee topology (#9651)
|
- Zigbee command ``ZbMap`` to describe Zigbee topology (#9651)
|
||||||
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
|
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
|
||||||
- Command ``Gpios 255`` to show all possible GPIO configurations
|
- Command ``Gpios 255`` to show all possible GPIO configurations
|
||||||
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
|
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
|
||||||
|
- HM10 Beacon support and refactoring by Christian Baars (#9702)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- PlatformIO library structure redesigned for compilation speed by Jason2866
|
- 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
|
### Fixed
|
||||||
- Rule Break not working as expected when ONCE is enabled (#9245)
|
- Rule Break not working as expected when ONCE is enabled (#9245)
|
||||||
- Rule expressions using mems corrupts character pool (#9301)
|
- 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
|
## [9.0.0.2] - 20201025
|
||||||
### Added
|
### 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)
|
- Support for EZO CO2 sensors by Christopher Tremblay (#9619)
|
||||||
- On ZigbeeBridge support for glowing led when permit join is active (#9581)
|
- On ZigbeeBridge support for glowing led when permit join is active (#9581)
|
||||||
- Support for PWM Dimmer multi-press and ledmask (#9584)
|
- 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
|
- Support for fixed output Hi or Lo GPIO selection
|
||||||
- ESP32 support for Wireless-Tag WT32-ETH01 (#9496)
|
- 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
|
### Changed
|
||||||
- Command ``Gpio17`` replaces command ``Adc``
|
- 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_EZOO2 | xsns_78 | EZOO2 | 0x61 - 0x70 | O2 sensor
|
||||||
55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor
|
55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor
|
||||||
55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter 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)
|
- TLS in binary tasmota-zbbridge (#9620)
|
||||||
- Zigbee reduce battery drain (#9642)
|
- Zigbee reduce battery drain (#9642)
|
||||||
- ESP32 support for Wireless-Tag WT32-ETH01 (#9496)
|
- 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
|
### Breaking Changed
|
||||||
- Redesigned ESP8266 GPIO internal representation in line with ESP32 changing ``Template`` layout too
|
- 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)
|
- Thermostat sensor status corruption regression from v8.5.0.1 (#9449)
|
||||||
- Telegram message decoding error regression from v8.5.0.1
|
- 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 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)
|
- Correct Energy period display shortly after midnight by gominoa (#9536)
|
||||||
- TuyaMcu energy display regression from v8.5.0.1 (#9547)
|
- TuyaMcu energy display regression from v8.5.0.1 (#9547)
|
||||||
- Tuyamcu dimmers MQTT topic (#9606)
|
- 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
|
* Lightweight String to Float, because atof() or strtof() takes 10KB
|
||||||
*
|
*
|
||||||
* To remove code, exponents are not parsed
|
* To remove code, exponents are not parsed
|
||||||
* (commented out below, just in case we need them after all)
|
* (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) {
|
while ((unsigned int)(*p - '0') < 10u) {
|
||||||
value = value*10 + (*p++ - '0');
|
value = value*10 + (*p++ - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p == '.' ) {
|
if (*p == '.' ) {
|
||||||
@ -335,7 +335,7 @@ float JsonParserToken::getFloat(float val) const {
|
|||||||
}
|
}
|
||||||
const char * JsonParserToken::getStr(const char * val) const {
|
const char * JsonParserToken::getStr(const char * val) const {
|
||||||
if (t->type == JSMN_INVALID) { return val; }
|
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;
|
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))) {
|
if ((!this->isValid()) || (nullptr == needle) || (0 == pgm_read_byte(needle))) {
|
||||||
return JsonParserToken(&token_bad);
|
return JsonParserToken(&token_bad);
|
||||||
}
|
}
|
||||||
|
|
||||||
String needle_s((const __FlashStringHelper *)needle);
|
String needle_s((const __FlashStringHelper *)needle);
|
||||||
needle_s.toLowerCase();
|
needle_s.toLowerCase();
|
||||||
|
|
||||||
|
292
platformio.ini
292
platformio.ini
@ -1,146 +1,146 @@
|
|||||||
; PlatformIO Project Configuration File
|
; PlatformIO Project Configuration File
|
||||||
;
|
;
|
||||||
; Build options: build flags, source filter, extra scripting
|
; Build options: build flags, source filter, extra scripting
|
||||||
; Upload options: custom port, speed and extra flags
|
; Upload options: custom port, speed and extra flags
|
||||||
; Library options: dependencies, extra library storages
|
; Library options: dependencies, extra library storages
|
||||||
;
|
;
|
||||||
; Please visit documentation for the other options and examples
|
; Please visit documentation for the other options and examples
|
||||||
; http://docs.platformio.org/en/stable/projectconf.html
|
; http://docs.platformio.org/en/stable/projectconf.html
|
||||||
|
|
||||||
|
|
||||||
; *** Tasmota build variant selection
|
; *** Tasmota build variant selection
|
||||||
[build_envs]
|
[build_envs]
|
||||||
default_envs =
|
default_envs =
|
||||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||||
; tasmota
|
; tasmota
|
||||||
; tasmota-ircustom
|
; tasmota-ircustom
|
||||||
; tasmota-minimal
|
; tasmota-minimal
|
||||||
; tasmota-lite
|
; tasmota-lite
|
||||||
; tasmota-knx
|
; tasmota-knx
|
||||||
; tasmota-sensors
|
; tasmota-sensors
|
||||||
; tasmota-display
|
; tasmota-display
|
||||||
; tasmota-zbbridge
|
; tasmota-zbbridge
|
||||||
; tasmota-ir
|
; tasmota-ir
|
||||||
; tasmota-BG
|
; tasmota-BG
|
||||||
; tasmota-BR
|
; tasmota-BR
|
||||||
; tasmota-CN
|
; tasmota-CN
|
||||||
; tasmota-CZ
|
; tasmota-CZ
|
||||||
; tasmota-DE
|
; tasmota-DE
|
||||||
; tasmota-ES
|
; tasmota-ES
|
||||||
; tasmota-FR
|
; tasmota-FR
|
||||||
; tasmota-GR
|
; tasmota-GR
|
||||||
; tasmota-HE
|
; tasmota-HE
|
||||||
; tasmota-HU
|
; tasmota-HU
|
||||||
; tasmota-IT
|
; tasmota-IT
|
||||||
; tasmota-KO
|
; tasmota-KO
|
||||||
; tasmota-NL
|
; tasmota-NL
|
||||||
; tasmota-PL
|
; tasmota-PL
|
||||||
; tasmota-PT
|
; tasmota-PT
|
||||||
; tasmota-RO
|
; tasmota-RO
|
||||||
; tasmota-RU
|
; tasmota-RU
|
||||||
; tasmota-SE
|
; tasmota-SE
|
||||||
; tasmota-SK
|
; tasmota-SK
|
||||||
; tasmota-TR
|
; tasmota-TR
|
||||||
; tasmota-TW
|
; tasmota-TW
|
||||||
; tasmota-UK
|
; tasmota-UK
|
||||||
; tasmota-VN
|
; tasmota-VN
|
||||||
;
|
;
|
||||||
; *** Selection for Tasmota ESP32 is done in platformio_tasmota32.ini
|
; *** Selection for Tasmota ESP32 is done in platformio_tasmota32.ini
|
||||||
;
|
;
|
||||||
; *** alternatively can be done in: platformio_override.ini
|
; *** alternatively can be done in: platformio_override.ini
|
||||||
; *** See example: platformio_override_sample.ini
|
; *** See example: platformio_override_sample.ini
|
||||||
; *********************************************************************
|
; *********************************************************************
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware
|
description = Provide ESP8266 / ESP32 based devices with Web, MQTT and OTA firmware
|
||||||
src_dir = tasmota
|
src_dir = tasmota
|
||||||
lib_dir = lib/default
|
lib_dir = lib/default
|
||||||
build_cache_dir = .cache
|
build_cache_dir = .cache
|
||||||
extra_configs = platformio_tasmota32.ini
|
extra_configs = platformio_tasmota32.ini
|
||||||
platformio_tasmota_env.ini
|
platformio_tasmota_env.ini
|
||||||
platformio_tasmota_env32.ini
|
platformio_tasmota_env32.ini
|
||||||
platformio_override.ini
|
platformio_override.ini
|
||||||
default_envs = ${build_envs.default_envs}
|
default_envs = ${build_envs.default_envs}
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp01_1m
|
board = esp01_1m
|
||||||
board_build.flash_mode = dout
|
board_build.flash_mode = dout
|
||||||
board_build.ldscript = eagle.flash.1m.ld
|
board_build.ldscript = eagle.flash.1m.ld
|
||||||
|
|
||||||
platform = ${core.platform}
|
platform = ${core.platform}
|
||||||
platform_packages = ${core.platform_packages}
|
platform_packages = ${core.platform_packages}
|
||||||
build_unflags = ${core.build_unflags}
|
build_unflags = ${core.build_unflags}
|
||||||
build_flags = ${core.build_flags}
|
build_flags = ${core.build_flags}
|
||||||
|
|
||||||
board_build.f_cpu = 80000000L
|
board_build.f_cpu = 80000000L
|
||||||
board_build.f_flash = 40000000L
|
board_build.f_flash = 40000000L
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||||
upload_resetmethod = nodemcu
|
upload_resetmethod = nodemcu
|
||||||
upload_port = COM5
|
upload_port = COM5
|
||||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||||
lib_ldf_mode = chain+
|
lib_ldf_mode = chain+
|
||||||
shared_libdeps_dir = lib
|
shared_libdeps_dir = lib
|
||||||
lib_extra_dirs =
|
lib_extra_dirs =
|
||||||
lib/lib_basic
|
lib/lib_basic
|
||||||
lib/lib_i2c
|
lib/lib_i2c
|
||||||
lib/lib_display
|
lib/lib_display
|
||||||
lib/lib_ssl
|
lib/lib_ssl
|
||||||
lib/lib_audio
|
lib/lib_audio
|
||||||
lib/lib_rf
|
lib/lib_rf
|
||||||
lib/lib_div
|
lib/lib_div
|
||||||
|
|
||||||
[scripts_defaults]
|
[scripts_defaults]
|
||||||
extra_scripts = pio/strip-floats.py
|
extra_scripts = pio/strip-floats.py
|
||||||
pio/name-firmware.py
|
pio/name-firmware.py
|
||||||
pio/gzip-firmware.py
|
pio/gzip-firmware.py
|
||||||
pio/override_copy.py
|
pio/override_copy.py
|
||||||
|
|
||||||
[esp_defaults]
|
[esp_defaults]
|
||||||
; *** remove undesired all warnings
|
; *** remove undesired all warnings
|
||||||
build_unflags = -Wall
|
build_unflags = -Wall
|
||||||
-Wdeprecated-declarations
|
-Wdeprecated-declarations
|
||||||
build_flags = -Wno-deprecated-declarations
|
build_flags = -Wno-deprecated-declarations
|
||||||
-D_IR_ENABLE_DEFAULT_=false
|
-D_IR_ENABLE_DEFAULT_=false
|
||||||
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
|
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
|
||||||
-DDECODE_RC5=true -DSEND_RC5=true -DDECODE_RC6=true -DSEND_RC6=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
|
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
|
||||||
|
; *********************************************************************
|
||||||
; *********************************************************************
|
; *** Use custom settings from file user_config_override.h
|
||||||
; *** Use custom settings from file user_config_override.h
|
-DUSE_CONFIG_OVERRIDE
|
||||||
-DUSE_CONFIG_OVERRIDE
|
; *********************************************************************
|
||||||
; *********************************************************************
|
|
||||||
|
|
||||||
[esp82xx_defaults]
|
[esp82xx_defaults]
|
||||||
build_flags = ${esp_defaults.build_flags}
|
build_flags = ${esp_defaults.build_flags}
|
||||||
-Wl,-Map,firmware.map
|
-Wl,-Map,firmware.map
|
||||||
-D CORE_DEBUG_LEVEL=0
|
-D CORE_DEBUG_LEVEL=0
|
||||||
-D NDEBUG
|
-D NDEBUG
|
||||||
-mtarget-align
|
-mtarget-align
|
||||||
-DFP_IN_IROM
|
-DFP_IN_IROM
|
||||||
-DBEARSSL_SSL_BASIC
|
-DBEARSSL_SSL_BASIC
|
||||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||||
; lwIP 2 - Higher Bandwidth no Features
|
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
; VTABLES in Flash
|
||||||
; VTABLES in Flash
|
-DVTABLES_IN_FLASH
|
||||||
-DVTABLES_IN_FLASH
|
; remove the 4-bytes alignment for PSTR()
|
||||||
; remove the 4-bytes alignment for PSTR()
|
-DPSTR_ALIGN=1
|
||||||
-DPSTR_ALIGN=1
|
; restrict to minimal mime-types
|
||||||
; restrict to minimal mime-types
|
-DMIMETYPE_MINIMAL
|
||||||
-DMIMETYPE_MINIMAL
|
|
||||||
|
[irremoteesp_full]
|
||||||
[irremoteesp_full]
|
build_flags = -DUSE_IR_REMOTE_FULL
|
||||||
build_flags = -DUSE_IR_REMOTE_FULL
|
-U_IR_ENABLE_DEFAULT_
|
||||||
-U_IR_ENABLE_DEFAULT_
|
-DDECODE_PRONTO=false -DSEND_PRONTO=false
|
||||||
-DDECODE_PRONTO=false -DSEND_PRONTO=false
|
|
||||||
|
|
||||||
[core]
|
[core]
|
||||||
; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4
|
; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4
|
||||||
platform = espressif8266@2.6.2
|
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
|
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
|
platformio/tool-esptool @ 1.413.0
|
||||||
build_unflags = ${esp_defaults.build_unflags}
|
build_unflags = ${esp_defaults.build_unflags}
|
||||||
build_flags = ${esp82xx_defaults.build_flags}
|
build_flags = ${esp82xx_defaults.build_flags}
|
||||||
|
@ -1,200 +1,234 @@
|
|||||||
; *** Example PlatformIO Project Configuration Override File ***
|
; *** Example PlatformIO Project Configuration Override File ***
|
||||||
; *** Changes done here override settings in platformio.ini ***
|
; *** Changes done here override settings in platformio.ini ***
|
||||||
;
|
;
|
||||||
; *****************************************************************
|
; *****************************************************************
|
||||||
; *** to activate rename this file to platformio_override.ini ***
|
; *** to activate rename this file to platformio_override.ini ***
|
||||||
; *****************************************************************
|
; *****************************************************************
|
||||||
;
|
;
|
||||||
; Please visit documentation for the options and examples
|
; Please visit documentation for the options and examples
|
||||||
; http://docs.platformio.org/en/stable/projectconf.html
|
; http://docs.platformio.org/en/stable/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
; For best Gitpod performance remove the ";" in the next line. Needed Platformio files are cached and installed at first run
|
; For best Gitpod performance remove the ";" in the next line. Needed Platformio files are cached and installed at first run
|
||||||
;core_dir = .platformio
|
;core_dir = .platformio
|
||||||
extra_configs = platformio_tasmota_cenv.ini
|
extra_configs = platformio_tasmota_cenv.ini
|
||||||
|
|
||||||
; *** Build/upload environment
|
; *** Build/upload environment
|
||||||
default_envs =
|
default_envs =
|
||||||
; *** Uncomment the line(s) below to select version(s)
|
; *** Uncomment the line(s) below to select version(s)
|
||||||
tasmota
|
tasmota
|
||||||
; tasmota-debug
|
; tasmota-debug
|
||||||
; tasmota-ircustom
|
; tasmota-ircustom
|
||||||
; tasmota-minimal
|
; tasmota-minimal
|
||||||
; tasmota-lite
|
; tasmota-lite
|
||||||
; tasmota-knx
|
; tasmota-knx
|
||||||
; tasmota-sensors
|
; tasmota-sensors
|
||||||
; tasmota-display
|
; tasmota-display
|
||||||
; tasmota-zbbridge
|
; tasmota-zbbridge
|
||||||
; tasmota-ir
|
; tasmota-ir
|
||||||
; tasmota32
|
; tasmota32
|
||||||
; tasmota32-webcam
|
; tasmota32-webcam
|
||||||
; tasmota32-minimal
|
; tasmota32-minimal
|
||||||
; tasmota32-lite
|
; tasmota32-lite
|
||||||
; tasmota32-knx
|
; tasmota32-knx
|
||||||
; tasmota32-sensors
|
; tasmota32-sensors
|
||||||
; tasmota32-display
|
; tasmota32-display
|
||||||
; tasmota32-ir
|
; tasmota32-ir
|
||||||
; tasmota32-ircustom
|
; tasmota32-ircustom
|
||||||
|
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
platform_packages = ${core.platform_packages}
|
platform_packages = ${core.platform_packages}
|
||||||
build_unflags = ${core.build_unflags}
|
build_unflags = ${core.build_unflags}
|
||||||
build_flags = ${core.build_flags}
|
build_flags = ${core.build_flags}
|
||||||
; *** Optional Debug messages
|
; *** Optional Debug messages
|
||||||
; -DDEBUG_TASMOTA_CORE
|
; -DDEBUG_TASMOTA_CORE
|
||||||
; -DDEBUG_TASMOTA_DRIVER
|
; -DDEBUG_TASMOTA_DRIVER
|
||||||
; -DDEBUG_TASMOTA_SENSOR
|
; -DDEBUG_TASMOTA_SENSOR
|
||||||
|
|
||||||
; set CPU frequency to 80MHz (default) or 160MHz
|
; set CPU frequency to 80MHz (default) or 160MHz
|
||||||
;board_build.f_cpu = 160000000L
|
;board_build.f_cpu = 160000000L
|
||||||
|
|
||||||
; set Flash chip frequency to 40MHz (default), 20MHz, 26Mhz, 80Mhz
|
; set Flash chip frequency to 40MHz (default), 20MHz, 26Mhz, 80Mhz
|
||||||
;board_build.f_flash = 20000000L
|
;board_build.f_flash = 20000000L
|
||||||
;board_build.f_flash = 26000000L
|
;board_build.f_flash = 26000000L
|
||||||
;board_build.f_flash = 80000000L
|
;board_build.f_flash = 80000000L
|
||||||
|
|
||||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||||
upload_port = COM5
|
upload_port = COM5
|
||||||
|
|
||||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||||
; pio/obj-dump.py
|
; pio/obj-dump.py
|
||||||
|
|
||||||
; *** Upload file to OTA server using SCP
|
; *** Upload file to OTA server using SCP
|
||||||
;upload_port = user@host:/path
|
;upload_port = user@host:/path
|
||||||
;extra_scripts = ${scripts_defaults.extra_scripts}
|
;extra_scripts = ${scripts_defaults.extra_scripts}
|
||||||
; pio/strip-floats.py
|
; pio/strip-floats.py
|
||||||
; pio/sftp-uploader.py
|
; pio/sftp-uploader.py
|
||||||
|
|
||||||
; *** Upload file to OTA server in folder api/arduino using HTTP
|
; *** Upload file to OTA server in folder api/arduino using HTTP
|
||||||
;upload_port = domus1:80/api/upload-arduino.php
|
;upload_port = domus1:80/api/upload-arduino.php
|
||||||
;extra_scripts = ${scripts_defaults.extra_scripts}
|
;extra_scripts = ${scripts_defaults.extra_scripts}
|
||||||
; pio/strip-floats.py
|
; pio/strip-floats.py
|
||||||
; pio/http-uploader.py
|
; pio/http-uploader.py
|
||||||
|
|
||||||
lib_ldf_mode = chain+
|
lib_extra_dirs = ${library.lib_extra_dirs}
|
||||||
shared_libdeps_dir = lib
|
|
||||||
|
[core]
|
||||||
; *** Library disable / enable for variant Tasmota. Disable reduces compile time
|
; Activate only (one set) if you want to override the standard core defined in platformio.ini !!!
|
||||||
; *** !!! Disabling needed libs will generate compile errors !!!
|
|
||||||
; *** The resulting firmware will NOT be different if you leave all libs enabled
|
;platform_packages = ${tasmota_stage.platform_packages}
|
||||||
; *** Disabling by putting a ";" in front of the lib name
|
;build_unflags = ${tasmota_stage.build_unflags}
|
||||||
; *** If you dont know what it is all about, do not change
|
;build_flags = ${tasmota_stage.build_flags}
|
||||||
lib_extra_dirs =
|
|
||||||
; *** Only disabled for Tasmota minimal and Tasmota light. For all other variants needed!
|
;platform_packages = ${core_stage.platform_packages}
|
||||||
lib/lib_basic
|
;build_unflags = ${core_stage.build_unflags}
|
||||||
; **** I2C devices. Most sensors. Disable only if you dont have ANY I2C device enabled
|
;build_flags = ${core_stage.build_flags}
|
||||||
lib/lib_i2c
|
|
||||||
; *** Displays. Disable if you dont have any Display activated
|
|
||||||
lib/lib_display
|
[tasmota_stage]
|
||||||
; *** Bear SSL and base64. Disable if you dont have SSL or TLS activated
|
; *** Esp8266 core for Arduino version Tasmota stage (PR7231 and Backport PR7514)
|
||||||
lib/lib_ssl
|
platform_packages = framework-arduinoespressif8266@https://github.com/Jason2866/Arduino.git#2.7.4.4
|
||||||
; *** Audio needs a lot of time to compile. Mostly not used functions. Recommended to disable
|
build_unflags = ${esp_defaults.build_unflags}
|
||||||
lib/lib_audio
|
build_flags = ${esp82xx_defaults.build_flags}
|
||||||
; *** RF 433 stuff (not RF Bridge). Recommended to disable
|
|
||||||
lib/lib_rf
|
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||||
; *** Mostly not used functions. Recommended to disable
|
; NONOSDK221
|
||||||
lib/lib_div
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||||
|
; NONOSDK22x_190313
|
||||||
[core]
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||||
; Activate only (one set) if you want to override the standard core defined in platformio.ini !!!
|
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||||
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||||
;platform_packages = ${tasmota_stage.platform_packages}
|
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||||
;build_unflags = ${tasmota_stage.build_unflags}
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||||
;build_flags = ${tasmota_stage.build_flags}
|
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||||
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||||
;platform_packages = ${core_stage.platform_packages}
|
; NONOSDK3V0 (known issues)
|
||||||
;build_unflags = ${core_stage.build_unflags}
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||||
;build_flags = ${core_stage.build_flags}
|
; lwIP 1.4
|
||||||
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||||
|
; lwIP 2 - Low Memory
|
||||||
[tasmota_stage]
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||||
; *** Esp8266 core for Arduino version Tasmota stage (PR7231 and Backport PR7514)
|
; lwIP 2 - Higher Bandwidth
|
||||||
platform_packages = framework-arduinoespressif8266@https://github.com/Jason2866/Arduino.git#2.7.4.4
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||||
build_unflags = ${esp_defaults.build_unflags}
|
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||||
build_flags = ${esp82xx_defaults.build_flags}
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||||
|
; VTABLES in Heap
|
||||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
; -DVTABLES_IN_DRAM
|
||||||
; NONOSDK221
|
; VTABLES in IRAM
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
; -DVTABLES_IN_IRAM
|
||||||
; NONOSDK22x_190313
|
; Exception code in firmware /needs much space!
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
; -fexceptions
|
||||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
; -lstdc++-exc
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
|
||||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
[core_stage]
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
; *** Esp8266 core version. Tasmota stage or Arduino stage version. Built with GCC 10.1 toolchain
|
||||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
platform_packages = framework-arduinoespressif8266 @ https://github.com/Jason2866/platform-espressif8266/releases/download/2.9.1/framework-arduinoespressif8266-3.20901.0.tar.gz
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
;framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||||
; NONOSDK3V0 (known issues)
|
toolchain-xtensa @ ~2.100100.0
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
build_unflags = ${esp_defaults.build_unflags}
|
||||||
; lwIP 1.4
|
-Wswitch-unreachable
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
build_flags = ${esp82xx_defaults.build_flags}
|
||||||
; lwIP 2 - Low Memory
|
-Wno-switch-unreachable
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
|
||||||
; lwIP 2 - Higher Bandwidth
|
; *********** Alternative Options, enable only if you know exactly what you do ********
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
; NONOSDK221
|
||||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
; NONOSDK22x_190313
|
||||||
; VTABLES in Heap
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||||
; -DVTABLES_IN_DRAM
|
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||||
; VTABLES in IRAM
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||||
; -DVTABLES_IN_IRAM
|
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||||
; Exception code in firmware /needs much space!
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||||
; -fexceptions
|
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
||||||
; -lstdc++-exc
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||||
|
; NONOSDK3V0 (known issues)
|
||||||
[core_stage]
|
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||||
; *** Esp8266 core version. Tasmota stage or Arduino stage version. Built with GCC 10.1 toolchain
|
; lwIP 2 - Low Memory
|
||||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/Jason2866/platform-espressif8266/releases/download/2.9.1/framework-arduinoespressif8266-3.20901.0.tar.gz
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||||
;framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
; lwIP 2 - Higher Bandwidth
|
||||||
toolchain-xtensa @ ~2.100100.0
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||||
build_unflags = ${esp_defaults.build_unflags}
|
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||||
-Wswitch-unreachable
|
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||||
build_flags = ${esp82xx_defaults.build_flags}
|
; VTABLES in Heap
|
||||||
-Wno-switch-unreachable
|
; -DVTABLES_IN_DRAM
|
||||||
|
; VTABLES in IRAM
|
||||||
; *********** Alternative Options, enable only if you know exactly what you do ********
|
; -DVTABLES_IN_IRAM
|
||||||
; NONOSDK221
|
; Exception code in firmware /needs much space!
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
; -fexceptions
|
||||||
; NONOSDK22x_190313
|
; -lstdc++-exc
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
|
||||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
[common32]
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
platform = ${core32.platform}
|
||||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
platform_packages = ${core32.platform_packages}
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
build_unflags = ${core32.build_unflags}
|
||||||
; NONOSDK22x_191122 = 2.2.1+119-dev(a58da79)
|
build_flags = ${core32.build_flags}
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
board = esp32dev
|
||||||
; NONOSDK3V0 (known issues)
|
board_build.ldscript = esp32_out.ld
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||||
; lwIP 2 - Low Memory
|
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
board_build.f_flash = ${common.board_build.f_flash}
|
||||||
; lwIP 2 - Higher Bandwidth
|
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
monitor_speed = ${common.monitor_speed}
|
||||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
upload_port = ${common.upload_port}
|
||||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
upload_resetmethod = ${common.upload_resetmethod}
|
||||||
; VTABLES in Heap
|
upload_speed = 921600
|
||||||
; -DVTABLES_IN_DRAM
|
extra_scripts = ${common.extra_scripts}
|
||||||
; VTABLES in IRAM
|
lib_extra_dirs = ${library.lib_extra_dirs}
|
||||||
; -DVTABLES_IN_IRAM
|
; *** ESP32 lib. ALWAYS needed for ESP32 !!!
|
||||||
; Exception code in firmware /needs much space!
|
lib/libesp32
|
||||||
; -fexceptions
|
[core32]
|
||||||
; -lstdc++-exc
|
; Activate Stage Core32 by removing ";" in next 4 lines, if you want to override the standard core32
|
||||||
|
;platform = ${core32_stage.platform}
|
||||||
[core32]
|
;platform_packages = ${core32_stage.platform_packages}
|
||||||
; Activate Stage Core32 by removing ";" in next lines, if you want to override the standard core32
|
;build_unflags = ${core32_stage.build_unflags}
|
||||||
;platform_packages = ${core32_stage.platform_packages}
|
;build_flags = ${core32_stage.build_flags}
|
||||||
;build_flags = ${core32_stage.build_flags}
|
|
||||||
|
|
||||||
[core32_stage]
|
[core32_stage]
|
||||||
platform_packages = tool-esptoolpy@1.20800.0
|
platform = espressif32@2.0.0
|
||||||
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#f7fb00632e04d74a7890a77fa7dbbb8ae572e866
|
platform_packages = tool-esptoolpy@1.20800.0
|
||||||
|
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#f7fb00632e04d74a7890a77fa7dbbb8ae572e866
|
||||||
build_flags = ${esp32_defaults.build_flags}
|
build_unflags = ${esp32_defaults.build_unflags}
|
||||||
-D ESP32_STAGE=true
|
build_flags = ${esp32_defaults.build_flags}
|
||||||
|
-D ESP32_STAGE=true
|
||||||
; *** Debug version used for PlatformIO Home Project Inspection
|
|
||||||
[env:tasmota-debug]
|
[library]
|
||||||
build_type = debug
|
lib_ldf_mode = chain+
|
||||||
build_unflags = ${esp_defaults.build_unflags}
|
shared_libdeps_dir = lib
|
||||||
build_flags = ${esp82xx_defaults.build_flags}
|
; *** Library disable / enable for variant Tasmota(32). Disable reduces compile time
|
||||||
-Wstack-usage=300
|
; *** !!! 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 ***
|
; *** BETA ESP32 Tasmota version ***
|
||||||
; *** expect the unexpected. Some features not working!!! ***
|
; *** expect the unexpected. Some features not working!!! ***
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
|
|
||||||
; *** Tasmota build variant selection
|
; *** Tasmota build variant selection
|
||||||
default_envs = ${build_envs.default_envs}
|
default_envs = ${build_envs.default_envs}
|
||||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||||
; tasmota32
|
; tasmota32
|
||||||
; tasmota32-webcam
|
; tasmota32-webcam
|
||||||
; tasmota32-minimal
|
; tasmota32-minimal
|
||||||
; tasmota32-lite
|
; tasmota32-lite
|
||||||
; tasmota32-knx
|
; tasmota32-knx
|
||||||
; tasmota32-sensors
|
; tasmota32-sensors
|
||||||
; tasmota32-display
|
; tasmota32-display
|
||||||
; tasmota32-ir
|
; tasmota32-ir
|
||||||
; tasmota32-ircustom
|
; tasmota32-ircustom
|
||||||
; tasmota32-BG
|
; tasmota32-BG
|
||||||
; tasmota32-BR
|
; tasmota32-BR
|
||||||
; tasmota32-CN
|
; tasmota32-CN
|
||||||
; tasmota32-CZ
|
; tasmota32-CZ
|
||||||
; tasmota32-DE
|
; tasmota32-DE
|
||||||
; tasmota32-ES
|
; tasmota32-ES
|
||||||
; tasmota32-FR
|
; tasmota32-FR
|
||||||
; tasmota32-GR
|
; tasmota32-GR
|
||||||
; tasmota32-HE
|
; tasmota32-HE
|
||||||
; tasmota32-HU
|
; tasmota32-HU
|
||||||
; tasmota32-IT
|
; tasmota32-IT
|
||||||
; tasmota32-KO
|
; tasmota32-KO
|
||||||
; tasmota32-NL
|
; tasmota32-NL
|
||||||
; tasmota32-PL
|
; tasmota32-PL
|
||||||
; tasmota32-PT
|
; tasmota32-PT
|
||||||
; tasmota32-RO
|
; tasmota32-RO
|
||||||
; tasmota32-RU
|
; tasmota32-RU
|
||||||
; tasmota32-SE
|
; tasmota32-SE
|
||||||
; tasmota32-SK
|
; tasmota32-SK
|
||||||
; tasmota32-TR
|
; tasmota32-TR
|
||||||
; tasmota32-TW
|
; tasmota32-TW
|
||||||
; tasmota32-UK
|
; tasmota32-UK
|
||||||
; tasmota32-VN
|
; tasmota32-VN
|
||||||
|
|
||||||
[common32]
|
[common32]
|
||||||
board = esp32dev
|
platform = ${core32.platform}
|
||||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
platform_packages = ${core32.platform_packages}
|
||||||
board_build.ldscript = esp32_out.ld
|
build_unflags = ${core32.build_unflags}
|
||||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
build_flags = ${core32.build_flags}
|
||||||
|
board = esp32dev
|
||||||
platform = ${core32.platform}
|
board_build.ldscript = esp32_out.ld
|
||||||
platform_packages = ${core32.platform_packages}
|
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||||
build_unflags = ${esp_defaults.build_unflags}
|
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||||
-Wpointer-arith
|
board_build.f_flash = ${common.board_build.f_flash}
|
||||||
build_flags = ${core32.build_flags}
|
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||||
|
monitor_speed = ${common.monitor_speed}
|
||||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
upload_port = ${common.upload_port}
|
||||||
board_build.f_flash = ${common.board_build.f_flash}
|
upload_resetmethod = ${common.upload_resetmethod}
|
||||||
monitor_speed = ${common.monitor_speed}
|
upload_speed = 921600
|
||||||
upload_port = ${common.upload_port}
|
extra_scripts = ${common.extra_scripts}
|
||||||
upload_resetmethod = ${common.upload_resetmethod}
|
lib_ldf_mode = chain+
|
||||||
upload_speed = 921600
|
shared_libdeps_dir = lib
|
||||||
extra_scripts = ${common.extra_scripts}
|
lib_extra_dirs =
|
||||||
|
lib/libesp32
|
||||||
lib_ldf_mode = chain+
|
lib/lib_basic
|
||||||
shared_libdeps_dir = lib
|
lib/lib_i2c
|
||||||
lib_extra_dirs =
|
lib/lib_display
|
||||||
lib/libesp32
|
lib/lib_ssl
|
||||||
lib/lib_basic
|
lib/lib_audio
|
||||||
lib/lib_i2c
|
lib/lib_rf
|
||||||
lib/lib_display
|
lib/lib_div
|
||||||
lib/lib_ssl
|
|
||||||
lib/lib_audio
|
[esp32_defaults]
|
||||||
lib/lib_rf
|
build_unflags = ${esp_defaults.build_unflags}
|
||||||
lib/lib_div
|
-Wpointer-arith
|
||||||
|
build_flags = ${esp_defaults.build_flags}
|
||||||
[esp32_defaults]
|
-D CORE_DEBUG_LEVEL=0
|
||||||
build_flags = ${esp_defaults.build_flags}
|
-D BUFFER_LENGTH=128
|
||||||
-D CORE_DEBUG_LEVEL=0
|
-D MQTT_MAX_PACKET_SIZE=1200
|
||||||
-D BUFFER_LENGTH=128
|
-D uint32=uint32_t
|
||||||
-D MQTT_MAX_PACKET_SIZE=1200
|
-D uint16=uint16_t
|
||||||
-D uint32=uint32_t
|
-D uint8=uint8_t
|
||||||
-D uint16=uint16_t
|
-D sint8_t=int8_t
|
||||||
-D uint8=uint8_t
|
-D sint32_t=int32_t
|
||||||
-D sint8_t=int8_t
|
-D sint16_t=int16_t
|
||||||
-D sint32_t=int32_t
|
-D memcpy_P=memcpy
|
||||||
-D sint16_t=int16_t
|
-D memcmp_P=memcmp
|
||||||
-D memcpy_P=memcpy
|
|
||||||
-D memcmp_P=memcmp
|
|
||||||
|
[core32]
|
||||||
[core32]
|
platform = espressif32@2.0.0
|
||||||
platform = espressif32@2.0.0
|
platform_packages = tool-esptoolpy@1.20800.0
|
||||||
platform_packages = tool-esptoolpy@1.20800.0
|
platformio/framework-arduinoespressif32 @ 3.10004.201016
|
||||||
platformio/framework-arduinoespressif32 @ 3.10004.201016
|
build_unflags = ${esp32_defaults.build_unflags}
|
||||||
build_flags = ${esp32_defaults.build_flags}
|
build_flags = ${esp32_defaults.build_flags}
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#define D_JSON_DARKNESS "Darkness"
|
#define D_JSON_DARKNESS "Darkness"
|
||||||
#define D_JSON_DATA "Data"
|
#define D_JSON_DATA "Data"
|
||||||
#define D_JSON_DEWPOINT "DewPoint"
|
#define D_JSON_DEWPOINT "DewPoint"
|
||||||
|
#define D_JSON_DO "DisolvedOxygen"
|
||||||
#define D_JSON_DISTANCE "Distance"
|
#define D_JSON_DISTANCE "Distance"
|
||||||
#define D_JSON_DNSSERVER "DNSServer"
|
#define D_JSON_DNSSERVER "DNSServer"
|
||||||
#define D_JSON_DONE "Done"
|
#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_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_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_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_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Забранен"
|
#define D_DISABLED "Забранен"
|
||||||
#define D_DISTANCE "Разстояние"
|
#define D_DISTANCE "Разстояние"
|
||||||
#define D_DNS_SERVER "DNS Сървър"
|
#define D_DNS_SERVER "DNS Сървър"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Изпълнено"
|
#define D_DONE "Изпълнено"
|
||||||
#define D_DST_TIME "Лятно време"
|
#define D_DST_TIME "Лятно време"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Zablokováno"
|
#define D_DISABLED "Zablokováno"
|
||||||
#define D_DISTANCE "Distance"
|
#define D_DISTANCE "Distance"
|
||||||
#define D_DNS_SERVER "Server DNS"
|
#define D_DNS_SERVER "Server DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Provedeno"
|
#define D_DONE "Provedeno"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "deaktiviert"
|
#define D_DISABLED "deaktiviert"
|
||||||
#define D_DISTANCE "Abstand"
|
#define D_DISTANCE "Abstand"
|
||||||
#define D_DNS_SERVER "DNS-Server"
|
#define D_DNS_SERVER "DNS-Server"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "erledigt"
|
#define D_DONE "erledigt"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Ανενεργό"
|
#define D_DISABLED "Ανενεργό"
|
||||||
#define D_DISTANCE "Απόσταση"
|
#define D_DISTANCE "Απόσταση"
|
||||||
#define D_DNS_SERVER "Διακομιστής DNS"
|
#define D_DNS_SERVER "Διακομιστής DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Ολοκληρώθηκε"
|
#define D_DONE "Ολοκληρώθηκε"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Disabled"
|
#define D_DISABLED "Disabled"
|
||||||
#define D_DISTANCE "Distance"
|
#define D_DISTANCE "Distance"
|
||||||
#define D_DNS_SERVER "DNS Server"
|
#define D_DNS_SERVER "DNS Server"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Done"
|
#define D_DONE "Done"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Deshabilitado"
|
#define D_DISABLED "Deshabilitado"
|
||||||
#define D_DISTANCE "Distancia"
|
#define D_DISTANCE "Distancia"
|
||||||
#define D_DNS_SERVER "Servidor DNS"
|
#define D_DNS_SERVER "Servidor DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Listo"
|
#define D_DONE "Listo"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
#define D_DISABLED "Désactivé"
|
#define D_DISABLED "Désactivé"
|
||||||
#define D_DISTANCE "Distance"
|
#define D_DISTANCE "Distance"
|
||||||
#define D_DNS_SERVER "Serveur DNS"
|
#define D_DNS_SERVER "Serveur DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Terminé"
|
#define D_DONE "Terminé"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "מבוטל"
|
#define D_DISABLED "מבוטל"
|
||||||
#define D_DISTANCE "מרחק"
|
#define D_DISTANCE "מרחק"
|
||||||
#define D_DNS_SERVER "DNS שרת"
|
#define D_DNS_SERVER "DNS שרת"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "סיים"
|
#define D_DONE "סיים"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Letiltva"
|
#define D_DISABLED "Letiltva"
|
||||||
#define D_DISTANCE "Távolság"
|
#define D_DISTANCE "Távolság"
|
||||||
#define D_DNS_SERVER "DNS szerver"
|
#define D_DNS_SERVER "DNS szerver"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Kész"
|
#define D_DONE "Kész"
|
||||||
#define D_DST_TIME "nyári idő"
|
#define D_DST_TIME "nyári idő"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Disabilitato/a"
|
#define D_DISABLED "Disabilitato/a"
|
||||||
#define D_DISTANCE "Distanza"
|
#define D_DISTANCE "Distanza"
|
||||||
#define D_DNS_SERVER "Server DNS"
|
#define D_DNS_SERVER "Server DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Completato"
|
#define D_DONE "Completato"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "사용안함"
|
#define D_DISABLED "사용안함"
|
||||||
#define D_DISTANCE "거리"
|
#define D_DISTANCE "거리"
|
||||||
#define D_DNS_SERVER "DNS 서버"
|
#define D_DNS_SERVER "DNS 서버"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "완료"
|
#define D_DONE "완료"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||||
* Use online command Prefix to translate cmnd, stat and tele.
|
* 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)
|
//#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_DISABLED "Uitgeschakeld"
|
||||||
#define D_DISTANCE "Afstand"
|
#define D_DISTANCE "Afstand"
|
||||||
#define D_DNS_SERVER "DNS Server"
|
#define D_DNS_SERVER "DNS Server"
|
||||||
|
#define D_DO "Opgelost zuurstof"
|
||||||
#define D_DONE "Klaar"
|
#define D_DONE "Klaar"
|
||||||
#define D_DST_TIME "ZT"
|
#define D_DST_TIME "ZT"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Wyłączony"
|
#define D_DISABLED "Wyłączony"
|
||||||
#define D_DISTANCE "Odległość"
|
#define D_DISTANCE "Odległość"
|
||||||
#define D_DNS_SERVER "Serwer DNS"
|
#define D_DNS_SERVER "Serwer DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Wykonane"
|
#define D_DONE "Wykonane"
|
||||||
#define D_DST_TIME "Czas DST"
|
#define D_DST_TIME "Czas DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Desabilitado"
|
#define D_DISABLED "Desabilitado"
|
||||||
#define D_DISTANCE "Distância"
|
#define D_DISTANCE "Distância"
|
||||||
#define D_DNS_SERVER "Servidor DNS"
|
#define D_DNS_SERVER "Servidor DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Concluído"
|
#define D_DONE "Concluído"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Disabilitado"
|
#define D_DISABLED "Disabilitado"
|
||||||
#define D_DISTANCE "Distância"
|
#define D_DISTANCE "Distância"
|
||||||
#define D_DNS_SERVER "Servidor DNS"
|
#define D_DNS_SERVER "Servidor DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Concluído"
|
#define D_DONE "Concluído"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Dezactivat"
|
#define D_DISABLED "Dezactivat"
|
||||||
#define D_DISTANCE "Distanță"
|
#define D_DISTANCE "Distanță"
|
||||||
#define D_DNS_SERVER "Server DNS"
|
#define D_DNS_SERVER "Server DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Terminat"
|
#define D_DONE "Terminat"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Блокирован"
|
#define D_DISABLED "Блокирован"
|
||||||
#define D_DISTANCE "Distance"
|
#define D_DISTANCE "Distance"
|
||||||
#define D_DNS_SERVER "DNS Сервер"
|
#define D_DNS_SERVER "DNS Сервер"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Выполнено"
|
#define D_DONE "Выполнено"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
#define D_DISABLED "Zablokované"
|
#define D_DISABLED "Zablokované"
|
||||||
#define D_DISTANCE "Vzdialenosť"
|
#define D_DISTANCE "Vzdialenosť"
|
||||||
#define D_DNS_SERVER "Server DNS"
|
#define D_DNS_SERVER "Server DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Hotovo"
|
#define D_DONE "Hotovo"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Inaktiverad"
|
#define D_DISABLED "Inaktiverad"
|
||||||
#define D_DISTANCE "Distans"
|
#define D_DISTANCE "Distans"
|
||||||
#define D_DNS_SERVER "DNS-server"
|
#define D_DNS_SERVER "DNS-server"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Gjort"
|
#define D_DONE "Gjort"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Etkin Değil"
|
#define D_DISABLED "Etkin Değil"
|
||||||
#define D_DISTANCE "Mesage"
|
#define D_DISTANCE "Mesage"
|
||||||
#define D_DNS_SERVER "DNS Sunucu"
|
#define D_DNS_SERVER "DNS Sunucu"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Tamam"
|
#define D_DONE "Tamam"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Вимкнено"
|
#define D_DISABLED "Вимкнено"
|
||||||
#define D_DISTANCE "Відстань"
|
#define D_DISTANCE "Відстань"
|
||||||
#define D_DNS_SERVER "Сервер DNS"
|
#define D_DNS_SERVER "Сервер DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Виконано"
|
#define D_DONE "Виконано"
|
||||||
#define D_DST_TIME "Літній час"
|
#define D_DST_TIME "Літній час"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "Vô hiệu hóa"
|
#define D_DISABLED "Vô hiệu hóa"
|
||||||
#define D_DISTANCE "Khoảng cách"
|
#define D_DISTANCE "Khoảng cách"
|
||||||
#define D_DNS_SERVER "Máy chủ DNS"
|
#define D_DNS_SERVER "Máy chủ DNS"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "Hoàn thành"
|
#define D_DONE "Hoàn thành"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "禁用"
|
#define D_DISABLED "禁用"
|
||||||
#define D_DISTANCE "距离"
|
#define D_DISTANCE "距离"
|
||||||
#define D_DNS_SERVER "DNS服务器"
|
#define D_DNS_SERVER "DNS服务器"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "完成"
|
#define D_DONE "完成"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#define D_EC "EC"
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
#define D_DISABLED "已停用"
|
#define D_DISABLED "已停用"
|
||||||
#define D_DISTANCE "距離"
|
#define D_DISTANCE "距離"
|
||||||
#define D_DNS_SERVER "DNS伺服器"
|
#define D_DNS_SERVER "DNS伺服器"
|
||||||
|
#define D_DO "Disolved Oxygen"
|
||||||
#define D_DONE "完成"
|
#define D_DONE "完成"
|
||||||
#define D_DST_TIME "DST"
|
#define D_DST_TIME "DST"
|
||||||
#define D_EC "EC"
|
#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_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_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_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 // Add I2C Display Support (+2k code)
|
||||||
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
#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)
|
#if defined(USE_I2C) && defined(USE_EZOFLO)
|
||||||
feature7 |= 0x00000080;
|
feature7 |= 0x00000080;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(USE_I2C) && defined(USE_EZODO)
|
||||||
// feature7 |= 0x00000100;
|
feature7 |= 0x00000100;
|
||||||
|
#endif
|
||||||
// feature7 |= 0x00000200;
|
// feature7 |= 0x00000200;
|
||||||
// feature7 |= 0x00000400;
|
// feature7 |= 0x00000400;
|
||||||
// feature7 |= 0x00000800;
|
// feature7 |= 0x00000800;
|
||||||
|
@ -490,7 +490,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
|
|||||||
result = XdrvRulesProcess();
|
result = XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
#ifdef USE_PWM_DIMMER
|
#ifdef USE_PWM_DIMMER
|
||||||
if (PWM_DIMMER == TasmotaGlobal.module_type && !result) {
|
if (PWM_DIMMER != TasmotaGlobal.module_type || !result) {
|
||||||
#endif // USE_PWM_DIMMER
|
#endif // USE_PWM_DIMMER
|
||||||
int32_t payload_save = XdrvMailbox.payload;
|
int32_t payload_save = XdrvMailbox.payload;
|
||||||
XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device;
|
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_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_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_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_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
|
||||||
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
|
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
|
||||||
|
@ -67,6 +67,8 @@
|
|||||||
|
|
||||||
#define XDRV_10 10
|
#define XDRV_10 10
|
||||||
|
|
||||||
|
//#define DEBUG_RULES
|
||||||
|
|
||||||
#include <unishox.h>
|
#include <unishox.h>
|
||||||
|
|
||||||
#define D_CMND_RULE "Rule"
|
#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_name = "INA219#CURRENT"
|
||||||
// rule_param = "0.100" or "%VAR1%"
|
// 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 };
|
char rule_svalue[80] = { 0 };
|
||||||
float rule_value = 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
|
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());
|
JsonParser parser((char*)buf.c_str());
|
||||||
JsonParserObject obj = parser.getRootObject();
|
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"
|
while ((pos = rule_name.indexOf("#")) > 0) { // "SUBTYPE1#SUBTYPE2#CURRENT"
|
||||||
subtype = rule_name.substring(0, pos);
|
subtype = rule_name.substring(0, pos);
|
||||||
obj = obj[subtype.c_str()].getObject();
|
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);
|
rule_name = rule_name.substring(pos +1);
|
||||||
if (i++ > 10) { return false; } // Abandon possible loop
|
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()];
|
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;
|
const char* str_value;
|
||||||
if (rule_name_idx) {
|
if (rule_name_idx) {
|
||||||
if (val.isArray()) {
|
if (val.isArray()) {
|
||||||
@ -531,11 +535,14 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
|
|||||||
str_value = val.getStr();
|
str_value = val.getStr();
|
||||||
}
|
}
|
||||||
} else {
|
} 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"),
|
#ifdef DEBUG_RULES
|
||||||
// rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none");
|
AddLog_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%
|
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; }
|
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 (bitRead(Settings.rule_once, rule_set)) {
|
||||||
if (match) { // Only allow match state changes
|
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;
|
return match;
|
||||||
}
|
}
|
||||||
@ -663,7 +670,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
|||||||
|
|
||||||
delay(0); // Prohibit possible loop software watchdog
|
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);
|
String rules = GetRule(rule_set);
|
||||||
|
|
||||||
@ -696,7 +703,9 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
|||||||
Rules.event_value = "";
|
Rules.event_value = "";
|
||||||
String event = event_saved;
|
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 (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
|
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 getReachable(void) const { return reachable; }
|
||||||
inline bool getPower(uint8_t ep =0) const;
|
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
|
// Add an endpoint to a device
|
||||||
bool addEndpoint(uint8_t endpoint);
|
bool addEndpoint(uint8_t endpoint);
|
||||||
void clearEndpoints(void);
|
void clearEndpoints(void);
|
||||||
@ -552,6 +555,8 @@ public:
|
|||||||
void setModelId(const char * str);
|
void setModelId(const char * str);
|
||||||
void setFriendlyName(const char * str);
|
void setFriendlyName(const char * str);
|
||||||
|
|
||||||
|
void setLastSeenNow(void);
|
||||||
|
|
||||||
// dump device attributes to ZbData
|
// dump device attributes to ZbData
|
||||||
void toAttributes(Z_attribute_list & attr_list) const;
|
void toAttributes(Z_attribute_list & attr_list) const;
|
||||||
|
|
||||||
@ -568,30 +573,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns: dirty flag, did we change the value of the object
|
void setLightChannels(int8_t channels);
|
||||||
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;
|
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static void setStringAttribute(char*& attr, const char * str);
|
static void setStringAttribute(char*& attr, const char * str);
|
||||||
@ -655,9 +638,9 @@ public:
|
|||||||
// - 0x0000 = not found
|
// - 0x0000 = not found
|
||||||
// - BAD_SHORTADDR = bad parameter
|
// - BAD_SHORTADDR = bad parameter
|
||||||
// - 0x<shortaddr> = the device's short address
|
// - 0x<shortaddr> = the device's short address
|
||||||
uint16_t isKnownLongAddr(uint64_t longaddr) const;
|
Z_Device & isKnownLongAddrDevice(uint64_t longaddr) const;
|
||||||
uint16_t isKnownIndex(uint32_t index) const;
|
Z_Device & isKnownIndexDevice(uint32_t index) const;
|
||||||
uint16_t isKnownFriendlyName(const char * name) const;
|
Z_Device & isKnownFriendlyNameDevice(const char * name) const;
|
||||||
|
|
||||||
Z_Device & findShortAddr(uint16_t shortaddr);
|
Z_Device & findShortAddr(uint16_t shortaddr);
|
||||||
const Z_Device & findShortAddr(uint16_t shortaddr) const;
|
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 & 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
|
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
|
// check if a device was found or if it's the fallback device
|
||||||
inline bool foundDevice(const Z_Device & device) const {
|
inline bool foundDevice(const Z_Device & device) const { return device.valid(); }
|
||||||
return (&device != &device_unk);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t findFriendlyName(const char * name) const;
|
int32_t findFriendlyName(const char * name) const;
|
||||||
uint64_t getDeviceLongAddr(uint16_t shortaddr) const;
|
uint64_t getDeviceLongAddr(uint16_t shortaddr) const;
|
||||||
@ -689,26 +670,15 @@ public:
|
|||||||
return findShortAddr(shortaddr).manufacturerId;
|
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)
|
// get next sequence number for (increment at each all)
|
||||||
uint8_t getNextSeqNumber(uint16_t shortaddr);
|
uint8_t getNextSeqNumber(uint16_t shortaddr);
|
||||||
|
|
||||||
// Dump json
|
// Dump json
|
||||||
static void addLightState(Z_attribute_list & attr_list, const Z_Data_Light & light);
|
static String dumpLightState(const Z_Device & device);
|
||||||
String dumpLightState(uint16_t shortaddr) const;
|
String dumpDevice(uint32_t dump_mode, const Z_Device & device) const;
|
||||||
String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const;
|
static String dumpSingleDevice(uint32_t dump_mode, const Z_Device & device);
|
||||||
int32_t deviceRestore(JsonParserObject json);
|
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
|
// Hue support
|
||||||
int8_t getHueBulbtype(uint16_t shortaddr) const ;
|
int8_t getHueBulbtype(uint16_t shortaddr) const ;
|
||||||
void hideHueBulb(uint16_t shortaddr, bool hidden);
|
void hideHueBulb(uint16_t shortaddr, bool hidden);
|
||||||
@ -731,14 +701,7 @@ public:
|
|||||||
size_t devicesSize(void) const {
|
size_t devicesSize(void) const {
|
||||||
return _devices.length();
|
return _devices.length();
|
||||||
}
|
}
|
||||||
const Z_Device & devicesAt(size_t i) const {
|
Z_Device & devicesAt(size_t i) const;
|
||||||
const Z_Device * devp = _devices.at(i);
|
|
||||||
if (devp) {
|
|
||||||
return *devp;
|
|
||||||
} else {
|
|
||||||
return device_unk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove device from list
|
// Remove device from list
|
||||||
bool removeDevice(uint16_t shortaddr);
|
bool removeDevice(uint16_t shortaddr);
|
||||||
@ -746,10 +709,10 @@ public:
|
|||||||
// Mark data as 'dirty' and requiring to save in Flash
|
// Mark data as 'dirty' and requiring to save in Flash
|
||||||
void dirty(void);
|
void dirty(void);
|
||||||
void clean(void); // avoid writing to flash the last changes
|
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
|
// 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:
|
private:
|
||||||
LList<Z_Device> _devices; // list of devices
|
LList<Z_Device> _devices; // list of devices
|
||||||
@ -757,10 +720,6 @@ private:
|
|||||||
uint32_t _saveTimer = 0;
|
uint32_t _saveTimer = 0;
|
||||||
uint8_t _seqNumber = 0; // global seqNumber if device is unknown
|
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;
|
//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
|
// 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);
|
Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0);
|
||||||
@ -772,6 +731,10 @@ private:
|
|||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
Z_Devices zigbee_devices = Z_Devices();
|
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
|
// Local coordinator information
|
||||||
uint64_t localIEEEAddr = 0;
|
uint64_t localIEEEAddr = 0;
|
||||||
uint16_t localShortAddr = 0;
|
uint16_t localShortAddr = 0;
|
||||||
|
@ -23,12 +23,21 @@
|
|||||||
* Implementation
|
* 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
|
// 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.
|
// entry with same shortaddr or longaddr exists.
|
||||||
//
|
//
|
||||||
Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) {
|
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();
|
Z_Device & device = _devices.addToLast();
|
||||||
device.shortaddr = shortaddr;
|
device.shortaddr = shortaddr;
|
||||||
device.longaddr = longaddr;
|
device.longaddr = longaddr;
|
||||||
@ -56,7 +65,7 @@ Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) {
|
|||||||
for (auto & elem : _devices) {
|
for (auto & elem : _devices) {
|
||||||
if (elem.shortaddr == shortaddr) { return elem; }
|
if (elem.shortaddr == shortaddr) { return elem; }
|
||||||
}
|
}
|
||||||
return (Z_Device&) device_unk;
|
return device_unk;
|
||||||
}
|
}
|
||||||
const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const {
|
const Z_Device & Z_Devices::findShortAddr(uint16_t shortaddr) const {
|
||||||
for (const auto & elem : _devices) {
|
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
|
// index in _devices of entry, -1 if not found
|
||||||
//
|
//
|
||||||
Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) {
|
Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) {
|
||||||
if (!longaddr) { return (Z_Device&) device_unk; }
|
if (!longaddr) { return device_unk; }
|
||||||
for (auto &elem : _devices) {
|
for (auto &elem : _devices) {
|
||||||
if (elem.longaddr == longaddr) { return elem; }
|
if (elem.longaddr == longaddr) { return elem; }
|
||||||
}
|
}
|
||||||
return (Z_Device&) device_unk;
|
return device_unk;
|
||||||
}
|
}
|
||||||
const Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) const {
|
const Z_Device & Z_Devices::findLongAddr(uint64_t longaddr) const {
|
||||||
if (!longaddr) { return device_unk; }
|
if (!longaddr) { return device_unk; }
|
||||||
@ -109,32 +118,25 @@ int32_t Z_Devices::findFriendlyName(const char * name) const {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const {
|
Z_Device & Z_Devices::isKnownLongAddrDevice(uint64_t longaddr) const {
|
||||||
const Z_Device & device = findLongAddr(longaddr);
|
return (Z_Device &) findLongAddr(longaddr);
|
||||||
if (foundDevice(device)) {
|
|
||||||
return device.shortaddr; // can be zero, if not yet registered
|
|
||||||
} else {
|
|
||||||
return BAD_SHORTADDR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Z_Devices::isKnownIndex(uint32_t index) const {
|
Z_Device & Z_Devices::isKnownIndexDevice(uint32_t index) const {
|
||||||
if (index < devicesSize()) {
|
if (index < devicesSize()) {
|
||||||
const Z_Device & device = devicesAt(index);
|
return devicesAt(index);
|
||||||
return device.shortaddr;
|
|
||||||
} else {
|
} else {
|
||||||
return BAD_SHORTADDR;
|
return device_unk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Z_Devices::isKnownFriendlyName(const char * name) const {
|
Z_Device & Z_Devices::isKnownFriendlyNameDevice(const char * name) const {
|
||||||
if ((!name) || (0 == strlen(name))) { return BAD_SHORTADDR; } // Error
|
if ((!name) || (0 == strlen(name))) { return device_unk; } // Error
|
||||||
int32_t found = findFriendlyName(name);
|
int32_t found = findFriendlyName(name);
|
||||||
if (found >= 0) {
|
if (found >= 0) {
|
||||||
const Z_Device & device = devicesAt(found);
|
return devicesAt(found);
|
||||||
return device.shortaddr; // can be zero, if not yet registered
|
|
||||||
} else {
|
} 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
|
// We have a seen a shortaddr on the network, get the corresponding device object
|
||||||
//
|
//
|
||||||
Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) {
|
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);
|
Z_Device & device = findShortAddr(shortaddr);
|
||||||
if (foundDevice(device)) {
|
if (foundDevice(device)) {
|
||||||
return 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)
|
// find the Device object by its longaddr (unique key if not null)
|
||||||
Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) {
|
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);
|
Z_Device & device = findLongAddr(longaddr);
|
||||||
if (foundDevice(device)) {
|
if (foundDevice(device)) {
|
||||||
return device;
|
return device;
|
||||||
@ -211,7 +213,7 @@ Z_Device & Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) {
|
|||||||
if ((BAD_SHORTADDR != shortaddr) || longaddr) {
|
if ((BAD_SHORTADDR != shortaddr) || longaddr) {
|
||||||
return createDeviceEntry(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);
|
setStringAttribute(friendlyName, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Z_Device::setLastSeenNow(void) {
|
||||||
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; }
|
|
||||||
// Only update time if after 2020-01-01 0000.
|
// Only update time if after 2020-01-01 0000.
|
||||||
// Fixes issue where zigbee device pings before WiFi/NTP has set utc_time
|
// 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
|
// to the correct time, and "last seen" calculations are based on the
|
||||||
// pre-corrected last_seen time and the since-corrected utc_time.
|
// pre-corrected last_seen time and the since-corrected utc_time.
|
||||||
if (Rtc.utc_time < 1577836800) { return; }
|
if (Rtc.utc_time < 1577836800) { return; }
|
||||||
getShortAddr(shortaddr).last_seen = Rtc.utc_time;
|
last_seen = Rtc.utc_time;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Z_Devices::setBatteryPercent(uint16_t shortaddr, uint8_t bp) {
|
|
||||||
getShortAddr(shortaddr).batterypercent = bp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the next sequance number for the device, or use the global seq number if device is unknown
|
// 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
|
// returns: dirty flag, did we change the value of the object
|
||||||
void Z_Devices::setLightProfile(uint16_t shortaddr, uint8_t light_profile) {
|
void Z_Device::setLightChannels(int8_t channels) {
|
||||||
Z_Device &device = getShortAddr(shortaddr);
|
if (channels >= 0) {
|
||||||
if (device.setLightChannels(light_profile)) {
|
// retrieve of create light object
|
||||||
dirty();
|
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 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)) {
|
if (0x00 == (light_profile & 0xF0)) {
|
||||||
return (light_profile & 0x07);
|
return (light_profile & 0x07);
|
||||||
} else {
|
} else {
|
||||||
@ -575,57 +571,56 @@ void Z_Devices::clean(void) {
|
|||||||
// - a long address starting with "0x", example: 0x7CB03EBB0A0292DD
|
// - a long address starting with "0x", example: 0x7CB03EBB0A0292DD
|
||||||
// - a number 0..99, the index number in ZigbeeStatus
|
// - a number 0..99, the index number in ZigbeeStatus
|
||||||
// - a friendly name, between quotes, example: "Room_Temp"
|
// - a friendly name, between quotes, example: "Room_Temp"
|
||||||
uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const {
|
Z_Device & Z_Devices::parseDeviceFromName(const char * param, bool short_must_be_known) {
|
||||||
if (nullptr == param) { return BAD_SHORTADDR; }
|
if (nullptr == param) { return device_unk; }
|
||||||
size_t param_len = strlen(param);
|
size_t param_len = strlen(param);
|
||||||
char dataBuf[param_len + 1];
|
char dataBuf[param_len + 1];
|
||||||
strcpy(dataBuf, param);
|
strcpy(dataBuf, param);
|
||||||
RemoveSpace(dataBuf);
|
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
|
// simple number 0..99
|
||||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 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'))) {
|
} else if ((dataBuf[0] == '0') && ((dataBuf[1] == 'x') || (dataBuf[1] == 'X'))) {
|
||||||
// starts with 0x
|
// starts with 0x
|
||||||
if (strlen(dataBuf) < 18) {
|
if (strlen(dataBuf) < 18) {
|
||||||
// expect a short address
|
// expect a short address
|
||||||
shortaddr = strtoull(dataBuf, nullptr, 0);
|
uint16_t shortaddr = strtoull(dataBuf, nullptr, 0);
|
||||||
if (short_must_be_known) {
|
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 {
|
} else {
|
||||||
// expect a long address
|
// expect a long address
|
||||||
uint64_t longaddr = strtoull(dataBuf, nullptr, 0);
|
uint64_t longaddr = strtoull(dataBuf, nullptr, 0);
|
||||||
shortaddr = zigbee_devices.isKnownLongAddr(longaddr);
|
return isKnownLongAddrDevice(longaddr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// expect a Friendly Name
|
// expect a Friendly Name
|
||||||
shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf);
|
return isKnownFriendlyNameDevice(dataBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shortaddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the tracked status for a light
|
// 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;
|
Z_attribute_list attr_list;
|
||||||
char hex[8];
|
char hex[8];
|
||||||
|
|
||||||
const Z_Device & device = findShortAddr(shortaddr);
|
const char * fname = device.friendlyName;
|
||||||
const char * fname = getFriendlyName(shortaddr);
|
|
||||||
bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with 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);
|
attr_list.addAttribute(F(D_JSON_ZIGBEE_DEVICE)).setStr(hex);
|
||||||
if (fname) {
|
if (fname) {
|
||||||
attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(fname);
|
attr_list.addAttribute(F(D_JSON_ZIGBEE_NAME)).setStr(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundDevice(device)) {
|
if (device.valid()) {
|
||||||
// dump all known values
|
// dump all known values
|
||||||
attr_list.addAttribute(F("Reachable")).setBool(device.getReachable());
|
attr_list.addAttribute(F("Reachable")).setBool(device.getReachable());
|
||||||
if (device.validPower()) { attr_list.addAttribute(F("Power")).setUInt(device.getPower()); }
|
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
|
// Dump the internal memory of Zigbee devices
|
||||||
// Mode = 1: simple dump of devices addresses
|
// Mode = 1: simple dump of devices addresses
|
||||||
// Mode = 2: simple dump of devices addresses and names, endpoints, light
|
// 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;
|
JsonGeneratorArray json_arr;
|
||||||
|
|
||||||
for (const auto & device : _devices) {
|
if (&device == nullptr) {
|
||||||
uint16_t shortaddr = device.shortaddr;
|
if (dump_mode < 2) {
|
||||||
char hex[22];
|
// dump light mode for all devices
|
||||||
|
for (const auto & device2 : _devices) {
|
||||||
// ignore non-current device, if device specified
|
json_arr.addStrRaw(dumpSingleDevice(dump_mode, device2).c_str());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (2 <= dump_mode) {
|
json_arr.addStrRaw(dumpSingleDevice(dump_mode, device).c_str());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return json_arr.toString();
|
return json_arr.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version) {
|
|||||||
|
|
||||||
// Hue bulbtype - if present
|
// Hue bulbtype - if present
|
||||||
if (1 == version) {
|
if (1 == version) {
|
||||||
zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d));
|
device.setLightChannels(buf_d.get8(d));
|
||||||
d++;
|
d++;
|
||||||
} else if (2 == version) {
|
} else if (2 == version) {
|
||||||
// v2 parser
|
// v2 parser
|
||||||
|
@ -1853,7 +1853,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
|
|||||||
switch (ccccaaaa) {
|
switch (ccccaaaa) {
|
||||||
case 0x00000004: device.setManufId(attr.getStr()); break;
|
case 0x00000004: device.setManufId(attr.getStr()); break;
|
||||||
case 0x00000005: device.setModelId(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 0x00060000:
|
||||||
case 0x00068000: device.setPower(attr.getBool(), src_ep); break;
|
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
|
// 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) {
|
void Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||||
if (BAD_SHORTADDR != shortaddr) {
|
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
|
// log the packet details
|
||||||
zcl_received.log();
|
zcl_received.log();
|
||||||
|
|
||||||
zigbee_devices.setLQI(srcaddr, linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI
|
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||||
zigbee_devices.setLastSeenNow(srcaddr);
|
if (srcaddr != localShortAddr) {
|
||||||
|
device.setLQI(linkquality != 0xFF ? linkquality : 0xFE); // EFR32 has a different scale for LQI
|
||||||
|
device.setLastSeenNow();
|
||||||
|
}
|
||||||
|
|
||||||
char shortaddr[8];
|
char shortaddr[8];
|
||||||
snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr);
|
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
|
// 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.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) {
|
if (defer_attributes) {
|
||||||
// Prepare for publish
|
// Prepare for publish
|
||||||
@ -1615,8 +1618,11 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) {
|
|||||||
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
|
if ((0x0000 == profileid) && (0x00 == srcendpoint)) {
|
||||||
// ZDO request
|
// ZDO request
|
||||||
// Report LQI
|
// Report LQI
|
||||||
zigbee_devices.setLQI(srcaddr, linkquality);
|
Z_Device & device = zigbee_devices.getShortAddr(srcaddr);
|
||||||
zigbee_devices.setLastSeenNow(srcaddr);
|
if (srcaddr != localShortAddr) {
|
||||||
|
device.setLQI(linkquality);
|
||||||
|
device.setLastSeenNow();
|
||||||
|
}
|
||||||
// Since ZDO messages start with a sequence number, we skip it
|
// Since ZDO messages start with a sequence number, we skip it
|
||||||
// but we add the source address in the last 2 bytes
|
// but we add the source address in the last 2 bytes
|
||||||
SBuffer zdo_buf(buf.get8(20) - 1 + 2);
|
SBuffer zdo_buf(buf.get8(20) - 1 + 2);
|
||||||
|
@ -683,7 +683,7 @@ void CmndZbSend(void) {
|
|||||||
// parse "Device" and "Group"
|
// parse "Device" and "Group"
|
||||||
JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)];
|
JsonParserToken val_device = root[PSTR(D_CMND_ZIGBEE_DEVICE)];
|
||||||
if (val_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) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
||||||
}
|
}
|
||||||
if (BAD_SHORTADDR == device) { // if not found, check if we have a group
|
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 endpoint = 0x00; // 0x00 is invalid for the src endpoint
|
||||||
uint8_t toendpoint = 0x01; // default dest endpoint to 0x01
|
uint8_t toendpoint = 0x01; // default dest endpoint to 0x01
|
||||||
uint16_t toGroup = 0x0000; // group address
|
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
|
uint32_t group = 0xFFFFFFFF; // 16 bits values, otherwise 0xFFFFFFFF is unspecified
|
||||||
|
|
||||||
// Information about source device: "Device", "Endpoint", "Cluster"
|
// Information about source device: "Device", "Endpoint", "Cluster"
|
||||||
// - the source endpoint must have a known IEEE address
|
// - the source endpoint must have a known IEEE address
|
||||||
srcDevice = zigbee_devices.parseDeviceParam(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr));
|
const Z_Device & src_device = zigbee_devices.parseDeviceFromName(root.getStr(PSTR(D_CMND_ZIGBEE_DEVICE), nullptr), true);
|
||||||
if (BAD_SHORTADDR == srcDevice) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
|
if (!src_device.valid()) { ResponseCmndChar_P(PSTR("Unknown source device")); return; }
|
||||||
// check if IEEE address is known
|
// 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; }
|
if (0 == srcLongAddr) { ResponseCmndChar_P(PSTR("Unknown source IEEE address")); return; }
|
||||||
// look for source endpoint
|
// look for source endpoint
|
||||||
endpoint = root.getUInt(PSTR(D_CMND_ZIGBEE_ENDPOINT), 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
|
// look for source cluster
|
||||||
JsonParserToken val_cluster = root[PSTR(D_CMND_ZIGBEE_CLUSTER)];
|
JsonParserToken val_cluster = root[PSTR(D_CMND_ZIGBEE_CLUSTER)];
|
||||||
if (val_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 no target is specified, we default to coordinator 0x0000
|
||||||
if ((!to_group) && (!dst_device)) {
|
if ((!to_group) && (!dst_device)) {
|
||||||
dstDevice = 0x0000;
|
dstDevice = 0x0000;
|
||||||
|
dstLongAddr = localIEEEAddr;
|
||||||
|
toendpoint = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dst_device) || (BAD_SHORTADDR != dstDevice)) {
|
if (dst_device) {
|
||||||
if (BAD_SHORTADDR == dstDevice) {
|
const Z_Device & dstDevice = zigbee_devices.parseDeviceFromName(dst_device.getStr(nullptr), true);
|
||||||
dstDevice = zigbee_devices.parseDeviceParam(dst_device.getStr(nullptr));
|
if (!dstDevice.valid()) { ResponseCmndChar_P(PSTR("Unknown dest device")); return; }
|
||||||
if (BAD_SHORTADDR == dstDevice) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; }
|
dstLongAddr = dstDevice.longaddr;
|
||||||
}
|
}
|
||||||
if (0x0000 == dstDevice) {
|
|
||||||
dstLongAddr = localIEEEAddr;
|
|
||||||
} else {
|
|
||||||
dstLongAddr = zigbee_devices.getDeviceLongAddr(dstDevice);
|
|
||||||
}
|
|
||||||
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
|
|
||||||
|
|
||||||
|
if (!to_group) {
|
||||||
|
if (0 == dstLongAddr) { ResponseCmndChar_P(PSTR("Unknown dest IEEE address")); return; }
|
||||||
toendpoint = root.getUInt(PSTR("ToEndpoint"), toendpoint);
|
toendpoint = root.getUInt(PSTR("ToEndpoint"), toendpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we don't have conflicting parameters
|
// 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 && dst_device) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; }
|
||||||
if (!to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; }
|
|
||||||
|
|
||||||
#ifdef USE_ZIGBEE_ZNP
|
#ifdef USE_ZIGBEE_ZNP
|
||||||
SBuffer buf(34);
|
SBuffer buf(34);
|
||||||
@ -891,7 +888,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
|||||||
buf.add64(srcLongAddr);
|
buf.add64(srcLongAddr);
|
||||||
buf.add8(endpoint);
|
buf.add8(endpoint);
|
||||||
buf.add16(cluster);
|
buf.add16(cluster);
|
||||||
if (dstLongAddr) {
|
if (!to_group) {
|
||||||
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
||||||
buf.add64(dstLongAddr);
|
buf.add64(dstLongAddr);
|
||||||
buf.add8(toendpoint);
|
buf.add8(toendpoint);
|
||||||
@ -910,7 +907,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
|||||||
buf.add64(srcLongAddr);
|
buf.add64(srcLongAddr);
|
||||||
buf.add8(endpoint);
|
buf.add8(endpoint);
|
||||||
buf.add16(cluster);
|
buf.add16(cluster);
|
||||||
if (dstLongAddr) {
|
if (!to_group) {
|
||||||
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT
|
||||||
buf.add64(dstLongAddr);
|
buf.add64(dstLongAddr);
|
||||||
buf.add8(toendpoint);
|
buf.add8(toendpoint);
|
||||||
@ -941,7 +938,7 @@ void CmndZbUnbind(void) {
|
|||||||
|
|
||||||
void CmndZbBindState_or_Map(uint16_t zdo_cmd) {
|
void CmndZbBindState_or_Map(uint16_t zdo_cmd) {
|
||||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
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; }
|
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
uint8_t index = XdrvMailbox.index - 1; // change default 1 to 0
|
uint8_t index = XdrvMailbox.index - 1; // change default 1 to 0
|
||||||
|
|
||||||
@ -1002,7 +999,7 @@ void CmndZbProbe(void) {
|
|||||||
//
|
//
|
||||||
void CmndZbProbeOrPing(boolean probe) {
|
void CmndZbProbeOrPing(boolean probe) {
|
||||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
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; }
|
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
// everything is good, we can send the command
|
// everything is good, we can send the command
|
||||||
@ -1034,19 +1031,19 @@ void CmndZbName(void) {
|
|||||||
|
|
||||||
// check if parameters contain a comma ','
|
// check if parameters contain a comma ','
|
||||||
char *p;
|
char *p;
|
||||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
char *str = strtok_r(XdrvMailbox.data, ",", &p);
|
||||||
|
|
||||||
// parse first part, <device_id>
|
// parse first part, <device_id>
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, false); // it's the only case where we create a new device
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
const char * friendlyName = device.friendlyName;
|
||||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName : "");
|
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), device.shortaddr, friendlyName ? friendlyName : "");
|
||||||
} else {
|
} else {
|
||||||
if (strlen(p) > 32) { p[32] = 0x00; } // truncate to 32 chars max
|
if (strlen(p) > 32) { p[32] = 0x00; } // truncate to 32 chars max
|
||||||
zigbee_devices.getShortAddr(shortaddr).setFriendlyName(p);
|
device.setFriendlyName(p);
|
||||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, 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 ','
|
// check if parameters contain a comma ','
|
||||||
char *p;
|
char *p;
|
||||||
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
char *str = strtok_r(XdrvMailbox.data, ",", &p);
|
||||||
|
|
||||||
// parse first part, <device_id>
|
// parse first part, <device_id>
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
const char * modelId = zigbee_devices.getModelId(shortaddr);
|
const char * modelId = device.modelId;
|
||||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, modelId ? modelId : "");
|
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), device.shortaddr, modelId ? modelId : "");
|
||||||
} else {
|
} else {
|
||||||
zigbee_devices.getShortAddr(shortaddr).setModelId(p);
|
device.setModelId(p);
|
||||||
Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, 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);
|
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||||
|
|
||||||
// parse first part, <device_id>
|
// parse first part, <device_id>
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
int8_t bulbtype = strtol(p, nullptr, 10);
|
int8_t bulbtype = strtol(p, nullptr, 10);
|
||||||
if (bulbtype > 5) { bulbtype = 5; }
|
if (bulbtype > 5) { bulbtype = 5; }
|
||||||
if (bulbtype < -1) { bulbtype = -1; }
|
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());
|
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));
|
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);
|
char *str = strtok_r(XdrvMailbox.data, ", ", &p);
|
||||||
|
|
||||||
// parse first part, <device_id>
|
// parse first part, <device_id>
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
Z_Device & device = zigbee_devices.getShortAddr(shortaddr);
|
|
||||||
|
|
||||||
int8_t occupancy_time = -1;
|
int8_t occupancy_time = -1;
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -1170,11 +1165,11 @@ void CmndZbOccupancy(void) {
|
|||||||
//
|
//
|
||||||
void CmndZbForget(void) {
|
void CmndZbForget(void) {
|
||||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true); // in case of short_addr, it must be already registered
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
|
|
||||||
// everything is good, we can send the command
|
// everything is good, we can send the command
|
||||||
if (zigbee_devices.removeDevice(shortaddr)) {
|
if (zigbee_devices.removeDevice(device.shortaddr)) {
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
} else {
|
} else {
|
||||||
ResponseCmndChar_P(PSTR("Unknown device"));
|
ResponseCmndChar_P(PSTR("Unknown device"));
|
||||||
@ -1369,12 +1364,17 @@ void ZigbeeGlowPermitJoinLight(void) {
|
|||||||
void CmndZbStatus(void) {
|
void CmndZbStatus(void) {
|
||||||
if (ZigbeeSerial) {
|
if (ZigbeeSerial) {
|
||||||
if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
|
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 (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());
|
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) {
|
for (auto device_name : root) {
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(device_name.getStr());
|
Z_Device & device = zigbee_devices.parseDeviceFromName(device_name.getStr(), true);
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
Z_Device & device = zigbee_devices.getShortAddr(shortaddr);
|
|
||||||
JsonParserObject inner_data = device_name.getValue().getObject();
|
JsonParserObject inner_data = device_name.getValue().getObject();
|
||||||
if (inner_data) {
|
if (inner_data) {
|
||||||
if (!parseDeviceInnerData(device, inner_data)) {
|
if (!parseDeviceInnerData(device, inner_data)) {
|
||||||
@ -1518,9 +1517,8 @@ void CmndZbData(void) {
|
|||||||
// non-JSON, export current data
|
// non-JSON, export current data
|
||||||
// ZbData 0x1234
|
// ZbData 0x1234
|
||||||
// ZbData Device_Name
|
// ZbData Device_Name
|
||||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
|
Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, true);
|
||||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
if (!device.valid()) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||||
const Z_Device & device = zigbee_devices.findShortAddr(shortaddr);
|
|
||||||
|
|
||||||
Z_attribute_list attr_data;
|
Z_attribute_list attr_data;
|
||||||
|
|
||||||
@ -1568,7 +1566,7 @@ void CmndZbData(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char hex[8];
|
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());
|
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 COMBO3b 12
|
||||||
#define WGS_COMBO 13
|
#define WGS_COMBO 13
|
||||||
#define EBZD_G 14
|
#define EBZD_G 14
|
||||||
|
#define SML_NO_OP 15
|
||||||
|
|
||||||
// select this meter
|
// 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
|
#if METER==EHZ161_0
|
||||||
@ -1662,6 +1674,7 @@ void SML_Show(boolean json) {
|
|||||||
//char b_mqtt_data[MESSZ];
|
//char b_mqtt_data[MESSZ];
|
||||||
//b_mqtt_data[0]=0;
|
//b_mqtt_data[0]=0;
|
||||||
|
|
||||||
|
if (!meters_used) return;
|
||||||
|
|
||||||
int8_t lastmind=((*mp)&7)-1;
|
int8_t lastmind=((*mp)&7)-1;
|
||||||
if (lastmind<0 || lastmind>=meters_used) lastmind=0;
|
if (lastmind<0 || lastmind>=meters_used) lastmind=0;
|
||||||
@ -1794,7 +1807,7 @@ void SML_Show(boolean json) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
if (json && !TasmotaGlobal.tele_period) {
|
if (json && !TasmotaGlobal.tele_period) {
|
||||||
char str[16];
|
char str[16];
|
||||||
@ -1806,7 +1819,7 @@ void SML_Show(boolean json) {
|
|||||||
DomoticzSensor(DZ_CURRENT, str); // Current
|
DomoticzSensor(DZ_CURRENT, str); // Current
|
||||||
}
|
}
|
||||||
#endif // USE_DOMOTICZ
|
#endif // USE_DOMOTICZ
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SML_COUNTER {
|
struct SML_COUNTER {
|
||||||
@ -1826,39 +1839,32 @@ struct SML_COUNTER {
|
|||||||
#endif
|
#endif
|
||||||
} sml_counters[MAX_COUNTERS];
|
} 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);
|
uint8_t sml_cnt_index[MAX_COUNTERS] = { 0, 1, 2, 3 };
|
||||||
if (!level) {
|
void ICACHE_RAM_ATTR SML_CounterIsr(void *arg) {
|
||||||
// falling edge
|
uint32_t index = *static_cast<uint8_t*>(arg);
|
||||||
uint32_t ltime=millis()-sml_counters[index].sml_counter_ltime;
|
|
||||||
sml_counters[index].sml_counter_ltime=millis();
|
uint32_t time = micros();
|
||||||
if (ltime>sml_counters[index].sml_debounce) {
|
uint32_t debounce_time;
|
||||||
RtcSettings.pulse_counter[index]++;
|
|
||||||
sml_counters[index].sml_cnt_updated=1;
|
if (digitalRead(meter_desc_p[sml_counters[index].sml_cnt_old_state].srcpin) == bitRead(sml_counter_pinstate, index)) {
|
||||||
//InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]);
|
return;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// rising edge
|
|
||||||
sml_counters[index].sml_counter_ltime=millis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#ifdef USE_SCRIPT
|
||||||
struct METER_DESC script_meter_desc[MAX_METERS];
|
struct METER_DESC script_meter_desc[MAX_METERS];
|
||||||
@ -1916,14 +1922,6 @@ uint32_t SML_getscriptsize(char *lp) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Gpio_used(uint8_t gpiopin) {
|
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)) {
|
if ((gpiopin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2131,7 +2129,6 @@ next_line:
|
|||||||
|
|
||||||
init10:
|
init10:
|
||||||
typedef void (*function)();
|
typedef void (*function)();
|
||||||
function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4};
|
|
||||||
uint8_t cindex=0;
|
uint8_t cindex=0;
|
||||||
// preloud counters
|
// preloud counters
|
||||||
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
||||||
@ -2158,7 +2155,7 @@ init10:
|
|||||||
// check for irq mode
|
// check for irq mode
|
||||||
if (meter_desc_p[meters].params<=0) {
|
if (meter_desc_p[meters].params<=0) {
|
||||||
// init irq mode
|
// 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_cnt_old_state=meters;
|
||||||
sml_counters[cindex].sml_debounce=-meter_desc_p[meters].params;
|
sml_counters[cindex].sml_debounce=-meter_desc_p[meters].params;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
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.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),
|
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
|
#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
|
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
|
#define HM10_MAX_RX_BUF 64
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#pragma pack(1) // byte-aligned structures to read the sensor data
|
#pragma pack(1) // byte-aligned structures to read the sensor data
|
||||||
|
|
||||||
@ -152,8 +117,44 @@ struct ATCPacket_t{
|
|||||||
uint8_t frameCnt;
|
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)
|
#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{
|
struct mi_sensor_t{
|
||||||
uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6
|
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
|
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::vector<mi_sensor_t> MIBLEsensors;
|
||||||
|
std::array<generic_beacon_t,4> MIBLEbeacons; // we support a fixed number
|
||||||
|
std::vector<scan_entry_t> MINBLEscanResult;
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* constants
|
* constants
|
||||||
@ -226,8 +270,9 @@ std::vector<mi_sensor_t> MIBLEsensors;
|
|||||||
#define D_CMND_HM10 "HM10"
|
#define D_CMND_HM10 "HM10"
|
||||||
|
|
||||||
const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}";
|
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 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 FLORA 1
|
||||||
#define MJ_HT_V1 2
|
#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_BAUD, // serial speed of ESP8266 (<-> HM10), does not change baud rate of HM10
|
||||||
CMND_HM10_TIME, // set LYWSD02-Time from ESP8266-time
|
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_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 {
|
enum HM10_awaitData: uint8_t {
|
||||||
@ -354,6 +400,50 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){
|
|||||||
HM10_TASK_LIST[slot][0] = task;
|
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[]){
|
void HM10_ReverseMAC(uint8_t _mac[]){
|
||||||
uint8_t _reversedMAC[6];
|
uint8_t _reversedMAC[6];
|
||||||
for (uint8_t i=0; i<6; i++){
|
for (uint8_t i=0; i<6; i++){
|
||||||
@ -361,7 +451,23 @@ void HM10_ReverseMAC(uint8_t _mac[]){
|
|||||||
}
|
}
|
||||||
memcpy(_mac,_reversedMAC, sizeof(_reversedMAC));
|
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
|
* chained tasks
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -377,9 +483,9 @@ void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disco
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HM10_Discovery_Scan(void) {
|
void HM10_Discovery_Scan(void) {
|
||||||
HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
|
// HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect
|
||||||
HM10_Launchtask(TASK_HM10_DISC,1,1); // discovery
|
HM10_Launchtask(TASK_HM10_DISC,0,1); // discovery
|
||||||
HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); // status
|
// HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,1); // status
|
||||||
}
|
}
|
||||||
|
|
||||||
void HM10_Read_LYWSD03(void) { //and MHO-C401
|
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
|
* @param _type Type number of the sensor
|
||||||
* @return uint32_t Known or new slot in the sensors-vector
|
* @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);
|
DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type);
|
||||||
bool _success = false;
|
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++){
|
for(uint32_t i=0; i<MIBLEsensors.size(); i++){
|
||||||
if(memcmp(_MAC,MIBLEsensors[i].MAC,sizeof(_MAC))==0){
|
if(memcmp(_MAC,MIBLEsensors[i].MAC,sizeof(_MAC))==0){
|
||||||
DEBUG_SENSOR_LOG(PSTR("%s: known sensor at slot: %u"),D_CMND_HM10, i);
|
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
|
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
|
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.feature.raw = 0;
|
||||||
_newSensor.temp =NAN;
|
_newSensor.temp =NAN;
|
||||||
_newSensor.bat=0x00;
|
_newSensor.bat=0x00;
|
||||||
_newSensor.rssi=_rssi * -1;
|
_newSensor.rssi=_rssi;
|
||||||
_newSensor.lux = 0x00ffffff;
|
_newSensor.lux = 0x00ffffff;
|
||||||
switch (_type){
|
switch (_type){
|
||||||
case FLORA:
|
case FLORA:
|
||||||
@ -540,13 +647,15 @@ void HM10SerialInit(void) {
|
|||||||
HM10.period = Settings.tele_period;
|
HM10.period = Settings.tele_period;
|
||||||
DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10);
|
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
|
//test section for options
|
||||||
HM10.option.noRealTime = 1;
|
|
||||||
HM10.option.allwaysAggregate = 1;
|
HM10.option.allwaysAggregate = 1;
|
||||||
HM10.option.showRSSI = 0;
|
|
||||||
HM10.option.ignoreBogusBattery = 1;
|
|
||||||
HM10.option.noSummary = 0;
|
HM10.option.noSummary = 0;
|
||||||
HM10.option.minimalSummary = 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];
|
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));
|
memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon));
|
||||||
}
|
}
|
||||||
HM10_ReverseMAC(_beacon.MAC);
|
HM10_ReverseMAC(_beacon.MAC);
|
||||||
if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){
|
// if(memcmp(_beacon.MAC,MIBLEsensors[_slot].MAC,sizeof(_beacon.MAC))!=0){
|
||||||
if (MIBLEsensors[_slot].showedUp>3) return; // probably false alarm from a damaged packet
|
// 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);
|
// 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 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]);
|
// 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);
|
// MIBLEsensors.erase(MIBLEsensors.begin()+_slot);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (MIBLEsensors[_slot].showedUp<4) MIBLEsensors[_slot].showedUp++;
|
// 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("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]);
|
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;
|
// 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);
|
DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type);
|
||||||
return;
|
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);
|
DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10DeviceType[MIBLEsensors[_slot].type-1],_slot);
|
||||||
switch(_beacon.type){
|
switch(_beacon.type){
|
||||||
case 0x01:
|
case 0x01:
|
||||||
@ -659,7 +770,7 @@ void HM10parseMiBeacon(char * _buf, uint32_t _slot){
|
|||||||
}
|
}
|
||||||
if(MIBLEsensors[_slot].eventType.raw == 0) return;
|
if(MIBLEsensors[_slot].eventType.raw == 0) return;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
HM10.mode.shallTriggerTele = 1;
|
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HM10parseATC(char * _buf, uint32_t _slot){
|
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).hum = (float)_packet->hum;
|
||||||
MIBLEsensors.at(_slot).bat = _packet->batPer;
|
MIBLEsensors.at(_slot).bat = _packet->batPer;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
|
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* HM10ParseResponse(char *buf, uint16_t bufsize) {
|
void HM10parseCGD1Packet(char * _buf, uint32_t _slot){ // no MiBeacon
|
||||||
if (!strncmp(buf,"HMSoft",6)) { //8
|
cg_packet_t *_packet = (cg_packet_t*)_buf;
|
||||||
const char* _fw = "000";
|
switch (_packet->mode){
|
||||||
memcpy((void *)_fw,(void *)(buf+8),3);
|
case 0x0401:
|
||||||
HM10.firmware = atoi(_fw);
|
float _tempFloat;
|
||||||
DEBUG_SENSOR_LOG(PSTR("%s: Firmware: %d"),D_CMND_HM10, HM10.firmware);
|
_tempFloat=(float)(_packet->temp)/10.0f;
|
||||||
return buf;
|
if(_tempFloat<60){
|
||||||
}
|
MIBLEsensors.at(_slot).temp = _tempFloat;
|
||||||
char * _pos = nullptr;
|
MIBLEsensors[_slot].eventType.temp = 1;
|
||||||
uint32_t _idx = 0;
|
DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated"));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
_tempFloat=(float)(_packet->hum)/10.0f;
|
||||||
if(_pos) {
|
if(_tempFloat<100){
|
||||||
uint8_t _newMacArray[6] = {0};
|
MIBLEsensors.at(_slot).hum = _tempFloat;
|
||||||
memcpy((void *)_newMacArray,(void *)(_pos+4),6);
|
MIBLEsensors[_slot].eventType.hum = 1;
|
||||||
uint32_t _rssi = 255- (uint8_t)(_pos[11]);
|
DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated"));
|
||||||
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]);
|
DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), _packet->temp, _packet->hum);
|
||||||
uint16_t _type=0xffff;
|
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++){
|
void HM10ParseResponse(char *buf, uint16_t bufsize) {
|
||||||
if((uint8_t)_pos[_idx] == 0xfe){
|
if (!strncmp(buf,"HMSoft",6)) { //8
|
||||||
if((uint8_t)_pos[_idx-2] == 0x16 && (uint8_t)_pos[_idx-1] == 0x95){
|
const char* _fw = "000";
|
||||||
_pos = _pos+_idx+1;
|
memcpy((void *)_fw,(void *)(buf+8),3);
|
||||||
_type = (uint8_t)_pos[3]*256 + (uint8_t)_pos[2];
|
HM10.firmware = atoi(_fw);
|
||||||
DEBUG_SENSOR_LOG(PSTR("%s: type %04x _ %02x %02x"),D_CMND_HM10,_type, _pos[3],_pos[2]);
|
DEBUG_SENSOR_LOG(PSTR("%s: Firmware: %d"),D_CMND_HM10, HM10.firmware);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else if (strstr(buf, "LOST")){
|
else if (strstr(buf, "LOST")){
|
||||||
HM10.current_task_delay = 0;
|
HM10.current_task_delay = 0;
|
||||||
HM10.mode.connected = false;
|
HM10.mode.connected = false;
|
||||||
}
|
}
|
||||||
else if (strstr(buf, "CONNF")){
|
else if (strstr(buf, "CONNF")){
|
||||||
HM10.mode.connected = false;
|
HM10.mode.connected = false;
|
||||||
HM10.current_task_delay = 0;
|
HM10.current_task_delay = 0;
|
||||||
}
|
}
|
||||||
else if (strstr(buf, "CONN")){
|
else if (strstr(buf, "CONN")){
|
||||||
HM10.current_task_delay = 0;
|
HM10.current_task_delay = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_SENSOR_LOG(PSTR("%s: empty response"),D_CMND_HM10);
|
DEBUG_SENSOR_LOG(PSTR("%s: empty response"),D_CMND_HM10);
|
||||||
return buf;
|
}
|
||||||
}
|
|
||||||
return _pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HM10readHT_LY(char *_buf){
|
void HM10readHT_LY(char *_buf){
|
||||||
@ -768,7 +868,7 @@ void HM10readHT_LY(char *_buf){
|
|||||||
MIBLEsensors[_slot].eventType.bat = 1;
|
MIBLEsensors[_slot].eventType.bat = 1;
|
||||||
}
|
}
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 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].eventType.tempHum = 1;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 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].eventType.tempHum = 1;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
HM10.mode.shallTriggerTele = 1;
|
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HM10readTLMF(char *_buf){
|
void HM10readTLMF(char *_buf){
|
||||||
@ -851,8 +951,7 @@ void HM10readTLMF(char *_buf){
|
|||||||
MIBLEsensors[_slot].eventType.moist = 1;
|
MIBLEsensors[_slot].eventType.moist = 1;
|
||||||
MIBLEsensors[_slot].eventType.fert = 1;
|
MIBLEsensors[_slot].eventType.fert = 1;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
HM10.mode.shallTriggerTele = 1;
|
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||||
|
|
||||||
HM10.mode.awaiting = none;
|
HM10.mode.awaiting = none;
|
||||||
HM10.current_task_delay = 0;
|
HM10.current_task_delay = 0;
|
||||||
}
|
}
|
||||||
@ -873,13 +972,90 @@ bool HM10readBat(char *_buf){
|
|||||||
MIBLEsensors[_slot].showedUp=255; // this sensor is real
|
MIBLEsensors[_slot].showedUp=255; // this sensor is real
|
||||||
MIBLEsensors[_slot].eventType.bat = 1;
|
MIBLEsensors[_slot].eventType.bat = 1;
|
||||||
MIBLEsensors[_slot].shallSendMQTT = 1;
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
HM10.mode.shallTriggerTele = 1;
|
if(HM10.option.directBridgeMode) HM10.mode.shallTriggerTele = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
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
|
* handle the return value from the HM10
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -887,19 +1063,63 @@ bool HM10readBat(char *_buf){
|
|||||||
bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
||||||
bool success = false;
|
bool success = false;
|
||||||
uint32_t i = 0;
|
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(_isPotentialAdv){ // we will change the pointer now according to the AD-type and data length
|
||||||
if(i<HM10_MAX_RX_BUF){
|
if(_nextStep>length_type[0]){
|
||||||
HM10.rxBuffer[i] = HM10Serial->read();
|
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++;
|
i++;
|
||||||
|
_rx++;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i==0){
|
if(i==0){
|
||||||
if(HM10.mode.shallTriggerTele){ // let us use the spare time for other things
|
if(HM10.mode.shallTriggerTele){ // let us use the spare time for other things
|
||||||
HM10.mode.shallTriggerTele=0;
|
HM10.mode.shallTriggerTele=0;
|
||||||
if(HM10.option.noRealTime){
|
if(HM10.option.directBridgeMode){
|
||||||
HM10.mode.triggeredTele=0;
|
HM10.mode.triggeredTele=0;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -928,11 +1148,23 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
|||||||
if (HM10.mode.connected) HM10readTLMF(HM10.rxBuffer);
|
if (HM10.mode.connected) HM10readTLMF(HM10.rxBuffer);
|
||||||
break;
|
break;
|
||||||
case discScan:
|
case discScan:
|
||||||
if(success) {
|
if(_isValidAdv) {
|
||||||
char *_src = HM10ParseResponse(HM10.rxBuffer,i);
|
if(HM10.state.beaconScanCounter!=0 || HM10.mode.activeBeacon){
|
||||||
if(_src){
|
HM10HandleGenericBeacon();
|
||||||
HM10ParseResponse(_src,i-(_src-HM10.rxBuffer)); // try a second parse
|
}
|
||||||
}
|
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;
|
break;
|
||||||
case tempHumMJ:
|
case tempHumMJ:
|
||||||
@ -949,6 +1181,9 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(HM10.rxBuffer,0,i); // wipe away the recent bytes
|
memset(HM10.rxBuffer,0,i); // wipe away the recent bytes
|
||||||
|
if(_isPotentialAdv){
|
||||||
|
memset((void*)&HM10.rxAdvertisement,0,sizeof(HM10.rxAdvertisement));
|
||||||
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1203,7 +1438,7 @@ void HM10StatusInfo() {
|
|||||||
AddLog_P2(LOG_LEVEL_INFO, stemp);
|
AddLog_P2(LOG_LEVEL_INFO, stemp);
|
||||||
RulesProcessEvent(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();
|
XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1223,6 +1458,25 @@ void HM10EverySecond(bool restart){
|
|||||||
return;
|
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.firmware == 0) return;
|
||||||
if(HM10.mode.pending_task == 1) return;
|
if(HM10.mode.pending_task == 1) return;
|
||||||
if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return;
|
if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return;
|
||||||
@ -1358,6 +1612,31 @@ bool HM10Cmd(void) {
|
|||||||
HM10_Discovery_Scan();
|
HM10_Discovery_Scan();
|
||||||
Response_P(S_JSON_HM10_COMMAND, command, "");
|
Response_P(S_JSON_HM10_COMMAND, command, "");
|
||||||
break;
|
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:
|
default:
|
||||||
// else for Unknown command
|
// else for Unknown command
|
||||||
serviced = false;
|
serviced = false;
|
||||||
@ -1388,7 +1667,7 @@ void HM10triggerTele(void){
|
|||||||
* Presentation
|
* 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_HM10_MAC[] PROGMEM = "{s}%s %s{m}%s{e}";
|
||||||
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}";
|
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}";
|
||||||
const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}";
|
const char HTTP_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)
|
void HM10Show(bool json)
|
||||||
{
|
{
|
||||||
if (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.mode.triggeredTele){
|
||||||
if(HM10.option.noSummary) return; // no message at TELEPERIOD
|
if(HM10.option.noSummary) return; // no message at TELEPERIOD
|
||||||
}
|
}
|
||||||
@ -1416,7 +1709,11 @@ void HM10Show(bool json)
|
|||||||
bool tempHumSended = false;
|
bool tempHumSended = false;
|
||||||
if(MIBLEsensors[i].feature.tempHum){
|
if(MIBLEsensors[i].feature.tempHum){
|
||||||
if(MIBLEsensors[i].eventType.tempHum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
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(","));
|
ResponseAppend_P(PSTR(","));
|
||||||
ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum);
|
ResponseAppendTHD(MIBLEsensors[i].temp, MIBLEsensors[i].hum);
|
||||||
tempHumSended = true;
|
tempHumSended = true;
|
||||||
@ -1425,7 +1722,11 @@ void HM10Show(bool json)
|
|||||||
}
|
}
|
||||||
if(MIBLEsensors[i].feature.temp && !tempHumSended){
|
if(MIBLEsensors[i].feature.temp && !tempHumSended){
|
||||||
if(MIBLEsensors[i].eventType.temp || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
|
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];
|
char temperature[FLOATSZ];
|
||||||
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
|
dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"), 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].feature.hum && !tempHumSended){
|
||||||
if(MIBLEsensors[i].eventType.hum || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate) {
|
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];
|
char hum[FLOATSZ];
|
||||||
dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum);
|
dtostrfd(MIBLEsensors[i].hum, Settings.flag2.humidity_resolution, hum);
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), 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].feature.lux){
|
||||||
if(MIBLEsensors[i].eventType.lux || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
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);
|
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].feature.moist){
|
||||||
if(MIBLEsensors[i].eventType.moist || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
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);
|
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].feature.fert){
|
||||||
if(MIBLEsensors[i].eventType.fert || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
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);
|
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].feature.bat){
|
||||||
if(MIBLEsensors[i].eventType.bat || !HM10.mode.triggeredTele || HM10.option.allwaysAggregate){
|
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);
|
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
|
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;
|
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
|
#ifdef USE_WEBSERVER
|
||||||
} else {
|
} else {
|
||||||
static uint16_t _page = 0;
|
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(MIBLEsensors.size()%HM10.perPage==0 && _page==MIBLEsensors.size()/HM10.perPage) _page=0;
|
||||||
if(_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
|
#endif // USE_WEBSERVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifdef USE_I2C
|
#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
|
#define USE_EZO
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_EZO)
|
#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
|
// The order of the EZO devices must map with the enum declared above
|
||||||
const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
||||||
EZOStruct::id, // "DO"
|
#ifdef USE_EZODO
|
||||||
|
EZODO::id,
|
||||||
|
#else
|
||||||
|
EZOStruct::id,
|
||||||
|
#endif
|
||||||
#ifdef USE_EZOORP
|
#ifdef USE_EZOORP
|
||||||
EZOORP::id,
|
EZOORP::id,
|
||||||
#else
|
#else
|
||||||
@ -67,7 +71,7 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
|||||||
#else
|
#else
|
||||||
EZOStruct::id,
|
EZOStruct::id,
|
||||||
#endif
|
#endif
|
||||||
EZOStruct::id,
|
EZOStruct::id, // <unnamed>
|
||||||
#ifdef USE_EZORTD
|
#ifdef USE_EZORTD
|
||||||
EZORTD::id,
|
EZORTD::id,
|
||||||
#else
|
#else
|
||||||
@ -89,14 +93,14 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = {
|
|||||||
#else
|
#else
|
||||||
EZOStruct::id,
|
EZOStruct::id,
|
||||||
#endif
|
#endif
|
||||||
EZOStruct::id,
|
EZOStruct::id, // <unnamed>
|
||||||
#ifdef USE_EZOO2
|
#ifdef USE_EZOO2
|
||||||
EZOO2::id,
|
EZOO2::id,
|
||||||
#else
|
#else
|
||||||
EZOStruct::id,
|
EZOStruct::id,
|
||||||
#endif
|
#endif
|
||||||
EZOStruct::id,
|
EZOStruct::id, // <unnamed>
|
||||||
EZOStruct::id,
|
EZOStruct::id, // <unnamed>
|
||||||
#ifdef USE_EZOHUM
|
#ifdef USE_EZOHUM
|
||||||
EZOHUM::id,
|
EZOHUM::id,
|
||||||
#else
|
#else
|
||||||
@ -234,6 +238,9 @@ private:
|
|||||||
|
|
||||||
// We use switch intead of virtual function to save RAM
|
// We use switch intead of virtual function to save RAM
|
||||||
switch (j + EZO_ADDR_0) {
|
switch (j + EZO_ADDR_0) {
|
||||||
|
#ifdef USE_EZODO
|
||||||
|
CREATE_EZO_CLASS(DO)
|
||||||
|
#endif
|
||||||
#ifdef USE_EZOORP
|
#ifdef USE_EZOORP
|
||||||
CREATE_EZO_CLASS(ORP)
|
CREATE_EZO_CLASS(ORP)
|
||||||
#endif
|
#endif
|
||||||
|
@ -235,7 +235,7 @@ a_features = [[
|
|||||||
],[
|
],[
|
||||||
"USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC",
|
"USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC",
|
||||||
"USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO",
|
"USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO",
|
||||||
"","","","",
|
"USE_EZODO","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
@ -268,7 +268,7 @@ else:
|
|||||||
obj = json.load(fp)
|
obj = json.load(fp)
|
||||||
|
|
||||||
def StartDecode():
|
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))
|
# print("Decoding\n{}".format(obj))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user