Merge branch 'development' into pre-release-9.1.0

This commit is contained in:
Theo Arends 2020-11-04 16:59:29 +01:00
commit 4f92d4984f
23 changed files with 386 additions and 122 deletions

View File

@ -22,8 +22,10 @@ All notable changes to this project will be documented in this file.
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
- Command ``Gpios 255`` to show all possible GPIO configurations
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes returning `{"Switch1":{"Action":"ON"}}`
- Command ``SetOption114 1`` to detach Switches from Relays and enable MQTT action state for all the SwitchModes returning `{"Switch1":{"Action":"ON"}}`
- HM10 Beacon support and refactoring by Christian Baars (#9702)
- Support for Hass discovery of TuyaMcu and Sonoff Ifan by Federico Leoni (#9727)
- Initial support for iBeacons (Sensor52) on ESP32 using internal BLE by rvbglas (#9732)
### Changed
- PlatformIO library structure redesigned for compilation speed by Jason2866
@ -36,6 +38,7 @@ All notable changes to this project will be documented in this file.
- 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)
- Arilux RF remote detection regression from v8.3.0
## [9.0.0.2] - 20201025
### Added

View File

@ -21,7 +21,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases
## Development
[![Dev Version](https://img.shields.io/badge/development%20version-v9.0.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Dev Version](https://img.shields.io/badge/development%20version-v9.1.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/)
[![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
[![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
@ -68,17 +68,17 @@ See [wiki migration path](https://tasmota.github.io/docs/Upgrading#migration-pat
1. Migrate to **Sonoff-Tasmota 3.9.x**
2. Migrate to **Sonoff-Tasmota 4.x**
3. Migrate to **Sonoff-Tasmota 5.14**
4. Migrate to **Sonoff-Tasmota 6.x**
5. Migrate to **Tasmota 7.x**
4. Migrate to **Sonoff-Tasmota 6.7.1**
5. Migrate to **Tasmota 7.2.0**
--- Major change in parameter storage layout ---
6. Migrate to **Tasmota 8.1**
7. Migrate to **Tasmota 8.x**
7. Migrate to **Tasmota 8.5.1**
--- Major change in internal GPIO function representation ---
8. Migrate to **Tasmota 9.x**
8. Migrate to **Tasmota 9.1**
While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with version **v9.0.0.1** the internal GPIO function representation has changed in such a way that fallback is only possible to the latest GPIO configuration before installing **v9.0.0.1**.

View File

@ -9,13 +9,13 @@ See [migration path](https://tasmota.github.io/docs/Upgrading#migration-path) fo
1. Migrate to **Sonoff-Tasmota 3.9.x**
2. Migrate to **Sonoff-Tasmota 4.x**
3. Migrate to **Sonoff-Tasmota 5.14**
4. Migrate to **Sonoff-Tasmota 6.x**
5. Migrate to **Tasmota 7.x**
4. Migrate to **Sonoff-Tasmota 6.7.1**
5. Migrate to **Tasmota 7.2.0**
--- Major change in parameter storage layout ---
6. Migrate to **Tasmota 8.1**
7. Migrate to **Tasmota 8.x**
7. Migrate to **Tasmota 8.5.1**
--- Major change in internal GPIO function representation ---
@ -64,7 +64,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- Command ``ShutterChange`` to increment change position (#9594)
- Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593)
- Command ``SetOption113 1`` to set dimmer low on rotary dial after power off
- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes
- Command ``SetOption114 1`` to detach Switches from Relays and enable MQTT action state for all the SwitchModes
- Command ``SwitchText`` to change JSON switch names by barbudor (#9691)
- Zigbee command ``ZbData`` for better support of device specific data
- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR
@ -79,11 +79,13 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- Support for timers in case of no-sunset permanent day by cybermaus (#9543)
- Support for EZO sensors by Christopher Tremblay
- Support for fixed output Hi or Lo GPIO selection
- Support for Hass discovery of TuyaMcu and Sonoff Ifan by Federico Leoni (#9727)
- TLS in binary tasmota-zbbridge (#9620)
- Zigbee reduce battery drain (#9642)
- ESP32 support for Wireless-Tag WT32-ETH01 (#9496)
- ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring by Christian Baars (#9609)
- HM10 Beacon support and refactoring by Christian Baars (#9702)
- Initial support for iBeacons (Sensor52) on ESP32 using internal BLE by rvbglas (#9732)
### Breaking Changed
- Redesigned ESP8266 GPIO internal representation in line with ESP32 changing ``Template`` layout too
@ -98,8 +100,6 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- New IR Raw compact format (#9444)
- A4988 optional microstep pin selection
- Pulsetime to allow use for all relays with 8 interleaved so ``Pulsetime1`` is valid for Relay1, Relay9, Relay17 etc. (#9279)
- IRremoteESP8266 library from v2.7.10 to v2.7.11
- NeoPixelBus library from v2.5.0.09 to v2.6.0
- Management of serial baudrate (#9554)
- Rotary driver adjusted accordingly if Mi Desk Lamp module is selected (#9399)
- Tasmota Arduino Core v2.7.4.5 allowing webpassword over 47 characters (#9687)
@ -107,26 +107,29 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- PlatformIO library structure redesigned for compilation speed by Jason2866
- Zigbee flash storage refactor adding commands ``ZbProbe``, ``ZbStatus2`` and ``ZbRestore`` (#9641)
- Default otaurl in my_user_config.h to http://ota.tasmota.com/tasmota/release/tasmota.bin.gz
- IRremoteESP8266 library from v2.7.10 to v2.7.11
- NeoPixelBus library from v2.5.0.09 to v2.6.0
### Fixed
- Ledlink blink when no network connected regression from v8.3.1.4 (#9292)
- Light wakeup Exception 0 (divide by zero) when ``WakeupDuration`` is not initialised (#9466)
- Exception 28 due to device group buffer overflow (#9459)
- Shutter timing problem due to buffer overflow in calibration matrix (#9458)
- Light wakeup exception 0 (divide by zero) when ``WakeupDuration`` is not initialised (#9466)
- Arilux RF remote detection regression from v8.3.0
- Ledlink blink when no network connected regression from v8.3.1.4 (#9292)
- TuyaMcu energy display regression from v8.5.0.1 (#9547)
- Thermostat sensor status corruption regression from v8.5.0.1 (#9449)
- Telegram message decoding error regression from v8.5.0.1
- Rule handling of Var or Mem using text regression from v8.5.0.1 (#9540)
- Rule handling of JSON ``null`` regression from v8.5.0.1 (#9685)
- Rule Break not working as expected when ONCE is enabled (#9245)
- Rule expressions using mems corrupts character pool (#9301)
- Shutter timing problem due to buffer overflow in calibration matrix (#9458)
- Correct Energy period display shortly after midnight by gominoa (#9536)
- TuyaMcu energy display regression from v8.5.0.1 (#9547)
- Tuyamcu dimmers MQTT topic (#9606)
- Scripter memory alignment (#9608)
- Zigbee battery percentage (#9607)
- HassAnyKey anomaly (#9601)
- Rule Break not working as expected when ONCE is enabled (#9245)
- Rule expressions using mems corrupts character pool (#9301)
### Removed
- Support for direct upgrade from Tasmota versions before v7.0
- Auto config update for all Friendlynames and Switchtopic from Tasmota versions before v8.0
- Support for downgrade to versions before 9.0 keeping current GPIO configuration
- Auto config update for all Friendlynames and Switchtopic from Tasmota versions before v8.0

View File

@ -89,6 +89,7 @@ lib_extra_dirs = ${library.lib_extra_dirs}
[tasmota_stage]
; *** Esp8266 core for Arduino version Tasmota stage (PR7231 and Backport PR7514)
platform_packages = framework-arduinoespressif8266@https://github.com/Jason2866/Arduino.git#2.7.4.4
platformio/tool-esptool @ 1.413.0
build_unflags = ${esp_defaults.build_unflags}
build_flags = ${esp82xx_defaults.build_flags}
@ -122,14 +123,15 @@ build_flags = ${esp82xx_defaults.build_flags}
; -lstdc++-exc
[core_stage]
; *** Esp8266 core version. Tasmota stage or Arduino stage version. Built with GCC 10.1 toolchain
platform_packages = framework-arduinoespressif8266 @ https://github.com/Jason2866/platform-espressif8266/releases/download/2.9.1/framework-arduinoespressif8266-3.20901.0.tar.gz
;framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
toolchain-xtensa @ ~2.100100.0
; *** Esp8266 core for Arduino version stage
platform_packages = framework-arduinoespressif8266@https://github.com/esp8266/Arduino.git
; *** Use Xtensa build chain 10.2. GNU13 from https://github.com/earlephilhower/esp-quick-toolchain
mcspr/toolchain-xtensa@5.100200.200918
platformio/tool-esptool @ 1.413.0
build_unflags = ${esp_defaults.build_unflags}
-Wswitch-unreachable
-Wswitch-unreachable
build_flags = ${esp82xx_defaults.build_flags}
-Wno-switch-unreachable
-Wno-switch-unreachable
; *********** Alternative Options, enable only if you know exactly what you do ********
; NONOSDK221

View File

@ -139,7 +139,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
typedef union { // Restricted by MISRA-C Rule 18.4 but so useful...
uint32_t data; // Allow bit manipulation using SetOption
struct { // SetOption114 .. SetOption145
uint32_t mqtt_switches : 1; // bit 0 (V9.0.0.3) - SetOption114 - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
uint32_t mqtt_switches : 1; // bit 0 (V9.0.0.3) - SetOption114 - Detach Switches from relays and enable MQTT action state for all the SwitchModes
//uint32_t spare00 : 1; // bit 0
uint32_t spare01 : 1; // bit 1
uint32_t spare02 : 1; // bit 2

View File

@ -1242,7 +1242,7 @@ void CmndTemplate(void)
bool error = false;
if (strstr(XdrvMailbox.data, "{") == nullptr) { // If no JSON it must be parameter
if (strchr(XdrvMailbox.data, '{') == nullptr) { // If no JSON it must be parameter
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= MAXMODULE)) {
XdrvMailbox.payload--;
if (ValidTemplateModule(XdrvMailbox.payload)) {
@ -1550,7 +1550,7 @@ void CmndHostname(void)
{
if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data);
if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) {
if (strchr(SettingsText(SET_HOSTNAME), '%') != nullptr) {
SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
}
TasmotaGlobal.restart_flag = 2;
@ -1643,7 +1643,7 @@ void CmndInterlock(void)
if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; }
if (max_relays > 1) { // Only interlock with more than 1 relay
if (XdrvMailbox.data_len > 0) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Interlock entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Interlock entry
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks
char *group;
char *q;
@ -1801,7 +1801,7 @@ void CmndTimeStdDst(uint32_t ts)
{
// TimeStd 0/1, 0/1/2/3/4, 1..12, 1..7, 0..23, +/-780
if (XdrvMailbox.data_len > 0) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Process parameter entry
uint32_t tpos = 0; // Parameter index
int value = 0;
char *p = XdrvMailbox.data; // Parameters like "1, 2,3 , 4 ,5, -120" or ",,,,,+240"

View File

@ -410,13 +410,13 @@ void SwitchHandler(uint32_t mode) {
Switch.last_state[i] = button;
}
if (switchflag <= POWER_TOGGLE) {
if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present)
}
} else { mqtt_action = switchflag; }
}
if ((mqtt_action != POWER_NONE) && Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes
if ((mqtt_action != POWER_NONE) && Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
char mqtt_state_str[16];
char *mqtt_state = mqtt_state_str;

View File

@ -25,10 +25,10 @@ char* Format(char* output, const char* input, int size)
char *token;
uint32_t digits = 0;
if (strstr(input, "%") != nullptr) {
if (strchr(input, '%') != nullptr) {
strlcpy(output, input, size);
token = strtok(output, "%");
if (strstr(input, "%") == input) {
if (strchr(input, '%') == input) {
output[0] = '\0';
} else {
token = strtok(nullptr, "");

View File

@ -280,7 +280,7 @@ void setup(void) {
Format(TasmotaGlobal.mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(TasmotaGlobal.mqtt_client));
Format(TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(TasmotaGlobal.mqtt_topic));
if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) {
if (strchr(SettingsText(SET_HOSTNAME), '%') != nullptr) {
SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
snprintf_P(TasmotaGlobal.hostname, sizeof(TasmotaGlobal.hostname)-1, SettingsText(SET_HOSTNAME), TasmotaGlobal.mqtt_topic, ESP_getChipId() & 0x1FFF);
} else {

View File

@ -2185,7 +2185,7 @@ void WifiSaveSettings(void)
WebGetArg("h", tmp, sizeof(tmp));
SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp);
if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) {
if (strchr(SettingsText(SET_HOSTNAME), '%') != nullptr) {
SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
}
WebGetArg("c", tmp, sizeof(tmp));
@ -3429,7 +3429,7 @@ void CmndWebSend(void)
void CmndWebColor(void)
{
if (XdrvMailbox.data_len > 0) {
if (strstr(XdrvMailbox.data, "{") == nullptr) { // If no JSON it must be parameter
if (strchr(XdrvMailbox.data, '{') == nullptr) { // If no JSON it must be parameter
if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= COL_LAST)) {
WebHexCode(XdrvMailbox.index -1, XdrvMailbox.data);
}

View File

@ -2513,7 +2513,7 @@ bool LightColorEntry(char *buffer, uint32_t buffer_length)
buffer_length--; // remove all trailing '='
memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color));
}
if (strstr(buffer, ",") != nullptr) { // Decimal entry
if (strchr(buffer, ',') != nullptr) { // Decimal entry
int8_t i = 0;
for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) {
if (i < LST_MAX) {

View File

@ -318,7 +318,7 @@ void CmndIrSend(void)
uint8_t error = IE_SYNTAX_IRSEND;
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, "{") == nullptr) {
if (strchr(XdrvMailbox.data, '{') == nullptr) {
error = IE_INVALID_JSON;
} else {
error = IrRemoteCmndIrSendJson();

View File

@ -805,7 +805,7 @@ void CmndIrSend(void)
uint8_t error = IE_SYNTAX_IRSEND;
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, "{") == nullptr) {
if (strchr(XdrvMailbox.data, '{') == nullptr) {
error = IrRemoteCmndIrSendRaw();
} else {
error = IrRemoteCmndIrSendJson();

View File

@ -497,7 +497,7 @@ void CmndDomoticzSend(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) {
if (XdrvMailbox.data_len > 0) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Process parameter entry
char *data;
uint32_t index = strtoul(strtok_r(XdrvMailbox.data, ",", &data), nullptr, 10);
if ((index > 0) && (data != nullptr)) {

View File

@ -2249,7 +2249,7 @@ void CmndScale(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Process parameter entry
char sub_string[XdrvMailbox.data_len +1];
float valueIN = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 1));

View File

@ -1120,7 +1120,7 @@ void CmndKnxEnhanced(void)
void CmndKnxPa(void)
{
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ".") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, '.') != nullptr) { // Process parameter entry
char sub_string[XdrvMailbox.data_len];
int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1));
@ -1148,7 +1148,7 @@ void CmndKnxGa(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) {
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Process parameter entry
char sub_string[XdrvMailbox.data_len];
int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
@ -1199,7 +1199,7 @@ void CmndKnxCb(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) {
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
if (strchr(XdrvMailbox.data, ',') != nullptr) { // Process parameter entry
char sub_string[XdrvMailbox.data_len];
int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));

View File

@ -187,17 +187,17 @@ const char HASS_DISCOVER_DEVICE[] PROGMEM = // Basic par
"\"hn\":\"%s\"," // Host Name
"\"mac\":\"%s\"," // Full MAC as Device id
"\"md\":\"%s\"," // Module or Template Name
"\"ty\":%d," // Flag for TuyaMCU devices
"\"ty\":%d,\"if\":%d," // Flag for TuyaMCU and Ifan devices
"\"ofln\":\"" MQTT_LWT_OFFLINE "\"," // Payload Offline
"\"onln\":\"" MQTT_LWT_ONLINE "\"," // Payload Online
"\"state\":[\"%s\",\"%s\",\"%s\",\"%s\"]," // State text for "OFF","ON","TOGGLE","HOLD"
"\"sw\":\"%s\"," // Software Version
"\"t\":\"%s\"," // Topic
"\"ft\":\"%s\"," // Ful Topic
"\"ft\":\"%s\"," // Full Topic
"\"tp\":[\"%s\",\"%s\",\"%s\"]," // Topics for command, stat and tele
"\"rl\":[%s],\"swc\":[%s],\"btn\":[%s]," // Inputs / Outputs
"\"so\":{\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," // SetOptions
"\"30\":%d,\"68\":%d,\"73\":%d,\"80\":%d,\"82\":%d},"
"\"rl\":[%s],\"swc\":[%s],\"swn\":[%s],\"btn\":[%s]," // Inputs / Outputs
"\"so\":{\"4\":%d,\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," // SetOptions
"\"30\":%d,\"68\":%d,\"73\":%d,\"82\":%d,\"114\":%d},"
"\"lk\":%d,\"lt_st\":%d,\"ver\":1}"; // Light SubType, and Discovery version
typedef struct HASS {
@ -272,16 +272,23 @@ void NewHAssDiscovery(void)
char stemp2[200];
char stemp3[TOPSZ];
char stemp4[TOPSZ];
char stemp5[TOPSZ];
char unique_id[30];
char relays[TOPSZ];
char *state_topic = stemp1;
bool SerialButton = false;
bool TuyaMod = false;
bool iFanMod = false;
stemp2[0] = '\0';
struct HASS Hass;
HassDiscoveryRelays(Hass);
#ifdef ESP8266
if (TUYA_DIMMER == TasmotaGlobal.module_type || SK03_TUYA == TasmotaGlobal.module_type) { TuyaMod = true; }
if (SONOFF_IFAN02 == TasmotaGlobal.module_type || SONOFF_IFAN03 == TasmotaGlobal.module_type) { iFanMod = true; }
#endif // ESP8266
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present;
for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) {
char fname[TOPSZ];
@ -290,22 +297,21 @@ void NewHAssDiscovery(void)
}
stemp3[0] = '\0';
// Enable Discovery for Switches only if SwitchTopic is set to a custom name or if there is not a Power device
auto discover_switches = ((KeyTopicActive(1) && (strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), TasmotaGlobal.mqtt_topic))) || !Hass.RelPst);
// Enable Discovery for Switches only if SetOption114 is enabled
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & discover_switches) ? Settings.switchmode[i] : -1);
char sname[TOPSZ];
snprintf_P(sname, sizeof(sname), PSTR("\"%s\""), GetSwitchText(i).c_str());
snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1);
snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%s"), stemp4, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? sname : "null");
}
stemp4[0] = '\0';
stemp5[0] = '\0';
// Enable Discovery for Buttons only if SetOption73 is enabled
for (uint32_t i = 0; i < MAX_KEYS; i++) {
#ifdef ESP8266
if (i == 0 && (SONOFF_DUAL == TasmotaGlobal.module_type )) { SerialButton = true; }
if (TUYA_DIMMER == TasmotaGlobal.module_type || SK03_TUYA == TasmotaGlobal.module_type) { TuyaMod = true; }
#endif // ESP8266
snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%d"), stemp4, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons));
snprintf_P(stemp5, sizeof(stemp5), PSTR("%s%s%d"), stemp5, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons));
SerialButton = false;
}
@ -318,13 +324,14 @@ void NewHAssDiscovery(void)
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id);
// Send empty message if new discovery is disabled
TasmotaGlobal.masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to see it
TasmotaGlobal.masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to show it
if (!Settings.flag.hass_discovery) { // HassDiscoveryRelays(relays)
Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME),
stemp2, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3),
TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap,
Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels,
Settings.flag3.mqtt_buttons, Settings.flag3.shutter_mode, Settings.flag4.alexa_ct_range, light_controller.isCTRGBLinked(), Light.subtype);
stemp2, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, iFanMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3),
TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4,
stemp5, Settings.flag.mqtt_response, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked,
Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag4.alexa_ct_range, Settings.flag5.mqtt_switches,
light_controller.isCTRGBLinked(), Light.subtype);
}
MqttPublish(stopic, true);

View File

@ -88,7 +88,7 @@ void PWMModulePreInit(void)
Settings.ledstate = 0; // Disable LED usage
// If the module was just changed to PWM Dimmer, set the defaults.
if (TasmotaGlobal.module_changed) {
if (TasmotaGlobal.module_changed) {
Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0;

View File

@ -132,7 +132,7 @@ void AdcGetSettings(uint32_t idx) {
Adc[idx].param2 = 0;
Adc[idx].param3 = 0;
Adc[idx].param4 = 0;
if (strstr(SettingsText(SET_ADC_PARAM1 + idx), ",") != nullptr) {
if (strchr(SettingsText(SET_ADC_PARAM1 + idx), ',') != nullptr) {
Adcs.type = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 1));
Adc[idx].param1 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 2));
Adc[idx].param2 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 3));

View File

@ -205,7 +205,7 @@ bool HxCommand(void)
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset");
break;
case 2: // Calibrate
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
Hx.scale = 1;
@ -215,26 +215,26 @@ bool HxCommand(void)
HxCalibrationStateTextJson(3);
break;
case 3: // WeightRef to user reference
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
show_parms = true;
break;
case 4: // WeightCal to user calculated value
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
Hx.scale = Settings.weight_calibration;
}
show_parms = true;
break;
case 5: // WeightMax
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000;
}
show_parms = true;
break;
case 6: // WeightItem
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10);
}
show_parms = true;
@ -244,13 +244,13 @@ bool HxCommand(void)
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE);
break;
case 8: // Json on weight change
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1;
}
show_parms = true;
break;
case 9: // WeightDelta
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
SetWeightDelta();
}

View File

@ -19,44 +19,13 @@
#ifdef USE_IBEACON
#define XSNS_52 52
#include <TasmotaSerial.h>
#define TMSBSIZ52 512
#define HM17_BAUDRATE 9600
#define IBEACON_DEBUG
// use this for Version 110
#define HM17_V110
// keyfob expires after N seconds
#define IB_TIMEOUT_INTERVAL 30
// does a passive scan every N seconds
#define IB_UPDATE_TIME_INTERVAL 10
TasmotaSerial *IBEACON_Serial = nullptr;
uint8_t hm17_found,hm17_cmd,hm17_flag;
#ifdef IBEACON_DEBUG
uint8_t hm17_debug=0;
#endif
// 78 is max serial response
#define HM17_BSIZ 128
char hm17_sbuffer[HM17_BSIZ];
uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting;
uint32_t hm17_lastms;
char ib_mac[14];
// should be in Settings
#if 1
uint8_t ib_upd_interval,ib_tout_interval;
@ -69,9 +38,71 @@ uint8_t ib_upd_interval,ib_tout_interval;
#define IB_TIMEOUT_TIME Settings.ib_tout_interval
#endif
char ib_mac[14];
#ifdef USE_IBEACON_ESP32
struct {
union {
struct {
uint32_t init:1;
uint32_t autoScan:1;
uint32_t canScan:1;
uint32_t runningScan:1;
uint32_t shallClearResults:1; // BLE scan results
uint32_t firstAutodiscoveryDone:1;
uint32_t activeBeacon;
};
uint32_t all = 0;
} mode;
struct {
uint8_t sensor; // points to to the number 0...255
uint8_t beaconScanCounter; // countdown timer in seconds
} state;
} ESP32BLE;
#include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h>
#include "NimBLEEddystoneURL.h"
#include "NimBLEEddystoneTLM.h"
#include "NimBLEBeacon.h"
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))
BLEScan *ESP32BLEScan;
#else
#include <TasmotaSerial.h>
#define TMSBSIZ52 512
#define HM17_BAUDRATE 9600
#define IBEACON_DEBUG
// use this for Version 110
#define HM17_V110
TasmotaSerial *IBEACON_Serial = nullptr;
uint8_t hm17_found,hm17_cmd,hm17_flag;
#ifdef IBEACON_DEBUG
uint8_t hm17_debug=0;
#endif
// 78 is max serial response
#define HM17_BSIZ 128
char hm17_sbuffer[HM17_BSIZ];
uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting;
uint32_t hm17_lastms;
enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON};
#define HM17_SUCESS 99
#endif
struct IBEACON {
char FACID[8];
char UID[32];
@ -82,7 +113,11 @@ struct IBEACON {
char RSSI[4];
};
#define MAX_IBEACONS 16
#ifdef USE_IBEACON_ESP32
#define MAX_IBEACONS 32
#else
#define MAX_IBEACONS 16
#endif
struct IBEACON_UID {
char MAC[12];
@ -92,11 +127,159 @@ struct IBEACON_UID {
char MINOR[4];
uint8_t FLAGS;
uint8_t TIME;
#ifdef USE_IBEACON_ESP32
uint8_t REPTIME;
#endif
} ibeacons[MAX_IBEACONS];
#ifdef USE_IBEACON_ESP32
uint32_t ibeacon_add(struct IBEACON *ib);
void ESP32BLE_ReverseStr(uint8_t _mac[], uint8_t len=6){
uint8_t _reversedMAC[len];
for (uint8_t i=0; i<len; i++){
_reversedMAC[len-1-i] = _mac[i];
}
memcpy(_mac,_reversedMAC, sizeof(_reversedMAC));
}
void DumpHex(const unsigned char * in, size_t insz, char * out)
{
static const char * hex = "0123456789ABCDEF";
const unsigned char * pin = in;
char * pout = out;
for (; pin < in+insz; pout+=2, pin++) {
pout[0] = hex[(pgm_read_byte(pin)>>4) & 0xF];
pout[1] = hex[ pgm_read_byte(pin) & 0xF];
}
}
class ESP32BLEScanCallback : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice *advertisedDevice)
{
struct IBEACON ib;
ESP32BLEScan->erase(advertisedDevice->getAddress());
if (advertisedDevice->haveManufacturerData() == true) {
std::string strManufacturerData = advertisedDevice->getManufacturerData();
uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
int16_t RSSI = advertisedDevice->getRSSI();
char sRSSI[6];
itoa(RSSI,sRSSI,10);
DumpHex(cManufacturerData,2,ib.FACID);
uint8_t MAC[6];
memcpy(MAC,advertisedDevice->getAddress().getNative(),6);
ESP32BLE_ReverseStr(MAC,6);
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00)
{
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData);
uint8_t UUID[16];
memcpy(UUID,oBeacon.getProximityUUID().getNative()->u128.value,16);
ESP32BLE_ReverseStr(UUID,16);
uint16_t Major = ENDIAN_CHANGE_U16(oBeacon.getMajor());
uint16_t Minor = ENDIAN_CHANGE_U16(oBeacon.getMinor());
uint8_t PWR = oBeacon.getSignalPower();
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MAC: %s Major: %d Minor: %d UUID: %s Power: %d RSSI: %d"),
advertisedDevice->getAddress().toString().c_str(),
Major, Minor,
oBeacon.getProximityUUID().toString().c_str(),
PWR, RSSI);
DumpHex((const unsigned char*)&UUID,16,ib.UID);
DumpHex((const unsigned char*)&Major,2,ib.MAJOR);
DumpHex((const unsigned char*)&Minor,2,ib.MINOR);
DumpHex((const unsigned char*)&PWR,1,ib.PWR);
DumpHex((const unsigned char*)&MAC,6,ib.MAC);
memcpy(ib.RSSI,sRSSI,4);
if (ibeacon_add(&ib)==2) {
ibeacon_mqtt(ib.MAC,ib.RSSI,ib.UID,ib.MAJOR,ib.MINOR);
}
} else {
memset(ib.UID,'0',32);
memset(ib.MAJOR,'0',4);
memset(ib.MINOR,'0',4);
memset(ib.PWR,'0',2);
DumpHex((const unsigned char*)&MAC,6,ib.MAC);
memcpy(ib.RSSI,sRSSI,4);
if (ibeacon_add(&ib)==2) {
ibeacon_mqtt(ib.MAC,ib.RSSI,ib.UID,ib.MAJOR,ib.MINOR);
}
}
}
}
};
void ESP32StartScanTask(){
ESP32BLE.mode.runningScan = 1;
xTaskCreatePinnedToCore(
ESP32ScanTask, /* Function to implement the task */
"ESP32ScanTask", /* Name of the task */
2048, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
NULL, /* Task handle. */
0); /* Core where the task should run */
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Start scanning"),"IBEACON_ESP32");
}
void ESP32scanEndedCB(NimBLEScanResults results);
void ESP32ScanTask(void *pvParameters){
if (ESP32BLEScan == nullptr) ESP32BLEScan = NimBLEDevice::getScan();
ESP32BLEScan->setInterval(70);
ESP32BLEScan->setWindow(50);
ESP32BLEScan->setAdvertisedDeviceCallbacks(new ESP32BLEScanCallback());
ESP32BLEScan->setActiveScan(false);
ESP32BLEScan->setDuplicateFilter(false);
for (;;) {
ESP32BLEScan->start(0, ESP32scanEndedCB, false);
}
}
void ESP32scanEndedCB(NimBLEScanResults results) {
ESP32BLE.mode.runningScan = 0;
}
#endif
void IBEACON_Init() {
#ifdef USE_IBEACON_ESP32
ESP32BLE.mode.init = false;
if (!ESP32BLE.mode.init) {
NimBLEDevice::init("");
ESP32BLE.mode.canScan = 1;
ESP32BLE.mode.init = 1;
ESP32StartScanTask(); // Let's get started !!
IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL;
IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL;
}
#else
hm17_found=0;
// actually doesnt work reliably with software serial
@ -113,8 +296,28 @@ void IBEACON_Init() {
IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL;
}
}
#endif
}
#ifdef USE_IBEACON_ESP32
void esp32_every_second(void) {
for (uint32_t cnt=0;cnt<MAX_IBEACONS;cnt++) {
if (ibeacons[cnt].FLAGS) {
ibeacons[cnt].TIME++;
ibeacons[cnt].REPTIME++;
if (ibeacons[cnt].TIME>IB_TIMEOUT_TIME) {
ibeacons[cnt].FLAGS=0;
ibeacon_mqtt(ibeacons[cnt].MAC,"0000",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR);
}
}
}
}
#else
void hm17_every_second(void) {
if (!IBEACON_Serial) return;
@ -196,6 +399,8 @@ void hm17_sendcmd(uint8_t cmd) {
}
}
#endif
uint32_t ibeacon_add(struct IBEACON *ib) {
/* if (!strncmp(ib->MAJOR,"4B1C",4)) {
return 0;
@ -214,6 +419,12 @@ uint32_t ibeacon_add(struct IBEACON *ib) {
// exists
memcpy(ibeacons[cnt].RSSI,ib->RSSI,4);
ibeacons[cnt].TIME=0;
#ifdef USE_IBEACON_ESP32
if (ibeacons[cnt].REPTIME >= IB_UPDATE_TIME) {
ibeacons[cnt].REPTIME = 0;
return 2;
}
#endif
return 1;
}
} else {
@ -221,6 +432,12 @@ uint32_t ibeacon_add(struct IBEACON *ib) {
// exists
memcpy(ibeacons[cnt].RSSI,ib->RSSI,4);
ibeacons[cnt].TIME=0;
#ifdef USE_IBEACON_ESP32
if (ibeacons[cnt].REPTIME >= IB_UPDATE_TIME) {
ibeacons[cnt].REPTIME = 0;
return 2;
}
#endif
return 1;
}
}
@ -235,6 +452,9 @@ uint32_t ibeacon_add(struct IBEACON *ib) {
memcpy(ibeacons[cnt].MINOR,ib->MINOR,4);
ibeacons[cnt].FLAGS=1;
ibeacons[cnt].TIME=0;
#ifdef USE_IBEACON_ESP32
ibeacons[cnt].REPTIME = 0;
#endif
return 1;
}
}
@ -242,6 +462,8 @@ uint32_t ibeacon_add(struct IBEACON *ib) {
return 0;
}
#ifndef USE_IBEACON_ESP32
void hm17_decode(void) {
struct IBEACON ib;
switch (hm17_cmd) {
@ -438,8 +660,16 @@ hm17_v110:
}
}
#endif
void IBEACON_loop() {
#ifdef USE_IBEACON_ESP32
return;
#else
if (!IBEACON_Serial) return;
uint32_t difftime=millis()-hm17_lastms;
@ -464,6 +694,8 @@ uint32_t difftime=millis()-hm17_lastms;
}
}
#endif
}
#ifdef USE_WEBSERVER
@ -523,7 +755,20 @@ bool xsns52_cmd(void) {
uint16_t len=XdrvMailbox.data_len;
if (len > 0) {
char *cp=XdrvMailbox.data;
if (*cp>='0' && *cp<='8') {
if (*cp=='u') {
cp++;
if (*cp) IB_UPDATE_TIME=atoi(cp);
Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME);
} else if (*cp=='t') {
cp++;
if (*cp) IB_TIMEOUT_TIME=atoi(cp);
Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME);
} else if (*cp=='c') {
for (uint32_t cnt=0;cnt<MAX_IBEACONS;cnt++) ibeacons[cnt].FLAGS=0;
Response_P(S_JSON_IBEACON1, XSNS_52,"clr list","");
}
#ifndef USE_IBEACON_ESP32
else if (*cp>='0' && *cp<='8') {
hm17_sendcmd(*cp&7);
Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7);
} else if (*cp=='s') {
@ -536,18 +781,8 @@ bool xsns52_cmd(void) {
IBEACON_Serial->write((uint8_t*)cp,len);
hm17_cmd=99;
Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp);
} else if (*cp=='u') {
cp++;
if (*cp) IB_UPDATE_TIME=atoi(cp);
Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME);
} else if (*cp=='t') {
cp++;
if (*cp) IB_TIMEOUT_TIME=atoi(cp);
Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME);
} else if (*cp=='c') {
for (uint32_t cnt=0;cnt<MAX_IBEACONS;cnt++) ibeacons[cnt].FLAGS=0;
Response_P(S_JSON_IBEACON1, XSNS_52,"clr list","");
}
#endif
#ifdef IBEACON_DEBUG
else if (*cp=='d') {
cp++;
@ -562,6 +797,8 @@ bool xsns52_cmd(void) {
}
#define D_CMND_IBEACON "IBEACON"
#ifndef USE_IBEACON_ESP32
//"IBEACON_FFFF3D1B1E9D_RSSI", Data "99" causes TAG to beep
bool ibeacon_cmd(void) {
ib_mac[0]=0;
@ -592,6 +829,8 @@ void ib_sendbeep(void) {
hm17_sendcmd(HM17_CON);
}
#endif
void ibeacon_mqtt(const char *mac,const char *rssi,const char *uid,const char *major,const char *minor) {
char s_mac[14];
char s_uid[34];
@ -636,19 +875,29 @@ bool Xsns52(byte function)
IBEACON_loop();
break;
case FUNC_EVERY_SECOND:
#ifdef USE_IBEACON_ESP32
esp32_every_second();
#else
hm17_every_second();
#endif
break;
case FUNC_COMMAND_SENSOR:
if (XSNS_52 == XdrvMailbox.index) {
result = xsns52_cmd();
}
break;
#ifndef USE_IBEACON_ESP32
case FUNC_COMMAND:
result=ibeacon_cmd();
break;
#endif
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
#ifndef USE_IBEACON_ESP32
if (hm17_found) IBEACON_Show();
#else
IBEACON_Show();
#endif
break;
#endif // USE_WEBSERVER
}

View File

@ -294,27 +294,27 @@ bool Xsns68Cmnd(void)
char sub_string[XdrvMailbox.data_len +1];
switch (XdrvMailbox.payload) {
case 1:
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.windmeter_radius = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
break;
case 2:
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.windmeter_pulses_x_rot = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
break;
case 3:
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.windmeter_pulse_debounce = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
break;
case 4:
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.windmeter_speed_factor = (int16_t)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 1000);
}
break;
case 5:
if (strstr(XdrvMailbox.data, ",") != nullptr) {
if (strchr(XdrvMailbox.data, ',') != nullptr) {
Settings.windmeter_tele_pchange = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
}
break;

View File

@ -168,7 +168,7 @@ a_setoption = [[
"Use friendly name in zigbee topic (use with SetOption89)",
"Set dimmer low on rotary dial after power off"
],[
"Detach Swiches from Relays and enable MQTT action state for all the SwitchModes",
"Detach Switches from Relays and enable MQTT action state for all the SwitchModes",
"","","",
"","","","",
"","","","",